/**
 * echarts组件类：极坐标
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Neil (杨骥, 511415343@qq.com)
 *
 */
module.exports = function (require) {
  var Base = require('./base'); // 图形依赖


  var TextShape = require('zrender/shape/Text');

  var LineShape = require('zrender/shape/Line');

  var PolygonShape = require('zrender/shape/Polygon');

  var Circle = require('zrender/shape/Circle');

  var Ring = require('zrender/shape/Ring');

  var ecConfig = require('../config');

  ecConfig.polar = {
    zlevel: 0,
    // 一级层叠
    z: 0,
    // 二级层叠
    center: ['50%', '50%'],
    // 默认全局居中
    radius: '75%',
    startAngle: 90,
    boundaryGap: [0, 0],
    // 数值起始和结束两端空白策略
    splitNumber: 5,
    name: {
      show: true,
      // formatter: null,
      textStyle: {
        // 其余属性默认使用全局文本样式，详见TEXTSTYLE
        color: '#333'
      }
    },
    axisLine: {
      // 坐标轴线
      show: true,
      // 默认显示，属性show控制显示与否
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: '#ccc',
        width: 1,
        type: 'solid'
      }
    },
    axisLabel: {
      // 坐标轴文本标签，详见axis.axisLabel
      show: false,
      // formatter: null,
      textStyle: {
        // 其余属性默认使用全局文本样式，详见TEXTSTYLE
        color: '#333'
      }
    },
    splitArea: {
      show: true,
      areaStyle: {
        color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
      }
    },
    splitLine: {
      show: true,
      lineStyle: {
        width: 1,
        color: '#ccc'
      }
    },
    type: 'polygon' // indicator: []

  };

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

  var ecCoordinates = require('../util/coordinates');

  function Polar(ecTheme, messageCenter, zr, option, myChart) {
    Base.call(this, ecTheme, messageCenter, zr, option, myChart);
    this.refresh(option);
  }

  Polar.prototype = {
    type: ecConfig.COMPONENT_TYPE_POLAR,

    /**
     * 绘制图形
     */
    _buildShape: function () {
      for (var i = 0; i < this.polar.length; i++) {
        this._index = i;
        this.reformOption(this.polar[i]);
        this._queryTarget = [this.polar[i], this.option];

        this._createVector(i);

        this._buildSpiderWeb(i);

        this._buildText(i);

        this._adjustIndicatorValue(i);

        this._addAxisLabel(i);
      }

      for (var i = 0; i < this.shapeList.length; i++) {
        this.zr.addShape(this.shapeList[i]);
      }
    },

    /**
     * 生成蜘蛛网顶点坐标
     * @param {number} polar的index
     */
    _createVector: function (index) {
      var item = this.polar[index];
      var indicator = this.deepQuery(this._queryTarget, 'indicator');
      var length = indicator.length;
      var startAngle = item.startAngle;
      var dStep = 2 * Math.PI / length;

      var radius = this._getRadius();

      var __ecIndicator = item.__ecIndicator = [];

      var vector;

      for (var i = 0; i < length; i++) {
        vector = ecCoordinates.polar2cartesian(radius, startAngle * Math.PI / 180 + dStep * i);

        __ecIndicator.push({
          // 将图形翻转
          vector: [vector[1], -vector[0]]
        });
      }
    },

    /**
     * 获取外圈的半径
     *
     * @return {number}
     */
    _getRadius: function () {
      var item = this.polar[this._index];
      return this.parsePercent(item.radius, Math.min(this.zr.getWidth(), this.zr.getHeight()) / 2);
    },

    /**
     * 构建蜘蛛网
     * @param {number} polar的index
     */
    _buildSpiderWeb: function (index) {
      var item = this.polar[index];
      var __ecIndicator = item.__ecIndicator;
      var splitArea = item.splitArea;
      var splitLine = item.splitLine;
      var center = this.getCenter(index);
      var splitNumber = item.splitNumber;
      var strokeColor = splitLine.lineStyle.color;
      var lineWidth = splitLine.lineStyle.width;
      var show = splitLine.show;
      var axisLine = this.deepQuery(this._queryTarget, 'axisLine');

      this._addArea(__ecIndicator, splitNumber, center, splitArea, strokeColor, lineWidth, show);

      axisLine.show && this._addLine(__ecIndicator, center, axisLine);
    },

    /**
     * 绘制axisLabel
     */
    _addAxisLabel: function (index) {
      var accMath = require('../util/accMath');

      var item = this.polar[index];
      var indicator = this.deepQuery(this._queryTarget, 'indicator');
      var __ecIndicator = item.__ecIndicator;
      var axisLabel;
      var vector;
      var style;
      var newStyle;
      var splitNumber = this.deepQuery(this._queryTarget, 'splitNumber');
      var center = this.getCenter(index);
      var vector;
      var value;
      var text;
      var theta; // var startAngle = this.deepQuery(this._queryTarget, 'startAngle');

      var offset;
      var interval;

      for (var i = 0; i < indicator.length; i++) {
        axisLabel = this.deepQuery([indicator[i], item, this.option], 'axisLabel');

        if (axisLabel.show) {
          var textStyle = this.deepQuery([axisLabel, item, this.option], 'textStyle');
          var formatter = this.deepQuery([axisLabel, item], 'formatter');
          style = {};
          style.textFont = this.getFont(textStyle);
          style.color = textStyle.color;
          style = zrUtil.merge(style, axisLabel);
          style.lineWidth = style.width;
          vector = __ecIndicator[i].vector;
          value = __ecIndicator[i].value;
          theta = i / indicator.length * 2 * Math.PI;
          offset = axisLabel.offset || 10;
          interval = axisLabel.interval || 0;

          if (!value) {
            return;
          }

          for (var j = 1; j <= splitNumber; j += interval + 1) {
            newStyle = zrUtil.merge({}, style);
            text = accMath.accAdd(value.min, accMath.accMul(value.step, j));

            if (typeof formatter === 'function') {
              text = formatter(text);
            } else if (typeof formatter === 'string') {
              text = formatter.replace('{a}', '{a0}').replace('{a0}', text);
            } else {
              text = this.numAddCommas(text);
            }

            newStyle.text = text;
            newStyle.x = j * vector[0] / splitNumber + Math.cos(theta) * offset + center[0];
            newStyle.y = j * vector[1] / splitNumber + Math.sin(theta) * offset + center[1];
            this.shapeList.push(new TextShape({
              zlevel: this.getZlevelBase(),
              z: this.getZBase(),
              style: newStyle,
              draggable: false,
              hoverable: false
            }));
          }
        }
      }
    },

    /**
     * 绘制坐标头的文字
     * @param {number} polar的index
     */
    _buildText: function (index) {
      var item = this.polar[index];
      var __ecIndicator = item.__ecIndicator;
      var vector;
      var indicator = this.deepQuery(this._queryTarget, 'indicator');
      var center = this.getCenter(index);
      var style;
      var textAlign;
      var name;
      var rotation;
      var x = 0;
      var y = 0;
      var margin;
      var textStyle;

      for (var i = 0; i < indicator.length; i++) {
        name = this.deepQuery([indicator[i], item, this.option], 'name');

        if (!name.show) {
          continue;
        }

        textStyle = this.deepQuery([name, item, this.option], 'textStyle');
        style = {};
        style.textFont = this.getFont(textStyle);
        style.color = textStyle.color;

        if (typeof name.formatter == 'function') {
          style.text = name.formatter.call(this.myChart, indicator[i].text, i);
        } else if (typeof name.formatter == 'string') {
          style.text = name.formatter.replace('{value}', indicator[i].text);
        } else {
          style.text = indicator[i].text;
        }

        __ecIndicator[i].text = style.text;
        vector = __ecIndicator[i].vector;

        if (Math.round(vector[0]) > 0) {
          textAlign = 'left';
        } else if (Math.round(vector[0]) < 0) {
          textAlign = 'right';
        } else {
          textAlign = 'center';
        }

        if (name.margin == null) {
          vector = this._mapVector(vector, center, 1.1);
        } else {
          margin = name.margin;
          x = vector[0] > 0 ? margin : -margin;
          y = vector[1] > 0 ? margin : -margin;
          x = vector[0] === 0 ? 0 : x;
          y = vector[1] === 0 ? 0 : y;
          vector = this._mapVector(vector, center, 1);
        }

        style.textAlign = textAlign;
        style.x = vector[0] + x;
        style.y = vector[1] + y;

        if (name.rotate) {
          rotation = [name.rotate / 180 * Math.PI, vector[0], vector[1]];
        } else {
          rotation = [0, 0, 0];
        }

        this.shapeList.push(new TextShape({
          zlevel: this.getZlevelBase(),
          z: this.getZBase(),
          style: style,
          draggable: false,
          hoverable: false,
          rotation: rotation
        }));
      }
    },
    getIndicatorText: function (polarIndex, indicatorIndex) {
      return this.polar[polarIndex] && this.polar[polarIndex].__ecIndicator[indicatorIndex] && this.polar[polarIndex].__ecIndicator[indicatorIndex].text;
    },

    /**
     * 添加一个隐形的盒子 当做drop的容器 暴露给外部的图形类使用
     * @param {number} polar的index
     * @return {Object} 添加的盒子图形
     */
    getDropBox: function (index) {
      var index = index || 0;
      var item = this.polar[index];
      var center = this.getCenter(index);
      var __ecIndicator = item.__ecIndicator;
      var len = __ecIndicator.length;
      var pointList = [];
      var vector;
      var shape;
      var type = item.type;

      if (type == 'polygon') {
        for (var i = 0; i < len; i++) {
          vector = __ecIndicator[i].vector;
          pointList.push(this._mapVector(vector, center, 1.2));
        }

        shape = this._getShape(pointList, 'fill', 'rgba(0,0,0,0)', '', 1);
      } else if (type == 'circle') {
        shape = this._getCircle('', 1, 1.2, center, 'fill', 'rgba(0,0,0,0)');
      }

      return shape;
    },

    /**
     * 绘制蜘蛛网的正n变形
     *
     * @param {Array<Object>} 指标数组
     * @param {number} 分割线数量
     * @param {Array<number>} 中点坐标
     * @param {Object} 分割区域对象
     * @param {string} 线条颜色
     * @param {number} 线条宽度
     */
    _addArea: function (__ecIndicator, splitNumber, center, splitArea, strokeColor, lineWidth, show) {
      var shape;
      var scale;
      var scale1;
      var pointList;
      var type = this.deepQuery(this._queryTarget, 'type');

      for (var i = 0; i < splitNumber; i++) {
        scale = (splitNumber - i) / splitNumber;

        if (show) {
          if (type == 'polygon') {
            pointList = this._getPointList(__ecIndicator, scale, center);
            shape = this._getShape(pointList, 'stroke', '', strokeColor, lineWidth);
          } else if (type == 'circle') {
            shape = this._getCircle(strokeColor, lineWidth, scale, center, 'stroke');
          }

          this.shapeList.push(shape);
        }

        if (splitArea.show) {
          scale1 = (splitNumber - i - 1) / splitNumber;

          this._addSplitArea(__ecIndicator, splitArea, scale, scale1, center, i);
        }
      }
    },

    /**
     * 绘制圆
     *
     * @param {string} strokeColor
     * @param {number} lineWidth
     * @param {number} scale
     * @param {Array.<number>} center
     * @param {string} brushType
     * @param {string} color
     * @return {Circle}
     */
    _getCircle: function (strokeColor, lineWidth, scale, center, brushType, color) {
      var radius = this._getRadius();

      return new Circle({
        zlevel: this.getZlevelBase(),
        z: this.getZBase(),
        style: {
          x: center[0],
          y: center[1],
          r: radius * scale,
          brushType: brushType,
          strokeColor: strokeColor,
          lineWidth: lineWidth,
          color: color
        },
        hoverable: false,
        draggable: false
      });
    },

    /**
     * 绘制圆环
     *
     * @param {string} color  间隔颜色
     * @param {number} scale0  小圆的scale
     * @param {number} scale1  大圆的scale
     * @param {Array.<number>} center  圆点
     * @return {Ring}
     */
    _getRing: function (color, scale0, scale1, center) {
      var radius = this._getRadius();

      return new Ring({
        zlevel: this.getZlevelBase(),
        z: this.getZBase(),
        style: {
          x: center[0],
          y: center[1],
          r: scale0 * radius,
          r0: scale1 * radius,
          color: color,
          brushType: 'fill'
        },
        hoverable: false,
        draggable: false
      });
    },

    /**
     * 获取需要绘制的多边形的点集
     * @param {Object} serie的指标参数
     * @param {number} 缩小的系数
     * @param {Array<number>} 中点坐标
     *
     * @return {Array<Array<number>>} 返回绘制的点集
     */
    _getPointList: function (__ecIndicator, scale, center) {
      var pointList = [];
      var len = __ecIndicator.length;
      var vector;

      for (var i = 0; i < len; i++) {
        vector = __ecIndicator[i].vector;
        pointList.push(this._mapVector(vector, center, scale));
      }

      return pointList;
    },

    /**
     * 获取绘制的图形
     * @param {Array<Array<number>>} 绘制的点集
     * @param {string} 绘制方式 stroke | fill | both 描边 | 填充 | 描边 + 填充
     * @param {string} 颜色
     * @param {string} 描边颜色
     * @param {number} 线条宽度
     * @return {Object} 绘制的图形对象
     */
    _getShape: function (pointList, brushType, color, strokeColor, lineWidth) {
      return new PolygonShape({
        zlevel: this.getZlevelBase(),
        z: this.getZBase(),
        style: {
          pointList: pointList,
          brushType: brushType,
          color: color,
          strokeColor: strokeColor,
          lineWidth: lineWidth
        },
        hoverable: false,
        draggable: false
      });
    },

    /**
     * 绘制填充区域
     */
    _addSplitArea: function (__ecIndicator, splitArea, scale, scale1, center, colorInd) {
      var indLen = __ecIndicator.length;
      var color;
      var colorArr = splitArea.areaStyle.color;
      var colorLen;
      var vector;
      var vector1;
      var pointList = [];
      var indLen = __ecIndicator.length;
      var shape;
      var type = this.deepQuery(this._queryTarget, 'type');

      if (typeof colorArr == 'string') {
        colorArr = [colorArr];
      }

      colorLen = colorArr.length;
      color = colorArr[colorInd % colorLen];

      if (type == 'polygon') {
        for (var i = 0; i < indLen; i++) {
          pointList = [];
          vector = __ecIndicator[i].vector;
          vector1 = __ecIndicator[(i + 1) % indLen].vector;
          pointList.push(this._mapVector(vector, center, scale));
          pointList.push(this._mapVector(vector, center, scale1));
          pointList.push(this._mapVector(vector1, center, scale1));
          pointList.push(this._mapVector(vector1, center, scale));
          shape = this._getShape(pointList, 'fill', color, '', 1);
          this.shapeList.push(shape);
        }
      } else if (type == 'circle') {
        shape = this._getRing(color, scale, scale1, center);
        this.shapeList.push(shape);
      }
    },

    /**
     * 转换坐标
     *
     * @param {Array<number>} 原始坐标
     * @param {Array<number>} 中点坐标
     * @param {number} 缩小的倍数
     *
     * @return {Array<number>} 转换后的坐标
     */
    _mapVector: function (vector, center, scale) {
      return [vector[0] * scale + center[0], vector[1] * scale + center[1]];
    },

    /**
     * 获取中心点位置 暴露给外部图形类使用
     * @param {number} polar的index
     */
    getCenter: function (index) {
      var index = index || 0;
      return this.parseCenter(this.zr, this.polar[index].center);
    },

    /**
     * 绘制从中点出发的线
     *
     * @param {Array<Object>} 指标对象
     * @param {Array<number>} 中点坐标
     * @param {string} 线条颜色
     * @param {number} 线条宽度
     * @param {string} 线条绘制类型
     *              solid | dotted | dashed 实线 | 点线 | 虚线
     */
    _addLine: function (__ecIndicator, center, axisLine) {
      var indLen = __ecIndicator.length;
      var line;
      var vector;
      var lineStyle = axisLine.lineStyle;
      var strokeColor = lineStyle.color;
      var lineWidth = lineStyle.width;
      var lineType = lineStyle.type;

      for (var i = 0; i < indLen; i++) {
        vector = __ecIndicator[i].vector;
        line = this._getLine(center[0], center[1], vector[0] + center[0], vector[1] + center[1], strokeColor, lineWidth, lineType);
        this.shapeList.push(line);
      }
    },

    /**
     * 获取线条对象
     * @param {number} 出发点横坐标
     * @param {number} 出发点纵坐标
     * @param {number} 终点横坐标
     * @param {number} 终点纵坐标
     * @param {string} 线条颜色
     * @param {number} 线条宽度
     * @param {string} 线条类型
     *
     * @return {Object} 线条对象
     */
    _getLine: function (xStart, yStart, xEnd, yEnd, strokeColor, lineWidth, lineType) {
      return new LineShape({
        zlevel: this.getZlevelBase(),
        z: this.getZBase(),
        style: {
          xStart: xStart,
          yStart: yStart,
          xEnd: xEnd,
          yEnd: yEnd,
          strokeColor: strokeColor,
          lineWidth: lineWidth,
          lineType: lineType
        },
        hoverable: false
      });
    },

    /**
     * 调整指标的值，当indicator中存在max时设置为固定值
     * @param {number} polar的index
     */
    _adjustIndicatorValue: function (index) {
      var item = this.polar[index];
      var indicator = this.deepQuery(this._queryTarget, 'indicator');
      var len = indicator.length;
      var __ecIndicator = item.__ecIndicator;
      var max;
      var min;

      var data = this._getSeriesData(index);

      var boundaryGap = item.boundaryGap;
      var splitNumber = item.splitNumber;
      var scale = item.scale;
      var opts;

      var smartSteps = require('../util/smartSteps');

      for (var i = 0; i < len; i++) {
        if (typeof indicator[i].max == 'number') {
          max = indicator[i].max;
          min = indicator[i].min || 0;
          opts = {
            max: max,
            min: min
          };
        } else {
          var value = this._findValue(data, i, splitNumber, boundaryGap);

          min = value.min;
          max = value.max;
        } // 非scale下双正，修正最小值为0


        if (!scale && min >= 0 && max >= 0) {
          min = 0;
        } // 非scale下双负，修正最大值为0


        if (!scale && min <= 0 && max <= 0) {
          max = 0;
        }

        var stepOpt = smartSteps(min, max, splitNumber, opts);
        __ecIndicator[i].value = {
          min: stepOpt.min,
          max: stepOpt.max,
          step: stepOpt.step
        };
      }
    },

    /**
     * 将series中的数据拿出来，如果没有polarIndex属性，默认为零
     * @param {number} polar 的index
     * @param {Array<Object>} 需要处理的数据
     */
    _getSeriesData: function (index) {
      var data = [];
      var serie;
      var serieData;
      var legend = this.component.legend;
      var polarIndex;

      for (var i = 0; i < this.series.length; i++) {
        serie = this.series[i];

        if (serie.type != ecConfig.CHART_TYPE_RADAR) {
          continue;
        }

        serieData = serie.data || [];

        for (var j = 0; j < serieData.length; j++) {
          polarIndex = this.deepQuery([serieData[j], serie, this.option], 'polarIndex') || 0;

          if (polarIndex == index && (!legend || legend.isSelected(serieData[j].name))) {
            data.push(serieData[j]);
          }
        }
      }

      return data;
    },

    /**
     * 查找指标合适的值
     *
     * 如果只有一组数据以数据中的最大值作为最大值 0为最小值
     * 如果是多组，使用同一维度的进行比较 选出最大值最小值
     * 对它们进行处理
     * @param {Object} serie 的 data
     * @param {number} index 指标的序号
     * @param {number} splitNumber 分段格式
     * * @param {boolean} boundaryGap 两端留白
     */
    _findValue: function (data, index, splitNumber, boundaryGap) {
      var max;
      var min;
      var one;

      if (!data || data.length === 0) {
        return;
      }

      function _compare(item) {
        (item > max || max === undefined) && (max = item);
        (item < min || min === undefined) && (min = item);
      }

      if (data.length == 1) {
        min = 0;
      }

      if (data.length != 1) {
        for (var i = 0; i < data.length; i++) {
          _compare(this.getDataFromOption(data[i].value[index]));
        }
      } else {
        one = data[0];

        for (var i = 0; i < one.value.length; i++) {
          _compare(this.getDataFromOption(one.value[i]));
        }
      }

      var gap = Math.abs(max - min);
      min = min - Math.abs(gap * boundaryGap[0]);
      max = max + Math.abs(gap * boundaryGap[1]);

      if (min === max) {
        if (max === 0) {
          // 修复全0数据
          max = 1;
        } // 修复最大值==最小值时数据整形
        else if (max > 0) {
          min = max / splitNumber;
        } else {
          // max < 0
          max = max / splitNumber;
        }
      }

      return {
        max: max,
        min: min
      };
    },

    /**
     * 获取每个指标上某个value对应的坐标
     * @param {number} polarIndex
     * @param {number} indicatorIndex
     * @param {number} value
     * @return {Array<number>} 对应坐标
     */
    getVector: function (polarIndex, indicatorIndex, value) {
      polarIndex = polarIndex || 0;
      indicatorIndex = indicatorIndex || 0;
      var __ecIndicator = this.polar[polarIndex].__ecIndicator;

      if (indicatorIndex >= __ecIndicator.length) {
        return;
      }

      var indicator = this.polar[polarIndex].__ecIndicator[indicatorIndex];
      var center = this.getCenter(polarIndex);
      var vector = indicator.vector;
      var max = indicator.value.max;
      var min = indicator.value.min;
      var alpha;

      if (typeof value == 'undefined') {
        return center;
      }

      switch (value) {
        case 'min':
          value = min;
          break;

        case 'max':
          value = max;
          break;

        case 'center':
          value = (max + min) / 2;
          break;
      }

      if (max != min) {
        alpha = (value - min) / (max - min);
      } else {
        alpha = 0.5;
      }

      return this._mapVector(vector, center, alpha);
    },

    /**
     * 判断一个点是否在网内
     * @param {Array<number>} 坐标
     * @return {number} 返回polarindex  返回-1表示不在任何polar
     */
    isInside: function (vector) {
      var polar = this.getNearestIndex(vector);

      if (polar) {
        return polar.polarIndex;
      }

      return -1;
    },

    /**
     * 如果一个点在网内，返回离它最近的数据轴的index
     * @param {Array<number>} 坐标
     * @return {Object} | false
     *      polarIndex
     *      valueIndex
     */
    getNearestIndex: function (vector) {
      var item;
      var center;
      var radius;
      var polarVector;
      var startAngle;
      var indicator;
      var len;
      var angle;
      var finalAngle;

      for (var i = 0; i < this.polar.length; i++) {
        item = this.polar[i];
        center = this.getCenter(i);

        if (vector[0] == center[0] && vector[1] == center[1]) {
          return {
            polarIndex: i,
            valueIndex: 0
          };
        }

        radius = this._getRadius();
        startAngle = item.startAngle;
        indicator = item.indicator;
        len = indicator.length;
        angle = 2 * Math.PI / len; // 注意y轴的翻转

        polarVector = ecCoordinates.cartesian2polar(vector[0] - center[0], center[1] - vector[1]);

        if (vector[0] - center[0] < 0) {
          polarVector[1] += Math.PI;
        }

        if (polarVector[1] < 0) {
          polarVector[1] += 2 * Math.PI;
        } // 减去startAngle的偏移量 再加2PI变成正数


        finalAngle = polarVector[1] - startAngle / 180 * Math.PI + Math.PI * 2;

        if (Math.abs(Math.cos(finalAngle % (angle / 2))) * radius > polarVector[0]) {
          return {
            polarIndex: i,
            valueIndex: Math.floor((finalAngle + angle / 2) / angle) % len
          };
        }
      }
    },

    /**
     * 获取指标信息
     * @param {number} polarIndex
     * @return {Array<Object>} indicator
     */
    getIndicator: function (index) {
      var index = index || 0;
      return this.polar[index].indicator;
    },

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

      this.clear();

      this._buildShape();
    }
  };
  zrUtil.inherits(Polar, Base);

  require('../component').define('polar', Polar);

  return Polar;
}(require);