/**
 * echarts图表类：散点图
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */
module.exports = function (require) {
  var ChartBase = require('./base'); // 图形依赖


  var SymbolShape = require('../util/shape/Symbol'); // 组件依赖


  require('../component/axis');

  require('../component/grid');

  require('../component/dataZoom');

  require('../component/dataRange');

  var ecConfig = require('../config'); // 散点图默认参数


  ecConfig.scatter = {
    zlevel: 0,
    // 一级层叠
    z: 2,
    // 二级层叠
    clickable: true,
    legendHoverLink: true,
    xAxisIndex: 0,
    yAxisIndex: 0,
    // symbol: null,        // 图形类型
    symbolSize: 4,
    // 图形大小，半宽（半径）参数，当图形为方向或菱形则总宽度为symbolSize * 2
    // symbolRotate: null,  // 图形旋转控制
    large: false,
    // 大规模散点图
    largeThreshold: 2000,
    // 大规模阀值，large为true且数据量>largeThreshold才启用大规模模式
    itemStyle: {
      normal: {
        // color: 各异,
        label: {
          show: false // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
          // position: 默认自适应，水平布局为'top'，垂直布局为'right'，可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式，详见TEXTSTYLE

        }
      },
      emphasis: {
        // color: '各异'
        label: {
          show: false // formatter: 标签文本格式器，同Tooltip.formatter，不支持异步回调
          // position: 默认自适应，水平布局为'top'，垂直布局为'right'，可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式，详见TEXTSTYLE

        }
      }
    }
  };

  var zrUtil = require('zrender/tool/util');

  var zrColor = require('zrender/tool/color');
  /**
   * 构造函数
   * @param {Object} messageCenter echart消息中心
   * @param {ZRender} zr zrender实例
   * @param {Object} series 数据
   * @param {Object} component 组件
   */


  function Scatter(ecTheme, messageCenter, zr, option, myChart) {
    // 图表基类
    ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);
    this.refresh(option);
  }

  Scatter.prototype = {
    type: ecConfig.CHART_TYPE_SCATTER,

    /**
     * 绘制图形
     */
    _buildShape: function () {
      var series = this.series;
      this._sIndex2ColorMap = {}; // series默认颜色索引，seriesIndex索引到color

      this._symbol = this.option.symbolList;
      this._sIndex2ShapeMap = {}; // series图形类型，seriesIndex索引到_symbol

      this.selectedMap = {};
      this.xMarkMap = {};
      var legend = this.component.legend;
      var seriesArray = [];
      var serie; // 临时映射变量

      var serieName; // 临时映射变量

      var iconShape;
      var iconType;

      for (var i = 0, l = series.length; i < l; i++) {
        serie = series[i];
        serieName = serie.name;

        if (serie.type === ecConfig.CHART_TYPE_SCATTER) {
          series[i] = this.reformOption(series[i]);
          this.legendHoverLink = series[i].legendHoverLink || this.legendHoverLink;
          this._sIndex2ShapeMap[i] = this.query(serie, 'symbol') || this._symbol[i % this._symbol.length];

          if (legend) {
            this.selectedMap[serieName] = legend.isSelected(serieName);
            this._sIndex2ColorMap[i] = zrColor.alpha(legend.getColor(serieName), 0.5);
            iconShape = legend.getItemShape(serieName);

            if (iconShape) {
              // 回调legend，换一个更形象的icon
              var iconType = this._sIndex2ShapeMap[i];
              iconShape.style.brushType = iconType.match('empty') ? 'stroke' : 'both';
              iconType = iconType.replace('empty', '').toLowerCase();

              if (iconType.match('rectangle')) {
                iconShape.style.x += Math.round((iconShape.style.width - iconShape.style.height) / 2);
                iconShape.style.width = iconShape.style.height;
              }

              if (iconType.match('star')) {
                iconShape.style.n = iconType.replace('star', '') - 0 || 5;
                iconType = 'star';
              }

              if (iconType.match('image')) {
                iconShape.style.image = iconType.replace(new RegExp('^image:\\/\\/'), '');
                iconShape.style.x += Math.round((iconShape.style.width - iconShape.style.height) / 2);
                iconShape.style.width = iconShape.style.height;
                iconType = 'image';
              }

              iconShape.style.iconType = iconType;
              legend.setItemShape(serieName, iconShape);
            }
          } else {
            this.selectedMap[serieName] = true;
            this._sIndex2ColorMap[i] = zrColor.alpha(this.zr.getColor(i), 0.5);
          }

          if (this.selectedMap[serieName]) {
            seriesArray.push(i);
          }
        }
      }

      this._buildSeries(seriesArray);

      this.addShapeList();
    },

    /**
     * 构建类目轴为水平方向的散点图系列
     */
    _buildSeries: function (seriesArray) {
      if (seriesArray.length === 0) {
        return;
      }

      var series = this.series;
      var seriesIndex;
      var serie;
      var data;
      var value;
      var xAxis;
      var yAxis;
      var pointList = {};
      var x;
      var y;

      for (var j = 0, k = seriesArray.length; j < k; j++) {
        seriesIndex = seriesArray[j];
        serie = series[seriesIndex];

        if (serie.data.length === 0) {
          continue;
        }

        xAxis = this.component.xAxis.getAxis(serie.xAxisIndex || 0);
        yAxis = this.component.yAxis.getAxis(serie.yAxisIndex || 0);
        pointList[seriesIndex] = [];

        for (var i = 0, l = serie.data.length; i < l; i++) {
          data = serie.data[i];
          value = this.getDataFromOption(data, '-');

          if (value === '-' || value.length < 2) {
            // 数据格式不符
            continue;
          }

          x = xAxis.getCoord(value[0]);
          y = yAxis.getCoord(value[1]);
          pointList[seriesIndex].push([x, // 横坐标
          y, // 纵坐标
          i, // 数据index
          data.name || '' // 名称
          ]);
        }

        this.xMarkMap[seriesIndex] = this._markMap(xAxis, yAxis, serie.data, pointList[seriesIndex]);
        this.buildMark(seriesIndex);
      } // console.log(pointList)


      this._buildPointList(pointList);
    },
    _markMap: function (xAxis, yAxis, data, pointList) {
      var xMarkMap = {
        min0: Number.POSITIVE_INFINITY,
        max0: Number.NEGATIVE_INFINITY,
        sum0: 0,
        counter0: 0,
        average0: 0,
        min1: Number.POSITIVE_INFINITY,
        max1: Number.NEGATIVE_INFINITY,
        sum1: 0,
        counter1: 0,
        average1: 0
      };
      var value;

      for (var i = 0, l = pointList.length; i < l; i++) {
        /**
        x,                  // 横坐标
        y,                  // 纵坐标
        i,                  // 数据index
        data.name || ''     // 名称 
         */
        value = data[pointList[i][2]].value || data[pointList[i][2]]; // 横轴

        if (xMarkMap.min0 > value[0]) {
          xMarkMap.min0 = value[0];
          xMarkMap.minY0 = pointList[i][1];
          xMarkMap.minX0 = pointList[i][0];
        }

        if (xMarkMap.max0 < value[0]) {
          xMarkMap.max0 = value[0];
          xMarkMap.maxY0 = pointList[i][1];
          xMarkMap.maxX0 = pointList[i][0];
        }

        xMarkMap.sum0 += value[0];
        xMarkMap.counter0++; // 纵轴

        if (xMarkMap.min1 > value[1]) {
          xMarkMap.min1 = value[1];
          xMarkMap.minY1 = pointList[i][1];
          xMarkMap.minX1 = pointList[i][0];
        }

        if (xMarkMap.max1 < value[1]) {
          xMarkMap.max1 = value[1];
          xMarkMap.maxY1 = pointList[i][1];
          xMarkMap.maxX1 = pointList[i][0];
        }

        xMarkMap.sum1 += value[1];
        xMarkMap.counter1++;
      }

      var gridX = this.component.grid.getX();
      var gridXend = this.component.grid.getXend();
      var gridY = this.component.grid.getY();
      var gridYend = this.component.grid.getYend();
      xMarkMap.average0 = xMarkMap.sum0 / xMarkMap.counter0;
      var x = xAxis.getCoord(xMarkMap.average0); // 横轴平均纵向

      xMarkMap.averageLine0 = [[x, gridYend], [x, gridY]];
      xMarkMap.minLine0 = [[xMarkMap.minX0, gridYend], [xMarkMap.minX0, gridY]];
      xMarkMap.maxLine0 = [[xMarkMap.maxX0, gridYend], [xMarkMap.maxX0, gridY]];
      xMarkMap.average1 = xMarkMap.sum1 / xMarkMap.counter1;
      var y = yAxis.getCoord(xMarkMap.average1); // 纵轴平均横向

      xMarkMap.averageLine1 = [[gridX, y], [gridXend, y]];
      xMarkMap.minLine1 = [[gridX, xMarkMap.minY1], [gridXend, xMarkMap.minY1]];
      xMarkMap.maxLine1 = [[gridX, xMarkMap.maxY1], [gridXend, xMarkMap.maxY1]];
      return xMarkMap;
    },

    /**
     * 生成折线和折线上的拐点
     */
    _buildPointList: function (pointList) {
      var series = this.series;
      var serie;
      var seriesPL;
      var singlePoint;
      var shape;

      for (var seriesIndex in pointList) {
        serie = series[seriesIndex];
        seriesPL = pointList[seriesIndex];

        if (serie.large && serie.data.length > serie.largeThreshold) {
          this.shapeList.push(this._getLargeSymbol(serie, seriesPL, this.getItemStyleColor(this.query(serie, 'itemStyle.normal.color'), seriesIndex, -1) || this._sIndex2ColorMap[seriesIndex]));
          continue;
        }
        /*
         * pointlist=[
         *      0  x,
         *      1  y, 
         *      2  数据index
         *      3  名称
         * ]
         */


        for (var i = 0, l = seriesPL.length; i < l; i++) {
          singlePoint = seriesPL[i];
          shape = this._getSymbol(seriesIndex, // seriesIndex
          singlePoint[2], // dataIndex
          singlePoint[3], // name
          singlePoint[0], // x
          singlePoint[1] // y
          );
          shape && this.shapeList.push(shape);
        }
      } // console.log(this.shapeList)

    },

    /**
     * 生成折线图上的拐点图形
     */
    _getSymbol: function (seriesIndex, dataIndex, name, x, y) {
      var series = this.series;
      var serie = series[seriesIndex];
      var data = serie.data[dataIndex];
      var dataRange = this.component.dataRange;
      var rangColor;

      if (dataRange) {
        rangColor = isNaN(data[2]) ? this._sIndex2ColorMap[seriesIndex] : dataRange.getColor(data[2]);

        if (!rangColor) {
          return null;
        }
      } else {
        rangColor = this._sIndex2ColorMap[seriesIndex];
      }

      var itemShape = this.getSymbolShape(serie, seriesIndex, data, dataIndex, name, x, y, this._sIndex2ShapeMap[seriesIndex], rangColor, 'rgba(0,0,0,0)', 'vertical');
      itemShape.zlevel = serie.zlevel;
      itemShape.z = serie.z;
      itemShape._main = true;
      return itemShape;
    },
    _getLargeSymbol: function (serie, pointList, nColor) {
      return new SymbolShape({
        zlevel: serie.zlevel,
        z: serie.z,
        _main: true,
        hoverable: false,
        style: {
          pointList: pointList,
          color: nColor,
          strokeColor: nColor
        },
        highlightStyle: {
          pointList: []
        }
      });
    },
    // 位置转换
    getMarkCoord: function (seriesIndex, mpData) {
      var serie = this.series[seriesIndex];
      var xMarkMap = this.xMarkMap[seriesIndex];
      var xAxis = this.component.xAxis.getAxis(serie.xAxisIndex);
      var yAxis = this.component.yAxis.getAxis(serie.yAxisIndex);
      var pos;

      if (mpData.type && (mpData.type === 'max' || mpData.type === 'min' || mpData.type === 'average')) {
        // 特殊值内置支持
        // 默认取纵值
        var valueIndex = mpData.valueIndex != null ? mpData.valueIndex : 1;
        pos = [xMarkMap[mpData.type + 'X' + valueIndex], xMarkMap[mpData.type + 'Y' + valueIndex], xMarkMap[mpData.type + 'Line' + valueIndex], xMarkMap[mpData.type + valueIndex]];
      } else {
        pos = [typeof mpData.xAxis != 'string' && xAxis.getCoordByIndex ? xAxis.getCoordByIndex(mpData.xAxis || 0) : xAxis.getCoord(mpData.xAxis || 0), typeof mpData.yAxis != 'string' && yAxis.getCoordByIndex ? yAxis.getCoordByIndex(mpData.yAxis || 0) : yAxis.getCoord(mpData.yAxis || 0)];
      }

      return pos;
    },

    /**
     * 刷新
     */
    refresh: function (newOption) {
      if (newOption) {
        this.option = newOption;
        this.series = newOption.series;
      }

      this.backupShapeList();

      this._buildShape();
    },

    /**
     * 值域响应
     * @param {Object} param
     * @param {Object} status
     */
    ondataRange: function (param, status) {
      if (this.component.dataRange) {
        this.refresh();
        status.needRefresh = true;
      }

      return;
    }
  };
  zrUtil.inherits(Scatter, ChartBase); // 图表注册

  require('../chart').define('scatter', Scatter);

  return Scatter;
}(require);