
var
 debug : boolean;
 gdebug : string;
// **********
// Functions to create tokens needed in URL
// **********
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);
    Result := 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);
    Result := 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);
 Result := 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);
    Result := 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);
    Result := 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);
    Result := 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);
    Result := 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)+2));
SetLength(r,( ((t + 64) shr 9) shl 4)+14+2);
for i := 0 to length(rin)-1 do begin
  r[i]:= rin[i];
end;

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

// 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
// In the loop below it doesn't like the +15 ...,
begin
   m := e;
   f := n;
   h := d;
   i := _;
  //writeln('A: ',a,' ',Length(r));
  //writeln('e:', e);
  gdebug := gdebug + 'Length(r):' + inttostr(Length(r));
  gdebug := gdebug + ' a:' + inttostr(a) + ' r[15]:' + inttostr(r[15]);
  if not(debug) then begin
   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);

   end;
   a := a + 16;

end;
    //return Array(e, n, d, _)
    SetLength(ret,4);
    ret[0] := e;
    ret[1] := n;
    ret[2] := d;
    ret[3] := _;
    Result := 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)+1);  // may need a +1...
   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;
    

    Result := t;

end;

function binl2rstr(const r : SIntArray): SIntArray; 
var
    temp : SIntArray;
	e : Longint;
    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('');
   Result := temp; 
end;

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

//	return binl2rstr(binl_md5(rstr2binl(r), 8 * r.length))
    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('');
    Result := ret
    
end;

function rstr2b64(const r: SIntArray) : string;
var
e : string;
b64pad : string;
a,d,n : integer;
t : string;
_ : Longint;
atmp1 : 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;
        if (d + 1) < n then
            if (d + 2) < n then
                _ := atmp1 or (r[d + 1] shl 8)  or  r[d + 2]
            else
                _ := atmp1 or (r[d + 1] shl 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);
				e:=e;
                //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:= e + t[btmp1+1];
				//e:=Concat(e,t[btmp1+1]);
            end;
            //writeln(d,' ',a,' ',e);
            a := a+1;
        end;
  d := d + 3;
  end;

  //return e
  Result := e;
end;


function TokenizedUrl(const urlbase: string; const rand_value: string; const usertoken: string) : String;
var
   ts: string;
   token: string;
   url_token: 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"
   
  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
end;


// **********
// Set of Functions to get user Token
// Note these functions are not finished - just
//   placeholders.. (left as is as things work for now..)
// **********
function HexStrToInt(const str: string): Integer;
begin
  Result := StrToInt('$' + str);
end;

function Convertblob(const str: string) : String;
var
    c: String;
    a: integer;
begin
    a := 2
    while a > 0 do
    begin
        c := str[a]
        c := chr(HexStrToInt('1B') xor 96)  + 'd'
        Result := c
        a := a -1
    end;
end;

function GetUserToken() : String;
var
   url: String;
begin
   url := 'http://fishing-app.gpsnauticalcharts.com/i-boating-fishing-web-app/emdec_web.json?rand=1557512563'
   // Get data from URL
   // Convert blob
   // extract UserToken
   Result := 'NqxvZy8Wk' // Hard coded for now. Should get from above URL.
end;


// **********
// Our Main Downloader Code
// **********
var
  base_url: string;
  rand_value : string;
  usertoken: string;
begin

     debug := false;
    // First get the url tokens we need.
    if ScriptBuffer <> '' then 
    begin
		usertoken := GetBetween(ScriptBuffer, 'usertoken', ';');
		rand_value := GetBetween(ScriptBuffer, 'rand_value', ';');
    end else 
    begin
		usertoken := 'NqxvZy8Wk' // Temp during testing - should use GetUserToken()
		rand_value:= '1557512563' // Temp during testing - should get from Params file for user to Grab from Webpage HTML
		//ScriptBuffer := '';
		ScriptBuffer := 'usertoken' + usertoken + ';' + 'rand_value' + rand_value + ';';
   end;

//n = "2082690000/rastertiles_webclient/8/73/101.png NqxvZy8Wk"
     
   base_url := GetURLBase + inttostr(GetZ-1) + '/' + inttostr(GetX) +'/'+inttostr(GetY)+'.png?rand=' + Rand_value
 
   //ResultURL := base_url
   ResultURL := TokenizedUrl(base_url,rand_value,usertoken)
      //http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/8/74/98.png?rand=1557512563&ts=2082690000&token=QcWTFFh6bkqc7beG_6Y7Cw
   if debug then ResultURL := gdebug;   


end.

// *************************************************
//  Notes from Devevlopment & 
//          Refrence JavaScript Code used on Webpage
// *************************************************
//
// Typical URLs  (Base+Variable):
// http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/
//          14/4716/5934.png?rand=1557512563&ts=2082690000&token=BhFIjt4y2l01S4-lihFdGA
//          12/1180/1481.png?rand=1557512563&ts=2082690000&token=s-OmQ84bgtz5dhRhIARVPQ
//          12/1181/1475.png?rand=1557512563&ts=2082690000&token=LAXqtp9YLXSrhvquWAQJtQ
//          9/147/204.png?rand=1557512563&ts=2082690000&token=KvNlh4PjGzrjZLeu5v6fDg
//
// Base portion: http://fishing-app.gpsnauticalcharts.com/rastertiles_webclient/
//  z/x/y.png
//  seems constant: rand=1557512563
//  calculated ts=2082690000  (calculate in Javascript, but I haven't seen change due to date in tokenizedUrl() below )
//  calculated token=BhFIjt4y2l01S4-lihFdGA   (in Javascript tokenizedUrl)
//
//
// *************
//  Associated Code from Webpage
// *************
//
// Can be found in .js script alongside this file.