// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// 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.

import { CompositeLayer, experimental } from '../../core';
const get = experimental.get;

import ScatterplotLayer from '../scatterplot-layer/scatterplot-layer';
import PathLayer from '../path-layer/path-layer';
// Use primitive layer to avoid "Composite Composite" layers for now
import SolidPolygonLayer from '../solid-polygon-layer/solid-polygon-layer';

import { getGeojsonFeatures, separateGeojsonFeatures } from './geojson';

const defaultLineColor = [0x0, 0x0, 0x0, 0xff];
const defaultFillColor = [0x0, 0x0, 0x0, 0xff];

const defaultProps = {
  stroked: true,
  filled: true,
  extruded: false,
  wireframe: false,

  lineWidthScale: 1,
  lineWidthMinPixels: 0,
  lineWidthMaxPixels: Number.MAX_SAFE_INTEGER,
  lineJointRounded: false,
  lineMiterLimit: 4,

  elevationScale: 1,

  pointRadiusScale: 1,
  pointRadiusMinPixels: 0, //  min point radius in pixels
  pointRadiusMaxPixels: Number.MAX_SAFE_INTEGER, // max point radius in pixels

  fp64: false,

  // Line and polygon outline color
  getLineColor: f => get(f, 'properties.lineColor') || defaultLineColor,
  // Point and polygon fill color
  getFillColor: f => get(f, 'properties.fillColor') || defaultFillColor,
  // Point radius
  getRadius: f => get(f, 'properties.radius') || get(f, 'properties.size') || 1,
  // Line and polygon outline accessors
  getLineWidth: f => get(f, 'properties.lineWidth') || 1,
  // Polygon extrusion accessor
  getElevation: f => get(f, 'properties.elevation') || 1000,

  subLayers: {
    PointLayer: ScatterplotLayer,
    LineLayer: PathLayer,
    PolygonLayer: SolidPolygonLayer
  },

  // Optional settings for 'lighting' shader module
  lightSettings: {}
};

const getCoordinates = f => f.geometry.coordinates;

export default class GeoJsonLayer extends CompositeLayer {
  initializeState() {
    this.state = {
      features: {}
    };
  }

  updateState({ oldProps, props, changeFlags }) {
    if (changeFlags.dataChanged) {
      const data = props.data;

      const features = getGeojsonFeatures(data);
      this.state.features = separateGeojsonFeatures(features);
    }
  }

  getPickingInfo({ info }) {
    return Object.assign(info, {
      // override object with picked feature
      object: info.object && info.object.feature || info.object
    });
  }

  /* eslint-disable complexity */
  renderLayers() {
    const features = this.state.features;
    const pointFeatures = features.pointFeatures,
          lineFeatures = features.lineFeatures,
          polygonFeatures = features.polygonFeatures,
          polygonOutlineFeatures = features.polygonOutlineFeatures;

    // Layer composition props

    var _props = this.props;
    const stroked = _props.stroked,
          filled = _props.filled,
          extruded = _props.extruded,
          wireframe = _props.wireframe,
          subLayers = _props.subLayers,
          lightSettings = _props.lightSettings;

    // Rendering props underlying layer

    var _props2 = this.props;
    const lineWidthScale = _props2.lineWidthScale,
          lineWidthMinPixels = _props2.lineWidthMinPixels,
          lineWidthMaxPixels = _props2.lineWidthMaxPixels,
          lineJointRounded = _props2.lineJointRounded,
          lineMiterLimit = _props2.lineMiterLimit,
          pointRadiusScale = _props2.pointRadiusScale,
          pointRadiusMinPixels = _props2.pointRadiusMinPixels,
          pointRadiusMaxPixels = _props2.pointRadiusMaxPixels,
          elevationScale = _props2.elevationScale,
          fp64 = _props2.fp64;

    // Accessor props for underlying layers

    var _props3 = this.props;
    const getLineColor = _props3.getLineColor,
          getFillColor = _props3.getFillColor,
          getRadius = _props3.getRadius,
          getLineWidth = _props3.getLineWidth,
          getElevation = _props3.getElevation,
          updateTriggers = _props3.updateTriggers;


    const drawPoints = pointFeatures && pointFeatures.length > 0;
    const drawLines = lineFeatures && lineFeatures.length > 0;
    const hasPolygonLines = polygonOutlineFeatures && polygonOutlineFeatures.length > 0;
    const hasPolygon = polygonFeatures && polygonFeatures.length > 0;

    // Filled Polygon Layer
    const polygonFillLayer = filled && hasPolygon && new subLayers.PolygonLayer(this.getSubLayerProps({
      id: 'polygon-fill',
      updateTriggers: {
        getElevation: updateTriggers.getElevation,
        getColor: updateTriggers.getFillColor
      }
    }), {
      data: polygonFeatures,
      fp64,
      extruded,
      elevationScale,
      wireframe: false,
      lightSettings,
      getPolygon: getCoordinates,
      getElevation,
      getColor: getFillColor
    });

    const polygonWireframeLayer = wireframe && extruded && hasPolygon && new subLayers.PolygonLayer(this.getSubLayerProps({
      id: 'polygon-wireframe',
      updateTriggers: {
        getElevation: updateTriggers.getElevation,
        getColor: updateTriggers.getLineColor
      }
    }), {
      data: polygonFeatures,

      fp64,
      extruded,
      elevationScale,
      wireframe: true,
      getPolygon: getCoordinates,
      getElevation,
      getColor: getLineColor
    });

    const polygonLineLayer = !extruded && stroked && hasPolygonLines && new subLayers.LineLayer(this.getSubLayerProps({
      id: 'polygon-outline',
      updateTriggers: {
        getColor: updateTriggers.getLineColor,
        getWidth: updateTriggers.getLineWidth
      }
    }), {
      data: polygonOutlineFeatures,

      fp64,
      widthScale: lineWidthScale,
      widthMinPixels: lineWidthMinPixels,
      widthMaxPixels: lineWidthMaxPixels,
      rounded: lineJointRounded,
      miterLimit: lineMiterLimit,

      getPath: getCoordinates,
      getColor: getLineColor,
      getWidth: getLineWidth
    });

    const pathLayer = drawLines && new subLayers.LineLayer(this.getSubLayerProps({
      id: 'line-paths',
      updateTriggers: {
        getColor: updateTriggers.getLineColor,
        getWidth: updateTriggers.getLineWidth
      }
    }), {
      data: lineFeatures,

      fp64,
      widthScale: lineWidthScale,
      widthMinPixels: lineWidthMinPixels,
      widthMaxPixels: lineWidthMaxPixels,
      rounded: lineJointRounded,
      miterLimit: lineMiterLimit,

      getPath: getCoordinates,
      getColor: getLineColor,
      getWidth: getLineWidth
    });

    const pointLayer = drawPoints && new subLayers.PointLayer(this.getSubLayerProps({
      id: 'points',
      updateTriggers: {
        getColor: updateTriggers.getFillColor,
        getRadius: updateTriggers.getRadius
      }
    }), {
      data: pointFeatures,

      fp64,
      radiusScale: pointRadiusScale,
      radiusMinPixels: pointRadiusMinPixels,
      radiusMaxPixels: pointRadiusMaxPixels,

      getPosition: getCoordinates,
      getColor: getFillColor,
      getRadius
    });

    return [
    // If not extruded: flat fill layer is drawn below outlines
    !extruded && polygonFillLayer, polygonWireframeLayer, polygonLineLayer, pathLayer, pointLayer,
    // If extruded: draw fill layer last for correct blending behavior
    extruded && polygonFillLayer];
  }
  /* eslint-enable complexity */
}

GeoJsonLayer.layerName = 'GeoJsonLayer';
GeoJsonLayer.defaultProps = defaultProps;
//# sourceMappingURL=geojson-layer.js.map