Program HelloWorld(output);
uses SysUtils;
Type  
  SIntArray = Array of Longint;

function bit_rol(const r: Longint; const t: Longint) : Longint;
var
  ret : Longint;
begin
    //writeln('bit_rol:',r,'-',t);
    ret := (r shl t) or (r shr (32-t));
    //writeln(ret);
    bit_rol := ret;
end;

function safe_add(const r: LongInt; const t: Longint): Longint;
var
e,n : Longint;
begin
    //writeln('safe_add:',r,' ',t);
    e := (65535 and r) + (65535 and t);
    n := (r shr 16) + (t shr 16) + (e shr 16);
    safe_add := n shl 16 or 65535 and e;
end;

function md5_cmn(const r: Longint; const t: Longint; const e: Longint; n : Longint; d : Longint; _ : Longint): Longint;
var
  ret : Longint;
begin
//writeln('md5_cmn:',r,' ',t,' ',e,' ',n,' ',d,' ',_);
 ret := safe_add(bit_rol(safe_add(safe_add(t, r), safe_add(n, _)), d), e);
 //writeln('md5_cmn ret:',ret);
 md5_cmn := ret 
end;

function md5_gg(const r: Longint; const t: Longint; const e: Longint; const n: Longint; const d: Longint;  const _: Longint; const a: Longint): Longint;
var
  ret : Longint;
begin
    //writeln('md5_gg:',r,' ',t,' ',e,' ',n,' ',d,' ',_,' ',a);
    //return md5_cmn(t & n | e & ~n, r, t, d, _, a)
    ret := md5_cmn((t and n) or (e and not(n)),r,t,d,_,a);
    //writeln('md5gg ret:',ret);
    md5_gg := ret;
end;

function md5_hh(const r: Longint; const t: Longint; const e: Longint; const n: Longint; const d: Longint;  const _: Longint; const a: Longint) : Longint;
var
  ret : Longint;
begin
   //writeln('md5_hh:',r,t,e,n,d,_,a);
    
    //return md5_cmn(t ^ e ^ n, r, t, d, _, a)
    ret := md5_cmn((t xor e xor n), r, t, d, _, a);
    //writeln('md5hh ret:',ret);
    md5_hh := ret;
end;

function md5_ii(const r: Longint; const t: Longint; const e: Longint; const n: Longint; const d: Longint;  const _: Longint; const a: Longint) : Longint;
var
  ret : Longint;
 begin
    //return md5_cmn(e ^ (t | ~n), r, t, d, _, a)
    ret := md5_cmn((e xor (t or not(n))), r, t, d, _, a);
    //writeln('md5_ii ret:',ret);
    md5_ii := ret;
end;
            
function md5_ff(const r: Longint; const t: Longint; const e: Longint; n : Longint; d : Longint; _ : Longint; a : Longint): Longint;
var 
ret: Longint;
begin
    //writeln('md5_ff in:', r,' ',t,' ',e,' ',n,' ',d,' ',_,' ',a);
    ret := md5_cmn(t and e or not(t) and n, r, t, d, _, a);
   //writeln('md5_ff ret:',ret);
    md5_ff := ret;
end;

function binl_md5(const rin: SIntArray; const t: integer) : SIntArray;
var 
e,n,d,_ : Longint;
m,f,h,i : Longint;
a : integer;
r,ret : SIntArray;

begin
SetLength(r,(Length(rin)+1));
for i := 0 to length(rin) do begin
  r[i]:= rin[i];
end;

writeln('binl_md5 inputs ',t,' ',Length(r));
for a:= 0 to Length(r)-1 do write(r[a],' ');
writeln('');
writeln(( ((t + 64) shr 9) shl 4)+14);
// r[t >> 5] |= 128 << t % 32,
r[t shr 5 ] := r[t shr 5 ] or (128 shl (t mod 32));
r[( ((t + 64) shr 9) shl 4)+14] := t;

//for a:= 0 to Length(r)-1 do write(r[a],' ');
//writeln('');

e := 1732584193;
n := -271733879;
d := -1732584194; 
_ := 271733878;

a:= 0;
while a < Length(r)-1 do
begin
   m := e;
   f := n;
   h := d;
   i := _;
  //writeln('A: ',a,' ',Length(r));
  //writeln('e:', e);
   e := md5_ff(e, n, d, _, r[a + 0], 7, -680876936);
    _:= md5_ff(_, e, n, d, r[a + 1], 12, -389564586);
	d := md5_ff(d, _, e, n, r[a + 2], 17, 606105819);
	n := md5_ff(n, d, _, e, r[a + 3], 22, -1044525330);
	e := md5_ff(e, n, d, _, r[a + 4], 7, -176418897);
	_ := md5_ff(_, e, n, d, r[a + 5], 12, 1200080426);
	d := md5_ff(d, _, e, n, r[a + 6], 17, -1473231341);
	n := md5_ff(n, d, _, e, r[a + 7], 22, -45705983);
	e := md5_ff(e, n, d, _, r[a + 8], 7, 1770035416);
	_ := md5_ff(_, e, n, d, r[a + 9], 12, -1958414417);
	d := md5_ff(d, _, e, n, r[a + 10], 17, -42063);
	n := md5_ff(n, d, _, e, r[a + 11], 22, -1990404162);
	e := md5_ff(e, n, d, _, r[a + 12], 7, 1804603682);
	_ := md5_ff(_, e, n, d, r[a + 13], 12, -40341101);
	d := md5_ff(d, _, e, n, r[a + 14], 17, -1502002290);
	n := md5_ff(n, d, _, e, r[a + 15], 22, 1236535329);
	e := md5_gg(e, n, d, _, r[a + 1], 5, -165796510);
	_ := md5_gg(_, e, n, d, r[a + 6], 9, -1069501632);
	d := md5_gg(d, _, e, n, r[a + 11], 14, 643717713);
	n := md5_gg(n, d, _, e, r[a + 0], 20, -373897302);
	e := md5_gg(e, n, d, _, r[a + 5], 5, -701558691);
	_ := md5_gg(_, e, n, d, r[a + 10], 9, 38016083);
	d := md5_gg(d, _, e, n, r[a + 15], 14, -660478335);
	n := md5_gg(n, d, _, e, r[a + 4], 20, -405537848);
	e := md5_gg(e, n, d, _, r[a + 9], 5, 568446438);
	_ := md5_gg(_, e, n, d, r[a + 14], 9, -1019803690);
	d := md5_gg(d, _, e, n, r[a + 3], 14, -187363961);
	n := md5_gg(n, d, _, e, r[a + 8], 20, 1163531501);
	e := md5_gg(e, n, d, _, r[a + 13], 5, -1444681467);
	_ := md5_gg(_, e, n, d, r[a + 2], 9, -51403784);
	d := md5_gg(d, _, e, n, r[a + 7], 14, 1735328473);
	n := md5_gg(n, d, _, e, r[a + 12], 20, -1926607734);
	e := md5_hh(e, n, d, _, r[a + 5], 4, -378558);
	_ := md5_hh(_, e, n, d, r[a + 8], 11, -2022574463);
	d := md5_hh(d, _, e, n, r[a + 11], 16, 1839030562);
	n := md5_hh(n, d, _, e, r[a + 14], 23, -35309556);
	e := md5_hh(e, n, d, _, r[a + 1], 4, -1530992060);
	_ := md5_hh(_, e, n, d, r[a + 4], 11, 1272893353);
	d := md5_hh(d, _, e, n, r[a + 7], 16, -155497632);
	n := md5_hh(n, d, _, e, r[a + 10], 23, -1094730640);
	e := md5_hh(e, n, d, _, r[a + 13], 4, 681279174);
	_ := md5_hh(_, e, n, d, r[a + 0], 11, -358537222);
	d := md5_hh(d, _, e, n, r[a + 3], 16, -722521979);
	n := md5_hh(n, d, _, e, r[a + 6], 23, 76029189);
	e := md5_hh(e, n, d, _, r[a + 9], 4, -640364487);
	_ := md5_hh(_, e, n, d, r[a + 12], 11, -421815835);
	d := md5_hh(d, _, e, n, r[a + 15], 16, 530742520);
	n := md5_hh(n, d, _, e, r[a + 2], 23, -995338651);
	e := md5_ii(e, n, d, _, r[a + 0], 6, -198630844);

	_ := md5_ii(_, e, n, d, r[a + 7], 10, 1126891415);
	d := md5_ii(d, _, e, n, r[a + 14], 15, -1416354905);
	n := md5_ii(n, d, _, e, r[a + 5], 21, -57434055);
	e := md5_ii(e, n, d, _, r[a + 12], 6, 1700485571);
	_ := md5_ii(_, e, n, d, r[a + 3], 10, -1894986606);
	d := md5_ii(d, _, e, n, r[a + 10], 15, -1051523);
	n := md5_ii(n, d, _, e, r[a + 1], 21, -2054922799);
	e := md5_ii(e, n, d, _, r[a + 8], 6, 1873313359);
	_ := md5_ii(_, e, n, d, r[a + 15], 10, -30611744);
	d := md5_ii(d, _, e, n, r[a + 6], 15, -1560198380);
	n := md5_ii(n, d, _, e, r[a + 13], 21, 1309151649);
	e := md5_ii(e, n, d, _, r[a + 4], 6, -145523070);
	_ := md5_ii(_, e, n, d, r[a + 11], 10, -1120210379);
	d := md5_ii(d, _, e, n, r[a + 2], 15, 718787259);
	n := md5_ii(n, d, _, e, r[a + 9], 21, -343485551);
                      
    e := safe_add(e, m);
    n := safe_add(n, f);
    d := safe_add(d, h);
    _ := safe_add(_, i);

   a := a + 16;

end;
    //return Array(e, n, d, _)
    SetLength(ret,4);
    ret[0] := e;
    ret[1] := n;
    ret[2] := d;
    ret[3] := _;
    writeln('binl_md5 output ', Length(ret));
    for a:= 0 to Length(ret)-1 do write(ret[a],' ');
    writeln('');
    binl_md5 := ret;

end;

function rstr2binl(const r: string) : SIntArray;
var 
   t : SIntArray;
   e,q,q1,q2 : Longint;
   loopnum : integer;
   //i : integer;
begin
   SetLength(t,(Length(r) shr 2));
   for e:= 0 to Length(t)-1 do t[e] := 0;
	//for (var t = Array(r.length >> 2), e = 0; e < t.length; e++)
	//	t[e] = 0;;
   e := 0;
   q := 0;
   q1 := 0;
   q2 := 0;
   loopnum := (8 * (Length(r))); // = 432
   while e < loopnum do 
	//for (var e = 0; e < 8 * r.length; e += 8)
	begin
	    
	//	t[e >> 5] |= (255 & r.charCodeAt(e / 8)) << e % 32;
	    q1 := ord(r[(round(e/8))+1]);
	    q2 := (e mod 32);
	    q := (255 and q1) shl q2;
        t[(e shr 5)] := t[(e shr 5)] or q;
	    e := e + 8;
	     
	    
	end;
    
   
    
	//return t
	//i :=0;
	//write('rstr2binl output: ');
     //while i < Length(t) do 
        //begin
        //  write(t[i],',');
        //  i := i + 1;
        //end;
       // writeln('');
    rstr2binl := t;
    //Result := IntToStr(ord(r[1]))
    //Result := r
end;

function binl2rstr(const r : SIntArray): SIntArray; 
var
    temp : SIntArray;
    e,i : integer;
    loc : integer;
begin
    //writeln('binl2rstr in');
    //for e:= 0 to Length(r)-1 do write(r[e],' ');
    //writeln('');
    
    //t := '';
    setLength(temp, 4* Length(r));
    e :=0;
    i :=0;
    //for (var t = "", e = 0; e < 32 * r.length; e += 8)
    while e < (32* Length(r)) do
    begin
        //t += String.fromCharCode(r[e >> 5] >>> e % 32 & 255);
        loc := (r[e shr 5] shr (e mod 32) and 255);
        temp[i] := loc;
        //temp := Concat(t, chr(55) );
        e := e+8;
        i := i+1;
    end;
    //return t
   //writeln('binl2rstr out: ', ' >>',Length(temp));
   //for e:= 0 to Length(temp)-1 do write((temp[e]),' ');
    //writeln('');
   binl2rstr := temp; 
end;

function rstr_md5(const r: string) : SIntArray;
var
  //ret : string;
  ret : SIntArray;
  a : integer;
begin

    writeln('rstr_md5 in : ',r);
    ret := binl2rstr(binl_md5(rstr2binl(r), 8 * Length(r)));
     writeln('rstr_md5 out:');
    for a:= 0 to Length(ret)-1 do write(ret[a],' ');
    writeln('');
    rstr_md5 := ret
    
end;

function rstr2b64(const r: SIntArray) : string;
var
e : string;
b64pad : string;
a,d,n : integer;
t : string;
_ : Longint;
atmp1,atmp2,atmp3 : Longint;
btmp1,btmp2 : Longint;

begin
  writeln('rstr2b64');
  for a:= 0 to Length(r)-1 do write(r[a],' ');
  writeln('');
  e := '';
  b64pad := '';
  
  t := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  n := Length(r);
  d := 0;
  //for (var t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", e = "", n = r.length, d = 0; d < n; d += 3)
  while d < n do
  begin
        atmp1 := (r[d]) shl 16;
        atmp2 := r[d + 1] << 8;
        atmp3 := r[d + 2];
        if (d + 1) < n then
            if (d + 2) < n then
                _ := atmp1 or (r[d + 1] << 8)  or  r[d + 2]
            else
                _ := atmp1 or (r[d + 1] << 8) or 0
        else
            if (d + 1) < n then
                _ := atmp1 or 0  or  r[d + 2]
            else
                _ := atmp1 or 0 or 0;
        
   // for (var _ = r.charCodeAt(d) << 16 | (d + 1 < n ? r.charCodeAt(d + 1) << 8 : 0) | (d + 2 < n ? r.charCodeAt(d + 2) : 0), a = 0; a < 4; a++)
        a :=0;
        while a < 4 do
        begin
    
            //e += 8 * d + 6 * a > 8 * r.length ? b64pad : t.charAt(_ >>> 6 * (3 - a) & 63);
            // condition ? val1 : val2
            
            if (((8 * d) + (6 * a)) > (8 * Length(r))) then
            begin
                e:=Concat(e,b64pad);
                //writeln('FALSE');
            end
            else
            begin
                btmp1 := (_ shr (6 * (3 -a))) and 63;
                //writeln('kk ',btmp1,' ? ',_,' ??? ',a ,' ',btmp1, ' ',e);
               // writeln(t[btmp1+1]);
                // t.charAt(_ >>> 6 * (3 - a) & 63);
                e:=Concat(e,t[btmp1+1]);
            end;
            //writeln(d,' ',a,' ',e);
            a := a+1;
        end;
  d := d + 3;
  end;

  //return e
  rstr2b64 := e;
end;

function TokenizedUrl(const urlbase: string; const rand_value: string; const usertoken: string) : String;
var
   ts: string;
   token: string;
   url_token: string;
   Result: string;
   
begin
   ts := '2082690000'; //May not need to be cacluated..
   token := 'BhFIjt4y2l01S4-lihFdGA';  // Must be cacluated still!
   
   
   //url_token := ts + GetBetween(urlbase, '.com', '?') + ' ' + usertoken; 
   //"2082690000/rastertiles_webclient/8/73/101.png NqxvZy8Wk"
   url_token := '2082690000/rastertiles_webclient/13/2298/3467.png NqxvZy8Wk';
  token := rstr2b64(rstr_md5(url_token));
 
  
// d = my_b64_md5(url_token);
// return d.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_")

    token := StringReplace(token, '=', '',[rfReplaceAll]);
	token := StringReplace(token, '+', '-',[rfReplaceAll]);
	token := StringReplace(token, '/', '_',[rfReplaceAll]);

    //Result := 'http://dd' + urlbase +'&ts='+ts +'&token='+ token
	Result := urlbase +'&ts='+ts +'&token='+ token;
	//http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/8/74/97.png?rand=1557512563&ts=2082690000&token=YBPw_7tkrUobc-rYzxjBPg
    TokenizedUrl := Result;
end;

var 
  final,usertoken,rand_value,base_url : string;
begin
  writeln('Hello, world!');
  //rstr_md5('2082690000/rastertiles_webclient/8/74/97.png NqxvZy8Wk');
  //final :=  
  //http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/13/2298/3467.png?rand=1557512563&ts=2082690000&token=4fJB1j5mckOOWefKXnIiNg
  //rstr2b64(rstr_md5('2082690000/rastertiles_webclient/13/2298/3467.png NqxvZy8Wk'));
  //writeln('Final:',final);
  
  usertoken := 'NqxvZy8Wk'; // Tuse GetUserToken()
  rand_value:= '1557512563'; // user to Grab from Webpage HTML
  base_url := 'http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/13/2298/3467.png?rand=1557512563';
  //http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/13/2298/3467.png?rand=1557512563&ts=2082690000&token=4fJB1j5mckOOWefKXnIiNg
  final := TokenizedUrl(base_url,rand_value,usertoken);
  
  writeln('Final:',final);
end.