// 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 SolidPolygonLayer from '../solid-polygon-layer/solid-polygon-layer';
import PathLayer from '../path-layer/path-layer';
import * as Polygon from '../solid-polygon-layer/polygon';

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

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

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

  getPolygon: f => get(f, 'polygon'),
  // Polygon fill color
  getFillColor: f => get(f, 'fillColor') || defaultFillColor,
  // Point, line and polygon outline color
  getLineColor: f => get(f, 'lineColor') || defaultLineColor,
  // Line and polygon outline accessors
  getLineWidth: f => get(f, 'lineWidth') || 1,
  // Line dash array accessor
  getLineDashArray: null,
  // Polygon extrusion accessor
  getElevation: f => get(f, 'elevation') || 1000,

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

export default class PolygonLayer extends CompositeLayer {
  initializeState() {
    this.state = {
      paths: []
    };
  }

  updateState({ oldProps, props, changeFlags }) {
    const geometryChanged = changeFlags.dataChanged || changeFlags.updateTriggersChanged && (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getPolygon);

    if (geometryChanged) {
      var _props = this.props;
      const data = _props.data,
            getPolygon = _props.getPolygon;

      this.state.paths = [];
      data.forEach(object => {
        const complexPolygon = Polygon.normalize(getPolygon(object));
        complexPolygon.forEach(polygon => this.state.paths.push({
          path: polygon,
          object
        }));
      });
    }
  }

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

  /* eslint-disable complexity */
  renderLayers() {
    // Layer composition props
    var _props2 = this.props;
    const data = _props2.data,
          stroked = _props2.stroked,
          filled = _props2.filled,
          extruded = _props2.extruded,
          wireframe = _props2.wireframe,
          elevationScale = _props2.elevationScale;

    // Rendering props underlying layer

    var _props3 = this.props;
    const lineWidthScale = _props3.lineWidthScale,
          lineWidthMinPixels = _props3.lineWidthMinPixels,
          lineWidthMaxPixels = _props3.lineWidthMaxPixels,
          lineJointRounded = _props3.lineJointRounded,
          lineMiterLimit = _props3.lineMiterLimit,
          lineDashJustified = _props3.lineDashJustified,
          fp64 = _props3.fp64;

    // Accessor props for underlying layers

    var _props4 = this.props;
    const getFillColor = _props4.getFillColor,
          getLineColor = _props4.getLineColor,
          getLineWidth = _props4.getLineWidth,
          getLineDashArray = _props4.getLineDashArray,
          getElevation = _props4.getElevation,
          getPolygon = _props4.getPolygon,
          updateTriggers = _props4.updateTriggers,
          lightSettings = _props4.lightSettings;
    const paths = this.state.paths;


    const hasData = data && data.length > 0;

    // Filled Polygon Layer
    const polygonLayer = filled && hasData && new SolidPolygonLayer(this.getSubLayerProps({
      id: 'fill',
      updateTriggers: {
        getElevation: updateTriggers.getElevation,
        getColor: updateTriggers.getFillColor
      }
    }), {
      data,
      extruded,
      elevationScale,

      fp64,
      wireframe: false,

      getPolygon,
      getElevation,
      getColor: getFillColor,

      lightSettings
    });

    const polygonWireframeLayer = extruded && wireframe && hasData && new SolidPolygonLayer(this.getSubLayerProps({
      id: 'wireframe',
      updateTriggers: {
        getElevation: updateTriggers.getElevation,
        getColor: updateTriggers.getLineColor
      }
    }), {
      data,

      fp64,
      extruded: true,
      elevationScale,
      wireframe: true,

      getPolygon,
      getElevation,
      getColor: getLineColor
    });

    // Polygon line layer
    const polygonLineLayer = !extruded && stroked && hasData && new PathLayer(this.getSubLayerProps({
      id: 'stroke',
      updateTriggers: {
        getWidth: updateTriggers.getLineWidth,
        getColor: updateTriggers.getLineColor,
        getDashArray: updateTriggers.getLineDashArray
      }
    }), {
      data: paths,

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

      getPath: x => x.path,
      getColor: x => getLineColor(x.object),
      getWidth: x => getLineWidth(x.object),
      getDashArray: getLineDashArray && (x => getLineDashArray(x.object))
    });

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

PolygonLayer.layerName = 'PolygonLayer';
PolygonLayer.defaultProps = defaultProps;
//# sourceMappingURL=polygon-layer.js.map