// pooqRoman resource maker
//
// Copyright (c) 2021 Stephen P Spackman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Notes:
//
//////////////////////////////////////////////////////////////////////////////
/*                              ==ASSETS==                                  */

const heatshrink = require('heatshrink');

const enc = x => {
    const d = btoa(require("heatshrink").compress(x));
    var r = "'" + d.substr(0, 64);
    for (let i = 64; i < d.length; i += 64) r += "' +\n    '" + d.substr(i, 64);
    return r + "'";
};

const prepBitmap = (name, data) => {
    const image = Graphics.createImage(data);
    const raw = String.fromCharCode(image.width, image.height, 0x81, 0) + image.buffer;
    const x = `
const ${name}I = dec(${enc(raw)});
`;
    return x;
};

const prepFont = (name, data) => {
    const image = Graphics.createImage(data);
    const lengths = Uint8Array(256);
    const offsets = Uint16Array(256);
    const adjustments = Uint16Array(256);
    let min = Infinity, max = -Infinity;
    const lines = data.split('\n');
    let m;
    // This regexp is clearly suboptimal, but Espruino's regexp engine is really wonky
    // and doesn't process nested parentheses or alternation correctly.
    for (let i = 0; i < 5 && !(m = /^(<*)=([*\d]+)(=*)(>*)$/.exec(lines[i])); i++);
    if (!m) throw new Error('Missing or incorrect header');
    const desc = m[1].length, body = 1 + m[2].length + m[3].length, asc = m[4].length;
    const h = desc + body + asc;
    let width = m[2] == '*' ? null : +m[2];
    let c = null, o = 0;
    lines.forEach((line, l) => {
      m = /^(<*)(=)([*\d]*)(=*)(>*)$/.exec(line) || /^(<*)(-)(.)(-*)(>*)$/.exec(line);
      if (m) {
        const h = m[2] == '=';
        if (m[1].length > desc || h && m[1].length != desc)
          throw new Error('Invalid descender height at ' + l);
        if (m[2].length + m[3].length + m[4].length != body)
          throw new Error('Invalid body height at ' + l);
        if (m[5].length > asc || h && m[5].length != asc)
          throw new Error('Invalid ascender height at ' + l);
        if (c != null) {
          lengths[c] = l - o;
          if (width !== null && width !== lengths[c])
            throw new Error(
              `Character has width ${lengths[c]} != ${width} at ${offsets[c]}`
            );
          c = null
        }
        if (!h) {
          c = m[3].charCodeAt(0);
          if (c < min) min = c;
          if (c > max) max = c;
          o = l + 1;
          offsets[c] = l;
          adjustments[c] = m[1].length
        }
      }
    });
    const xoffs = Uint8Array(lines.length);
    const ypos = Uint16Array(lines.length);
    ypos.fill(0xffff);
    const w0 = lengths[min];
    let widths = '';
    for (c = min, o = 0; c <= max; c++) {
        for (i = 0, j = offsets[c]; i < lengths[c]; i++) {
            xoffs[j] = asc + body + adjustments[c] - 1;
            ypos[j++] = o++;
        }
        widths += String.fromCharCode(lengths[c]);
    }
    const raster = Graphics.createArrayBuffer(h, o, 1, {msb: true});
    const writer = Graphics.createCallback(
        image.width, image.height, 1,
        (x, y, col) => raster.setPixel(xoffs[y] - x, ypos[y], col)
    );
    writer.drawImage(image);
    if (width === null) width = `dec(${enc(widths)})`;
    const x = `const ${name}F = [
  dec(
    ${enc(raster.buffer)}
  ), ${min}, ${width}, ${h}
];`;
    return x;
};

res = `
const heatshrink = require('heatshrink');
const dec = x => E.toString(heatshrink.decompress(atob(x)));
`;

res += prepFont('romanParts', `
<=*==============
-a--------------
x              x
xx            xx
-b--------------
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
-c--------------
xx            xx
x              x
-d--------------
xx            xx
xx            xx
xx            xx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx
-e--------------
xx            xx
x           xxxx
<-f--------------
         xxxxxxxx
      xxxxxxxxxxx
   xxxxxxx     xx
 xxxxxx         x
xxxxx
 xxxxxx         x
   xxxxxxx     xx
      xxxxxxxxxxx
         xxxxxxxx
-g--------------
            xxxx
              xx
               x
-h--------------
               x
              xx
            xxxx
-i--------------
x           xxxx
xx            xx
-j--------------
xx            xx
xxx          xxx
xxxx        xxxx
xxxxxx    xxxxxx
xx xxxx  xxxx xx
x    xxxxxx    x
      xxxx
x    xxxxxx    x
xx xxxx  xxxx xx
xxxxxx    xxxxxx
xxxx        xxxx
xxx          xxx
xx            xx
-k--------------
x              x
<-l--------------
        xx      x
     xxxxxx    xx
   xxxx xxxx  xxx
 xxxx   xx xxxx x
xxx         xx
 xxxx   xx xxxx x
   xxxx xxxx  xxx
     xxxxxx    xx
        xx      x
-m--------------
x      xx      x
xx    xxxx    xx
xxx  xxxxxx  xxx
x xxxx xx xxxx x
   xx      xx
x xxxx xx xxxx x
xxx  xxxxxx  xxx
xx    xxxx    xx
x      xx      x
-n--------------
    xxxxxxxx
  xxxxxxxxxxxx
 xxxx      xxxx
xxxx        xxxx
xxx          xxx
xx    xxxx    xx
xx    xxxx    xx
xxx          xxx
xxxx        xxxx
 xxxx      xxxx
  xxxxxxxxxxxx
    xxxxxxxx
<=*==============
`);

res += prepFont('font', `
<<<<=*======>>>>
- ------

-.------
xx
xx
-0------>>>>
  xxxxxxxx
 xxxxxxxxxx
xxx      xxx
xx        xx
xx        xx
xxx      xxx
 xxxxxxxxxx
  xxxxxxxx

-1------>>>>
xx       x
xx       xx
xxxxxxxxxxxx
xxxxxxxxxxxx
xx
xx

-2------>>>>
x        x
xx       xx
xxx      xxx
xxxx      xx
xxxxx     xx
xx xxx   xxx
xx  xxxxxxx
xx   xxxxx

-3------>>>>
  x       xx
 xx   x   xx
xxx   xx  xx
xx    xxx xx
xx    xxxxxx
xxx  xxx xxx
 xxxxxx   xx
  xxx      x

-4------>>>>
   x
   xx
   xxxx
   xxxxxxxxx
xxxxx  xxxxx
xxxxx
   xx
   xx

-5------>>>>
  x   xxxxxx
 xx   xxxxxx
xxx   xx  xx
xx    xx  xx
xx    xx  xx
xxx  xxx  xx
 xxxxxx   xx
  xxxx

-6------>>>>
  xxxx
 xxxxxxx
xxx  xxxxx
xx    xxxxx
xx    xx xxx
xxx  xxx  xx
 xxxxxx    x
  xxxx

-7------>>>>
          xx
          xx
xxxx      xx
xxxxxx    xx
    xxxx  xx
      xxxxxx
        xxxx
           x

-8------>>>>
  xxx  xxx
 xxxxxxxxxx
xxx xxxx xxx
xx   xx   xx
xx   xx   xx
xxx xxxx xxx
 xxxxxxxxxx
  xxx  xxx

-9------>>>>
      xxxx
x    xxxxxx
xx  xxx  xxx
xxx xx    xx
 xxxxx    xx
  xxxxx  xxx
    xxxxxxx
      xxx

-A------>>>>
xx
xxxxx
 xxxxxxx
   xxxxxxx
   xx   xxxx
   xxxxxxx
 xxxxxxx
xxxxx
xx

-D------>>>>
xx        xx
xxxxxxxxxxxx
xxxxxxxxxxxx
xx        xx
xx        xx
xxx      xxx
 xxxxxxxxxx
  xxxxxxxx

-F------>>>>
xxxxxxxxxxxx
xxxxxxxxxxxx
     xx   xx
     xx   xx
     xx   xx
          xx
-I------>>>>
xxxxxxxxxxxx
xxxxxxxxxxxx

-J------>>>>
  xx
 xxx      xx
xxx       xx
xx        xx
xxx       xx
 xxxxxxxxxxx
  xxxxxxxxxx
          xx
-M------>>>>
xxxxxxxxxxxx
xxxxxxxxxxx
       xxx
     xxxx
     xxxx
       xxx
xxxxxxxxxxx
xxxxxxxxxxxx

-N------>>>>
xxxxxxxxxxxx
xxxxxxxxxxx
       xxx
     xxx
    xxx
  xxx
 xxxxxxxxxxx
xxxxxxxxxxxx

-O------>>>>
  xxxxxxxx
 xxxxxxxxxx
xxx      xxx
xx        xx
xx        xx
xxx      xxx
 xxxxxxxxxx
  xxxxxxxx

-S------>>>>
  x    xxx
 xx   xxxxx
xxx   xx xxx
xx   xx   xx
xx   xx   xx
xxx xx   xxx
 xxxxx   xx
  xxx    x

-T------>>>>
          xx
          xx
          xx
xxxxxxxxxxxx
xxxxxxxxxxxx
          xx
          xx
          xx
-V------>>>>
         xxx
      xxxxxx
   xxxxx
xxxxx
   xxxxx
      xxxxxx
         xxx

-W------>>>>
        xxxx
    xxxxxxxx
xxxxxxxx
  xxxx
    xxxx
  xxxx
xxxxxxxx
    xxxxxxxx
        xxxx
-X------>>>>
xx        xx
xxx      xxx
  xxx  xxx
    xxxx
    xxxx
  xxx  xxx
xxx      xxx
xx        xx

-a------
 xxx
xxxxx x
xx xx xx
xx xx xx
xx xx xx
 xxxxxx
xxxxxx

-b------>>>>
xxxxxxxxxxxx
 xxxxxxxxxxx
xx    xx
xx    xx
xxx  xxx
 xxxxxx
  xxxx

-c------
  xxxx
 xxxxxx
xxx  xxx
xx    xx
xx    xx
 xx  xx
  x  x

-d------>>>>
  xxxx
 xxxxxx
xxx  xxx
xx    xx
xx    xx
 xxxxxxxxxxx
xxxxxxxxxxxx

-e------
  xxxx
 xxxxxx
xx xx xx
xx xx xx
xx xx xx
 x xxxx
   xxx

<<<<-g------
  x   xxxx
 xx  xxxxxx
xx  xxx  xxx
xx  xx    xx
xxx xx   xxx
 xxxxxxxxxx
   xxxxxxxxx

-h------>>>>
xxxxxxxxxxxx
xxxxxxxxxxxx
     xx
      xx
     xxx
xxxxxxx
xxxxxx

-i------>>>>
xxxxxxxx xx
xxxxxxxx xx

-l------>>>>
xxxxxxxxxxxx
xxxxxxxxxxxx

-m------
xxxxxxxx
xxxxxxx
     xxx
     xxx
xxxxxxx
xxxxxxx
     xxx
     xxx
xxxxxxx
xxxxxx

-n------
xxxxxxxx
xxxxxxx
     xxx
      xx
     xxx
xxxxxxx
xxxxxx

-o------
  xxxx
 xxxxxx
xxx  xxx
xx    xx
xxx  xxx
 xxxxxx
  xxxx

<<<<-p------
xxxxxxxxxxxx
xxxxxxxxxxx
    xx    xx
    xx    xx
    xxx  xxx
     xxxxxx
      xxxx

-r------
xxxxxxxx
xxxxxxx
     xxx
      xx
      xx
     xx

-s------
 x  xxx
xx xxxxx
xx xx xx
xx xx xx
xxxxx xx
 xxx  x

-t------>>>>
      xx
  xxxxxxxxx
 xxxxxxxxxx
xxx   xx
xx    xx
xx    xx
 xx

-u------
  xxxxxx
 xxxxxxx
xxx
xx
xxx
 xxxxxxx
xxxxxxxx

-v------
      xx
    xxxx
  xxxx
xxxx
  xxxx
    xxxx
      xx

<<<<-y------
  x   xxxxxx
 xx  xxxxxxx
xx  xxx
xx  xx
xxx xxx
 xxxxxxxxxxx
   xxxxxxxxx

<<<<=*======>>>>
`);

res += prepBitmap('lock', `
      xxxxxx
     xxxxxxxx
    xxx    xxx
   xxx      xxx
   xxx      xxx
   xxx      xxx
   xxx      xxx
 xxxxxxxxxxxxxxxx
 xxxxxxxxxxxxxxxx
 xxx          xxx
 xxxxxxxxxxxxxxxx
 xxxxxxxxxxxxxxxx
 xxx          xxx
 xxxxxxxxxxxxxxxx
 xxxxxxxxxxxxxxxx
 xxx          xxx
 xxxxxxxxxxxxxxxx
 xxxxxxxxxxxxxxxx
`);

res += prepBitmap('battery', `
       xxxx
       xxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
   xxxxxxxxxxxx
`);

res += prepBitmap('charge', `
          x
         xx
        xx
       xxx
      xxx
     xxxxxxxxx
    xxxxxxxxx
         xxx
        xxx
        xx
       xx
       x
`);

res += prepBitmap('GPS', `
    x
   x x
  x   x
   x   x
    x x  xxxx
     x  xxxxx 
       xxxxxx
        xxxxx
     x   xxx  x
   x x    x  x x
 x x  x     x   x
 x x   xx    x   x
 x  x         x x
  x  xxx       x
   x
    xxx
`);

res += prepBitmap('HRM', `
  xxxx     xxxx
 xxxxxx   xxxxxx
 xx xxxx xxx xxx
xxx xxxxxxxx xxxx
xxx xxxxxxxx xxxx
xxx xxxxxxxx xxxx
xx  xxxxxxx  xxxx
xx  xx xxxx  xx x
 xx   x    x   x
 xx xxxxxxxx xxx
  xxxxxxxxxxxxx
   xxxxxxxxxxx
    xxxxxxxxx
     xxxxxxx
      xxxxx
       xxx
        x
`);

res += prepBitmap('compass', `
      xxxxx
    xxxxxxxxx
   xxx  x  xxx
  xx    x    xx
 xx     x     xx
 xx    xxx    xx
xx     xxx     xx
xx     xxx     xx
xx     xxx     xx
xx    xx xx    xx
xx    xx xx    xx
 xx   x   x   xx
 xx   x   x   xx
  xx         xx
   xxx     xxx
    xxxxxxxxx
      xxxxx
`);

print(res);
