/*
* 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 { __DEV__ } from '../../config';
import * as zrUtil from 'zrender/src/core/util';
import VisualMapModel from './VisualMapModel';
import VisualMapping from '../../visual/VisualMapping';
import visualDefault from '../../visual/visualDefault';
import { reformIntervals } from '../../util/number';
var PiecewiseModel = VisualMapModel.extend({
  type: 'visualMap.piecewise',

  /**
   * Order Rule:
   *
   * option.categories / option.pieces / option.text / option.selected:
   *     If !option.inverse,
   *     Order when vertical: ['top', ..., 'bottom'].
   *     Order when horizontal: ['left', ..., 'right'].
   *     If option.inverse, the meaning of
   *     the order should be reversed.
   *
   * this._pieceList:
   *     The order is always [low, ..., high].
   *
   * Mapping from location to low-high:
   *     If !option.inverse
   *     When vertical, top is high.
   *     When horizontal, right is high.
   *     If option.inverse, reverse.
   */

  /**
   * @protected
   */
  defaultOption: {
    selected: null,
    // Object. If not specified, means selected.
    // When pieces and splitNumber: {'0': true, '5': true}
    // When categories: {'cate1': false, 'cate3': true}
    // When selected === false, means all unselected.
    minOpen: false,
    // Whether include values that smaller than `min`.
    maxOpen: false,
    // Whether include values that bigger than `max`.
    align: 'auto',
    // 'auto', 'left', 'right'
    itemWidth: 20,
    // When put the controller vertically, it is the length of
    // horizontal side of each item. Otherwise, vertical side.
    itemHeight: 14,
    // When put the controller vertically, it is the length of
    // vertical side of each item. Otherwise, horizontal side.
    itemSymbol: 'roundRect',
    pieceList: null,
    // Each item is Object, with some of those attrs:
    // {min, max, lt, gt, lte, gte, value,
    // color, colorSaturation, colorAlpha, opacity,
    // symbol, symbolSize}, which customize the range or visual
    // coding of the certain piece. Besides, see "Order Rule".
    categories: null,
    // category names, like: ['some1', 'some2', 'some3'].
    // Attr min/max are ignored when categories set. See "Order Rule"
    splitNumber: 5,
    // If set to 5, auto split five pieces equally.
    // If set to 0 and component type not set, component type will be
    // determined as "continuous". (It is less reasonable but for ec2
    // compatibility, see echarts/component/visualMap/typeDefaulter)
    selectedMode: 'multiple',
    // Can be 'multiple' or 'single'.
    itemGap: 10,
    // The gap between two items, in px.
    hoverLink: true,
    // Enable hover highlight.
    showLabel: null // By default, when text is used, label will hide (the logic
    // is remained for compatibility reason)

  },

  /**
   * @override
   */
  optionUpdated: function (newOption, isInit) {
    PiecewiseModel.superApply(this, 'optionUpdated', arguments);
    /**
     * The order is always [low, ..., high].
     * [{text: string, interval: Array.<number>}, ...]
     * @private
     * @type {Array.<Object>}
     */

    this._pieceList = [];
    this.resetExtent();
    /**
     * 'pieces', 'categories', 'splitNumber'
     * @type {string}
     */

    var mode = this._mode = this._determineMode();

    resetMethods[this._mode].call(this);

    this._resetSelected(newOption, isInit);

    var categories = this.option.categories;
    this.resetVisual(function (mappingOption, state) {
      if (mode === 'categories') {
        mappingOption.mappingMethod = 'category';
        mappingOption.categories = zrUtil.clone(categories);
      } else {
        mappingOption.dataExtent = this.getExtent();
        mappingOption.mappingMethod = 'piecewise';
        mappingOption.pieceList = zrUtil.map(this._pieceList, function (piece) {
          var piece = zrUtil.clone(piece);

          if (state !== 'inRange') {
            // FIXME
            // outOfRange do not support special visual in pieces.
            piece.visual = null;
          }

          return piece;
        });
      }
    });
  },

  /**
   * @protected
   * @override
   */
  completeVisualOption: function () {
    // Consider this case:
    // visualMap: {
    //      pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}]
    // }
    // where no inRange/outOfRange set but only pieces. So we should make
    // default inRange/outOfRange for this case, otherwise visuals that only
    // appear in `pieces` will not be taken into account in visual encoding.
    var option = this.option;
    var visualTypesInPieces = {};
    var visualTypes = VisualMapping.listVisualTypes();
    var isCategory = this.isCategory();
    zrUtil.each(option.pieces, function (piece) {
      zrUtil.each(visualTypes, function (visualType) {
        if (piece.hasOwnProperty(visualType)) {
          visualTypesInPieces[visualType] = 1;
        }
      });
    });
    zrUtil.each(visualTypesInPieces, function (v, visualType) {
      var exists = 0;
      zrUtil.each(this.stateList, function (state) {
        exists |= has(option, state, visualType) || has(option.target, state, visualType);
      }, this);
      !exists && zrUtil.each(this.stateList, function (state) {
        (option[state] || (option[state] = {}))[visualType] = visualDefault.get(visualType, state === 'inRange' ? 'active' : 'inactive', isCategory);
      });
    }, this);

    function has(obj, state, visualType) {
      return obj && obj[state] && (zrUtil.isObject(obj[state]) ? obj[state].hasOwnProperty(visualType) : obj[state] === visualType // e.g., inRange: 'symbol'
      );
    }

    VisualMapModel.prototype.completeVisualOption.apply(this, arguments);
  },
  _resetSelected: function (newOption, isInit) {
    var thisOption = this.option;
    var pieceList = this._pieceList; // Selected do not merge but all override.

    var selected = (isInit ? thisOption : newOption).selected || {};
    thisOption.selected = selected; // Consider 'not specified' means true.

    zrUtil.each(pieceList, function (piece, index) {
      var key = this.getSelectedMapKey(piece);

      if (!selected.hasOwnProperty(key)) {
        selected[key] = true;
      }
    }, this);

    if (thisOption.selectedMode === 'single') {
      // Ensure there is only one selected.
      var hasSel = false;
      zrUtil.each(pieceList, function (piece, index) {
        var key = this.getSelectedMapKey(piece);

        if (selected[key]) {
          hasSel ? selected[key] = false : hasSel = true;
        }
      }, this);
    } // thisOption.selectedMode === 'multiple', default: all selected.

  },

  /**
   * @public
   */
  getSelectedMapKey: function (piece) {
    return this._mode === 'categories' ? piece.value + '' : piece.index + '';
  },

  /**
   * @public
   */
  getPieceList: function () {
    return this._pieceList;
  },

  /**
   * @private
   * @return {string}
   */
  _determineMode: function () {
    var option = this.option;
    return option.pieces && option.pieces.length > 0 ? 'pieces' : this.option.categories ? 'categories' : 'splitNumber';
  },

  /**
   * @public
   * @override
   */
  setSelected: function (selected) {
    this.option.selected = zrUtil.clone(selected);
  },

  /**
   * @public
   * @override
   */
  getValueState: function (value) {
    var index = VisualMapping.findPieceIndex(value, this._pieceList);
    return index != null ? this.option.selected[this.getSelectedMapKey(this._pieceList[index])] ? 'inRange' : 'outOfRange' : 'outOfRange';
  },

  /**
   * @public
   * @params {number} pieceIndex piece index in visualMapModel.getPieceList()
   * @return {Array.<Object>} [{seriesId, dataIndex: <Array.<number>>}, ...]
   */
  findTargetDataIndices: function (pieceIndex) {
    var result = [];
    this.eachTargetSeries(function (seriesModel) {
      var dataIndices = [];
      var data = seriesModel.getData();
      data.each(this.getDataDimension(data), function (value, dataIndex) {
        // Should always base on model pieceList, because it is order sensitive.
        var pIdx = VisualMapping.findPieceIndex(value, this._pieceList);
        pIdx === pieceIndex && dataIndices.push(dataIndex);
      }, this);
      result.push({
        seriesId: seriesModel.id,
        dataIndex: dataIndices
      });
    }, this);
    return result;
  },

  /**
   * @private
   * @param {Object} piece piece.value or piece.interval is required.
   * @return {number} Can be Infinity or -Infinity
   */
  getRepresentValue: function (piece) {
    var representValue;

    if (this.isCategory()) {
      representValue = piece.value;
    } else {
      if (piece.value != null) {
        representValue = piece.value;
      } else {
        var pieceInterval = piece.interval || [];
        representValue = pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity ? 0 : (pieceInterval[0] + pieceInterval[1]) / 2;
      }
    }

    return representValue;
  },
  getVisualMeta: function (getColorVisual) {
    // Do not support category. (category axis is ordinal, numerical)
    if (this.isCategory()) {
      return;
    }

    var stops = [];
    var outerColors = [];
    var visualMapModel = this;

    function setStop(interval, valueState) {
      var representValue = visualMapModel.getRepresentValue({
        interval: interval
      });

      if (!valueState) {
        valueState = visualMapModel.getValueState(representValue);
      }

      var color = getColorVisual(representValue, valueState);

      if (interval[0] === -Infinity) {
        outerColors[0] = color;
      } else if (interval[1] === Infinity) {
        outerColors[1] = color;
      } else {
        stops.push({
          value: interval[0],
          color: color
        }, {
          value: interval[1],
          color: color
        });
      }
    } // Suplement


    var pieceList = this._pieceList.slice();

    if (!pieceList.length) {
      pieceList.push({
        interval: [-Infinity, Infinity]
      });
    } else {
      var edge = pieceList[0].interval[0];
      edge !== -Infinity && pieceList.unshift({
        interval: [-Infinity, edge]
      });
      edge = pieceList[pieceList.length - 1].interval[1];
      edge !== Infinity && pieceList.push({
        interval: [edge, Infinity]
      });
    }

    var curr = -Infinity;
    zrUtil.each(pieceList, function (piece) {
      var interval = piece.interval;

      if (interval) {
        // Fulfill gap.
        interval[0] > curr && setStop([curr, interval[0]], 'outOfRange');
        setStop(interval.slice());
        curr = interval[1];
      }
    }, this);
    return {
      stops: stops,
      outerColors: outerColors
    };
  }
});
/**
 * Key is this._mode
 * @type {Object}
 * @this {module:echarts/component/viusalMap/PiecewiseMode}
 */

var resetMethods = {
  splitNumber: function () {
    var thisOption = this.option;
    var pieceList = this._pieceList;
    var precision = Math.min(thisOption.precision, 20);
    var dataExtent = this.getExtent();
    var splitNumber = thisOption.splitNumber;
    splitNumber = Math.max(parseInt(splitNumber, 10), 1);
    thisOption.splitNumber = splitNumber;
    var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber; // Precision auto-adaption

    while (+splitStep.toFixed(precision) !== splitStep && precision < 5) {
      precision++;
    }

    thisOption.precision = precision;
    splitStep = +splitStep.toFixed(precision);
    var index = 0;

    if (thisOption.minOpen) {
      pieceList.push({
        index: index++,
        interval: [-Infinity, dataExtent[0]],
        close: [0, 0]
      });
    }

    for (var curr = dataExtent[0], len = index + splitNumber; index < len; curr += splitStep) {
      var max = index === splitNumber - 1 ? dataExtent[1] : curr + splitStep;
      pieceList.push({
        index: index++,
        interval: [curr, max],
        close: [1, 1]
      });
    }

    if (thisOption.maxOpen) {
      pieceList.push({
        index: index++,
        interval: [dataExtent[1], Infinity],
        close: [0, 0]
      });
    }

    reformIntervals(pieceList);
    zrUtil.each(pieceList, function (piece) {
      piece.text = this.formatValueText(piece.interval);
    }, this);
  },
  categories: function () {
    var thisOption = this.option;
    zrUtil.each(thisOption.categories, function (cate) {
      // FIXME category模式也使用pieceList，但在visualMapping中不是使用pieceList。
      // 是否改一致。
      this._pieceList.push({
        text: this.formatValueText(cate, true),
        value: cate
      });
    }, this); // See "Order Rule".

    normalizeReverse(thisOption, this._pieceList);
  },
  pieces: function () {
    var thisOption = this.option;
    var pieceList = this._pieceList;
    zrUtil.each(thisOption.pieces, function (pieceListItem, index) {
      if (!zrUtil.isObject(pieceListItem)) {
        pieceListItem = {
          value: pieceListItem
        };
      }

      var item = {
        text: '',
        index: index
      };

      if (pieceListItem.label != null) {
        item.text = pieceListItem.label;
      }

      if (pieceListItem.hasOwnProperty('value')) {
        var value = item.value = pieceListItem.value;
        item.interval = [value, value];
        item.close = [1, 1];
      } else {
        // `min` `max` is legacy option.
        // `lt` `gt` `lte` `gte` is recommanded.
        var interval = item.interval = [];
        var close = item.close = [0, 0];
        var closeList = [1, 0, 1];
        var infinityList = [-Infinity, Infinity];
        var useMinMax = [];

        for (var lg = 0; lg < 2; lg++) {
          var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg];

          for (var i = 0; i < 3 && interval[lg] == null; i++) {
            interval[lg] = pieceListItem[names[i]];
            close[lg] = closeList[i];
            useMinMax[lg] = i === 2;
          }

          interval[lg] == null && (interval[lg] = infinityList[lg]);
        }

        useMinMax[0] && interval[1] === Infinity && (close[0] = 0);
        useMinMax[1] && interval[0] === -Infinity && (close[1] = 0);

        if (interval[0] === interval[1] && close[0] && close[1]) {
          // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}],
          // we use value to lift the priority when min === max
          item.value = interval[0];
        }
      }

      item.visual = VisualMapping.retrieveVisuals(pieceListItem);
      pieceList.push(item);
    }, this); // See "Order Rule".

    normalizeReverse(thisOption, pieceList); // Only pieces

    reformIntervals(pieceList);
    zrUtil.each(pieceList, function (piece) {
      var close = piece.close;
      var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]];
      piece.text = piece.text || this.formatValueText(piece.value != null ? piece.value : piece.interval, false, edgeSymbols);
    }, this);
  }
};

function normalizeReverse(thisOption, pieceList) {
  var inverse = thisOption.inverse;

  if (thisOption.orient === 'vertical' ? !inverse : inverse) {
    pieceList.reverse();
  }
}

export default PiecewiseModel;