import * as THREE from 'three'
import { Map$1, Coordinate, MultiPolygon, Polygon } from './featuresToPolygon'


let procssMap = new Map$1(null, {
  center: [0, 0]
})

function sign(x) {
  if (Math.sign) {
    return Math.sign(x);
  }

  x = +x;

  if (x === 0 || isNaN(x)) {
    return Number(x);
  }

  return x > 0 ? 1 : -1;
}

function getAmount(amount, map) {
  let zoom = map.maxNativeZoom
  let center = procssMap.getCenter();
  let target = procssMap.locate(center, amount, amount);
  let p0 = procssMap.coordinateToPoint(center, zoom);
  let p1 = procssMap.coordinateToPoint(target, zoom);
  var x = Math.abs(p1.x - p0.x) * sign(amount);
  var y = Math.abs(p1.y - p0.y) * sign(amount);
  return new THREE.Vector3(x, y, 0).x;
}

function coordinateToVector3(coordinate, map) {
  var z = 0;
  var p = procssMap.coordinateToPoint(coordinate, map.maxNativeZoom)
  return new THREE.Vector3(p.x, p.y, -z);
};

function toShape(polygon, map) {
  var center = polygon.getCenter();
  var centerPt = coordinateToVector3(center, map);
  
  var shell = polygon.getShell();
  var outer = shell.map(function (c) {
    return coordinateToVector3(c, map).sub(centerPt);
  });
  var shape = new THREE.Shape(outer);
  var holes = polygon.getHoles();

  if (holes && holes.length > 0) {
    shape.holes = holes.map(function (item) {
      var pts = item.map(function (c) {
        return coordinateToVector3(c, map).sub(centerPt);
      });
      return new THREE.Shape(pts);
    });
  }

  return shape;
};

function toExtrudeGeometry(polygon, map, height) {
  if (!polygon || !(polygon instanceof MultiPolygon || polygon instanceof Polygon)) {
    return null;
  }

  if (polygon instanceof MultiPolygon) {
    return polygon.getGeometries().map(c =>
      toExtrudeGeometry(c, map, height)
    );
  }

  var shape = toShape(polygon, map);
  var center = coordinateToVector3(polygon.getCenter(), map);
  var amount = getAmount(height, map);
  
  var geom = new THREE.ExtrudeGeometry(shape, { 'depth': amount, 'bevelEnabled': false });

  var vertices = geom.vertices
  var vlength = vertices.length

  for (let i = 0; i < vlength; i += 1) {
    vertices[i].x += center.x
    vertices[i].y += center.y
    vertices[i].z += -amount
  }

  return geom
}

function reductive(map) {
  procssMap.setCenter(new Coordinate(map.center))
  // procssMap.width = map.size.width
  // procssMap.height = map.size.height
  // procssMap.setBearing(map.bearing)
  // procssMap.setFov(map.fov)
  // procssMap.setMaxZoom(map.maxZoom)
  // procssMap.setMinZoom(map.minZoom)
  // procssMap.setPitch(map.pitch)
  // procssMap.setSpatialReference(map.spatialReference)
}

function LatLngToPoint({ lat, lng }, map) {
  var coord = new Coordinate({ x: lat, y: lng });
  var center = coordinateToVector3(coord, map);

  return center
}

export {
  reductive,
  toExtrudeGeometry,
  LatLngToPoint
}