/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import * as zrUtil from 'zrender/src/core/util';
import RoamController from './RoamController';
import * as roamHelper from '../../component/helper/roamHelper';
import { onIrrelevantElement } from '../../component/helper/cursorHelper';
import * as graphic from '../../util/graphic';
import geoSourceManager from '../../coord/geo/geoSourceManager';
import { getUID } from '../../util/component';

function getFixedItemStyle(model, scale) {
  var itemStyle = model.getItemStyle();
  var areaColor = model.get('areaColor'); // If user want the color not to be changed when hover,
  // they should both set areaColor and color to be null.

  if (areaColor != null) {
    itemStyle.fill = areaColor;
  }

  return itemStyle;
}

function updateMapSelectHandler(mapDraw, mapOrGeoModel, regionsGroup, api, fromView) {
  regionsGroup.off('click');
  regionsGroup.off('mousedown');

  if (mapOrGeoModel.get('selectedMode')) {
    regionsGroup.on('mousedown', function () {
      mapDraw._mouseDownFlag = true;
    });
    regionsGroup.on('click', function (e) {
      if (!mapDraw._mouseDownFlag) {
        return;
      }

      mapDraw._mouseDownFlag = false;
      var el = e.target;

      while (!el.__regions) {
        el = el.parent;
      }

      if (!el) {
        return;
      }

      var action = {
        type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect',
        batch: zrUtil.map(el.__regions, function (region) {
          return {
            name: region.name,
            from: fromView.uid
          };
        })
      };
      action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id;
      api.dispatchAction(action);
      updateMapSelected(mapOrGeoModel, regionsGroup);
    });
  }
}

function updateMapSelected(mapOrGeoModel, regionsGroup) {
  // FIXME
  regionsGroup.eachChild(function (otherRegionEl) {
    zrUtil.each(otherRegionEl.__regions, function (region) {
      otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal');
    });
  });
}
/**
 * @alias module:echarts/component/helper/MapDraw
 * @param {module:echarts/ExtensionAPI} api
 * @param {boolean} updateGroup
 */


function MapDraw(api, updateGroup) {
  var group = new graphic.Group();
  /**
   * @type {string}
   * @private
   */

  this.uid = getUID('ec_map_draw');
  /**
   * @type {module:echarts/component/helper/RoamController}
   * @private
   */

  this._controller = new RoamController(api.getZr());
  /**
   * @type {Object} {target, zoom, zoomLimit}
   * @private
   */

  this._controllerHost = {
    target: updateGroup ? group : null
  };
  /**
   * @type {module:zrender/container/Group}
   * @readOnly
   */

  this.group = group;
  /**
   * @type {boolean}
   * @private
   */

  this._updateGroup = updateGroup;
  /**
   * This flag is used to make sure that only one among
   * `pan`, `zoom`, `click` can occurs, otherwise 'selected'
   * action may be triggered when `pan`, which is unexpected.
   * @type {booelan}
   */

  this._mouseDownFlag;
  /**
   * @type {string}
   */

  this._mapName;
  /**
   * @type {boolean}
   */

  this._initialized;
  /**
   * @type {module:zrender/container/Group}
   */

  group.add(this._regionsGroup = new graphic.Group());
  /**
   * @type {module:zrender/container/Group}
   */

  group.add(this._backgroundGroup = new graphic.Group());
}

MapDraw.prototype = {
  constructor: MapDraw,
  draw: function (mapOrGeoModel, ecModel, api, fromView, payload) {
    var isGeo = mapOrGeoModel.mainType === 'geo'; // Map series has data. GEO model that controlled by map series
    // will be assigned with map data. Other GEO model has no data.

    var data = mapOrGeoModel.getData && mapOrGeoModel.getData();
    isGeo && ecModel.eachComponent({
      mainType: 'series',
      subType: 'map'
    }, function (mapSeries) {
      if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) {
        data = mapSeries.getData();
      }
    });
    var geo = mapOrGeoModel.coordinateSystem;

    this._updateBackground(geo);

    var regionsGroup = this._regionsGroup;
    var group = this.group;
    var scale = geo.scale;
    var transform = {
      position: geo.position,
      scale: scale
    }; // No animation when first draw or in action

    if (!regionsGroup.childAt(0) || payload) {
      group.attr(transform);
    } else {
      graphic.updateProps(group, transform, mapOrGeoModel);
    }

    regionsGroup.removeAll();
    var itemStyleAccessPath = ['itemStyle'];
    var hoverItemStyleAccessPath = ['emphasis', 'itemStyle'];
    var labelAccessPath = ['label'];
    var hoverLabelAccessPath = ['emphasis', 'label'];
    var nameMap = zrUtil.createHashMap();
    zrUtil.each(geo.regions, function (region) {
      // Consider in GeoJson properties.name may be duplicated, for example,
      // there is multiple region named "United Kindom" or "France" (so many
      // colonies). And it is not appropriate to merge them in geo, which
      // will make them share the same label and bring trouble in label
      // location calculation.
      var regionGroup = nameMap.get(region.name) || nameMap.set(region.name, new graphic.Group());
      var compoundPath = new graphic.CompoundPath({
        segmentIgnoreThreshold: 1,
        shape: {
          paths: []
        }
      });
      regionGroup.add(compoundPath);
      var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;
      var itemStyleModel = regionModel.getModel(itemStyleAccessPath);
      var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath);
      var itemStyle = getFixedItemStyle(itemStyleModel, scale);
      var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel, scale);
      var labelModel = regionModel.getModel(labelAccessPath);
      var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath);
      var dataIdx; // Use the itemStyle in data if has data

      if (data) {
        dataIdx = data.indexOfName(region.name); // Only visual color of each item will be used. It can be encoded by dataRange
        // But visual color of series is used in symbol drawing
        //
        // Visual color for each series is for the symbol draw

        var visualColor = data.getItemVisual(dataIdx, 'color', true);

        if (visualColor) {
          itemStyle.fill = visualColor;
        }
      }

      zrUtil.each(region.geometries, function (geometry) {
        if (geometry.type !== 'polygon') {
          return;
        }

        compoundPath.shape.paths.push(new graphic.Polygon({
          segmentIgnoreThreshold: 1,
          shape: {
            points: geometry.exterior
          }
        }));

        for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); i++) {
          compoundPath.shape.paths.push(new graphic.Polygon({
            segmentIgnoreThreshold: 1,
            shape: {
              points: geometry.interiors[i]
            }
          }));
        }
      });
      compoundPath.setStyle(itemStyle);
      compoundPath.style.strokeNoScale = true;
      compoundPath.culling = true; // Label

      var showLabel = labelModel.get('show');
      var hoverShowLabel = hoverLabelModel.get('show');
      var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx));
      var itemLayout = data && data.getItemLayout(dataIdx); // In the following cases label will be drawn
      // 1. In map series and data value is NaN
      // 2. In geo component
      // 4. Region has no series legendSymbol, which will be add a showLabel flag in mapSymbolLayout

      if (isGeo || isDataNaN && (showLabel || hoverShowLabel) || itemLayout && itemLayout.showLabel) {
        var query = !isGeo ? dataIdx : region.name;
        var labelFetcher; // Consider dataIdx not found.

        if (!data || dataIdx >= 0) {
          labelFetcher = mapOrGeoModel;
        }

        var textEl = new graphic.Text({
          position: region.center.slice(),
          // FIXME
          // label rotation is not support yet in geo or regions of series-map
          // that has no data. The rotation will be effected by this `scale`.
          // So needed to change to RectText?
          scale: [1 / scale[0], 1 / scale[1]],
          z2: 10,
          silent: true
        });
        graphic.setLabelStyle(textEl.style, textEl.hoverStyle = {}, labelModel, hoverLabelModel, {
          labelFetcher: labelFetcher,
          labelDataIndex: query,
          defaultText: region.name,
          useInsideStyle: false
        }, {
          textAlign: 'center',
          textVerticalAlign: 'middle'
        });
        regionGroup.add(textEl);
      } // setItemGraphicEl, setHoverStyle after all polygons and labels
      // are added to the rigionGroup


      if (data) {
        data.setItemGraphicEl(dataIdx, regionGroup);
      } else {
        var regionModel = mapOrGeoModel.getRegionModel(region.name); // Package custom mouse event for geo component

        compoundPath.eventData = {
          componentType: 'geo',
          componentIndex: mapOrGeoModel.componentIndex,
          geoIndex: mapOrGeoModel.componentIndex,
          name: region.name,
          region: regionModel && regionModel.option || {}
        };
      }

      var groupRegions = regionGroup.__regions || (regionGroup.__regions = []);
      groupRegions.push(region);
      regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
      graphic.setHoverStyle(regionGroup, hoverItemStyle);
      regionsGroup.add(regionGroup);
    });

    this._updateController(mapOrGeoModel, ecModel, api);

    updateMapSelectHandler(this, mapOrGeoModel, regionsGroup, api, fromView);
    updateMapSelected(mapOrGeoModel, regionsGroup);
  },
  remove: function () {
    this._regionsGroup.removeAll();

    this._backgroundGroup.removeAll();

    this._controller.dispose();

    this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid);
    this._mapName = null;
    this._controllerHost = {};
  },
  _updateBackground: function (geo) {
    var mapName = geo.map;

    if (this._mapName !== mapName) {
      zrUtil.each(geoSourceManager.makeGraphic(mapName, this.uid), function (root) {
        this._backgroundGroup.add(root);
      }, this);
    }

    this._mapName = mapName;
  },
  _updateController: function (mapOrGeoModel, ecModel, api) {
    var geo = mapOrGeoModel.coordinateSystem;
    var controller = this._controller;
    var controllerHost = this._controllerHost;
    controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit');
    controllerHost.zoom = geo.getZoom(); // roamType is will be set default true if it is null

    controller.enable(mapOrGeoModel.get('roam') || false);
    var mainType = mapOrGeoModel.mainType;

    function makeActionBase() {
      var action = {
        type: 'geoRoam',
        componentType: mainType
      };
      action[mainType + 'Id'] = mapOrGeoModel.id;
      return action;
    }

    controller.off('pan').on('pan', function (e) {
      this._mouseDownFlag = false;
      roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy);
      api.dispatchAction(zrUtil.extend(makeActionBase(), {
        dx: e.dx,
        dy: e.dy
      }));
    }, this);
    controller.off('zoom').on('zoom', function (e) {
      this._mouseDownFlag = false;
      roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
      api.dispatchAction(zrUtil.extend(makeActionBase(), {
        zoom: e.scale,
        originX: e.originX,
        originY: e.originY
      }));

      if (this._updateGroup) {
        var scale = this.group.scale;

        this._regionsGroup.traverse(function (el) {
          if (el.type === 'text') {
            el.attr('scale', [1 / scale[0], 1 / scale[1]]);
          }
        });
      }
    }, this);
    controller.setPointerChecker(function (e, x, y) {
      return geo.getViewRectAfterRoam().contain(x, y) && !onIrrelevantElement(e, api, mapOrGeoModel);
    });
  }
};
export default MapDraw;