// Shared libraries
import * as Util from '@dra2020/util';

// Format for efficient packing of multipolygon coordinates
//
// [n] number of polygons
// [n polygon headers]...
//  [n] number of rings
//    [n]... number of coordinates in ring
//  followed by [x,y]... for all the coordinates

export function polyPack(coords: any): any
{
  if (Util.depthof(coords) == 4) coords = [ coords ]; // normalize to multipolygon
  let nFloats: number = 2;  // for number of polygons and size of header block
  let i: number, j: number, k: number;
  let p: any, r: any;
  for (i = 0; i < coords.length; i++)
  {
    p = coords[i];
    nFloats++;  // For number of rings in this polygon
    for (j = 0; j < p.length; j++)
    {
      nFloats++;  // For number of coordinates in this ring
      r = p[j];
      nFloats += r.length * 2;  // for each x, y pair
    }
  }
  // Allocate typed buffer
  let ab = new ArrayBuffer(nFloats * 8);
  let af = new Float64Array(ab);

  // Fill in header
  let z: number = 0;
  af[z++] = coords.length;
  z++;  // fill in header size
  for (i = 0; i < coords.length; i++)
  {
    p = coords[i];
    af[z++] = p.length;
    for (j = 0; j < p.length; j++)
      af[z++] = p[j].length;
  }
  af[1] = z;

  // Fill in coords
  for (i = 0; i < coords.length; i++)
  {
    p = coords[i];
    for (j = 0; j < p.length; j++)
    {
      r = p[j];
      for (k = 0; k < r.length; k++)
      {
        af[z++] = r[k][0];
        af[z++] = r[k][1];
      }
    }
  }

  return af;
}

export function polyUnpack(buffer: any): any
{
  let i: number, j: number, k: number;
  let nPolys: number, nRings: number, nCoords: number;
  let p: any, r: any;
  let af: Float64Array = buffer as Float64Array;
  let coords: any = [];
  nPolys = af[0];
  let z = af[1];  // start of coordinates
  let h = 2;
  for (i = 0; i < nPolys; i++)
  {
    p = [];
    coords[i] = p;
    nRings = af[h++];
    for (j = 0; j < nRings; j++)
    {
      r = [];
      p[j] = r;
      nCoords = af[h++];
      for (k = 0; k < nCoords; k++)
        r[k] = [ af[z++], af[z++] ];
    }
  }

  return coords.length > 1 ? coords : coords[0];
}
