import { COORDINATE_SYSTEM } from '../../lib/constants';
import { getOffsetOrigin } from './viewport-uniforms';
import WebMercatorViewport from '../../viewports/web-mercator-viewport';
import { vec3, vec4 } from '@math.gl/core';
import { addMetersToLngLat } from '@math.gl/web-mercator';
const DEFAULT_COORDINATE_ORIGIN = [0, 0, 0];

function lngLatZToWorldPosition(lngLatZ, viewport, offsetMode = false) {
  const p = viewport.projectPosition(lngLatZ);

  if (offsetMode && viewport instanceof WebMercatorViewport) {
    const [longitude, latitude, z = 0] = lngLatZ;
    const distanceScales = viewport.getDistanceScales([longitude, latitude]);
    p[2] = z * distanceScales.unitsPerMeter[2];
  }

  return p;
}

function normalizeParameters(opts) {
  const {
    viewport,
    modelMatrix,
    coordinateOrigin
  } = opts;
  let {
    coordinateSystem,
    fromCoordinateSystem,
    fromCoordinateOrigin
  } = opts;

  if (coordinateSystem === COORDINATE_SYSTEM.DEFAULT) {
    coordinateSystem = viewport.isGeospatial ? COORDINATE_SYSTEM.LNGLAT : COORDINATE_SYSTEM.CARTESIAN;
  }

  if (fromCoordinateSystem === undefined) {
    fromCoordinateSystem = coordinateSystem;
  }

  if (fromCoordinateOrigin === undefined) {
    fromCoordinateOrigin = coordinateOrigin;
  }

  return {
    viewport,
    coordinateSystem,
    coordinateOrigin,
    modelMatrix,
    fromCoordinateSystem,
    fromCoordinateOrigin
  };
}

export function getWorldPosition(position, {
  viewport,
  modelMatrix,
  coordinateSystem,
  coordinateOrigin,
  offsetMode
}) {
  let [x, y, z = 0] = position;

  if (modelMatrix) {
    [x, y, z] = vec4.transformMat4([], [x, y, z, 1.0], modelMatrix);
  }

  switch (coordinateSystem) {
    case COORDINATE_SYSTEM.LNGLAT:
      return lngLatZToWorldPosition([x, y, z], viewport, offsetMode);

    case COORDINATE_SYSTEM.LNGLAT_OFFSETS:
      return lngLatZToWorldPosition([x + coordinateOrigin[0], y + coordinateOrigin[1], z + (coordinateOrigin[2] || 0)], viewport, offsetMode);

    case COORDINATE_SYSTEM.METER_OFFSETS:
      return lngLatZToWorldPosition(addMetersToLngLat(coordinateOrigin, [x, y, z]), viewport, offsetMode);

    case COORDINATE_SYSTEM.CARTESIAN:
    default:
      return viewport.isGeospatial ? [x + coordinateOrigin[0], y + coordinateOrigin[1], z + coordinateOrigin[2]] : viewport.projectPosition([x, y, z]);
  }
}
export function projectPosition(position, params) {
  const {
    viewport,
    coordinateSystem,
    coordinateOrigin,
    modelMatrix,
    fromCoordinateSystem,
    fromCoordinateOrigin
  } = normalizeParameters(params);
  const {
    autoOffset = true
  } = params;
  const {
    geospatialOrigin = DEFAULT_COORDINATE_ORIGIN,
    shaderCoordinateOrigin = DEFAULT_COORDINATE_ORIGIN,
    offsetMode = false
  } = autoOffset ? getOffsetOrigin(viewport, coordinateSystem, coordinateOrigin) : {};
  const worldPosition = getWorldPosition(position, {
    viewport,
    modelMatrix,
    coordinateSystem: fromCoordinateSystem,
    coordinateOrigin: fromCoordinateOrigin,
    offsetMode
  });

  if (offsetMode) {
    const positionCommonSpace = viewport.projectPosition(geospatialOrigin || shaderCoordinateOrigin);
    vec3.sub(worldPosition, worldPosition, positionCommonSpace);
  }

  return worldPosition;
}
//# sourceMappingURL=project-functions.js.map