/**
 * zrender
 *
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *         Yi Shen(https://github.com/pissang)
 *
 * shape类：标线
 */

/**
 * @typedef {Object} IMarkLineStyle
 * @property {number} xStart 起点x坐标
 * @property {number} yStart 起点y坐标
 * @property {number} xEnd 终止点x坐标
 * @property {number} yEnd 终止点y坐标
 * @property {number} cpX1 控制点x坐标，可以使用updatePoints自动根据curveness计算
 * @property {number} cpY1 控制点y坐标，可以使用updatePoints自动根据curveness计算
 * @property {number} curveness 曲度
 * @property {Array.<string>} symbol
 * @property {Array.<number>} symbolRotate
 */
module.exports = function (require) {
  var Base = require('zrender/shape/Base');

  var IconShape = require('./Icon');

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

  var lineInstance = new LineShape({});

  var CurveShape = require('zrender/shape/BezierCurve');

  var curveInstance = new CurveShape({});

  var area = require('zrender/tool/area');

  var dashedLineTo = require('zrender/shape/util/dashedLineTo');

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

  var curveTool = require('zrender/tool/curve');

  function MarkLine(options) {
    Base.call(this, options);

    if (this.style.curveness > 0) {
      this.updatePoints(this.style);
    }

    if (this.highlightStyle.curveness > 0) {
      this.updatePoints(this.highlightStyle);
    }
  }

  MarkLine.prototype = {
    type: 'mark-line',

    /**
     * 画刷
     * @param ctx 画布句柄
     * @param isHighlight   是否为高亮状态
     * @param updateCallback 让painter更新视图，base.brush没用，需要的话重载brush
     */
    brush: function (ctx, isHighlight) {
      var style = this.style;

      if (isHighlight) {
        // 根据style扩展默认高亮样式
        style = this.getHighlightStyle(style, this.highlightStyle || {});
      }

      ctx.save();
      this.setContext(ctx, style); // 设置transform

      this.setTransform(ctx);
      ctx.save();
      ctx.beginPath();
      this.buildPath(ctx, style);
      ctx.stroke();
      ctx.restore();
      this.brushSymbol(ctx, style, 0);
      this.brushSymbol(ctx, style, 1);
      this.drawText(ctx, style, this.style);
      ctx.restore();
    },

    /**
     * 创建线条路径
     * @param {Context2D} ctx Canvas 2D上下文
     * @param {Object} style 样式
     */
    buildPath: function (ctx, style) {
      var lineType = style.lineType || 'solid';
      ctx.moveTo(style.xStart, style.yStart);

      if (style.curveness > 0) {
        // FIXME Bezier 在少部分浏览器上暂时不支持虚线
        var lineDash = null;

        switch (lineType) {
          case 'dashed':
            lineDash = [5, 5];
            break;

          case 'dotted':
            lineDash = [1, 1];
            break;
        }

        if (lineDash && ctx.setLineDash) {
          ctx.setLineDash(lineDash);
        }

        ctx.quadraticCurveTo(style.cpX1, style.cpY1, style.xEnd, style.yEnd);
      } else {
        if (lineType == 'solid') {
          ctx.lineTo(style.xEnd, style.yEnd);
        } else {
          var dashLength = (style.lineWidth || 1) * (style.lineType == 'dashed' ? 5 : 1);
          dashedLineTo(ctx, style.xStart, style.yStart, style.xEnd, style.yEnd, dashLength);
        }
      }
    },

    /**
     * Update cpX1 and cpY1 according to curveniss
     * @param  {Object} style
     */
    updatePoints: function (style) {
      var curveness = style.curveness || 0;
      var inv = 1;
      var x0 = style.xStart;
      var y0 = style.yStart;
      var x2 = style.xEnd;
      var y2 = style.yEnd;
      var x1 = (x0 + x2) / 2 - inv * (y0 - y2) * curveness;
      var y1 = (y0 + y2) / 2 - inv * (x2 - x0) * curveness;
      style.cpX1 = x1;
      style.cpY1 = y1;
    },

    /**
     * 标线始末标注
     */
    brushSymbol: function (ctx, style, idx) {
      if (style.symbol[idx] == 'none') {
        return;
      }

      ctx.save();
      ctx.beginPath();
      ctx.lineWidth = style.symbolBorder;
      ctx.strokeStyle = style.symbolBorderColor; // symbol

      var symbol = style.symbol[idx].replace('empty', '').toLowerCase();

      if (style.symbol[idx].match('empty')) {
        ctx.fillStyle = '#fff'; //'rgba(0, 0, 0, 0)';
      } // symbolRotate


      var x0 = style.xStart;
      var y0 = style.yStart;
      var x2 = style.xEnd;
      var y2 = style.yEnd;
      var x = idx === 0 ? x0 : x2;
      var y = idx === 0 ? y0 : y2;
      var curveness = style.curveness || 0;
      var rotate = style.symbolRotate[idx] != null ? style.symbolRotate[idx] - 0 : 0;
      rotate = rotate / 180 * Math.PI;

      if (symbol == 'arrow' && rotate === 0) {
        if (curveness === 0) {
          var sign = idx === 0 ? -1 : 1;
          rotate = Math.PI / 2 + Math.atan2(sign * (y2 - y0), sign * (x2 - x0));
        } else {
          var x1 = style.cpX1;
          var y1 = style.cpY1;
          var quadraticDerivativeAt = curveTool.quadraticDerivativeAt;
          var dx = quadraticDerivativeAt(x0, x1, x2, idx);
          var dy = quadraticDerivativeAt(y0, y1, y2, idx);
          rotate = Math.PI / 2 + Math.atan2(dy, dx);
        }
      }

      ctx.translate(x, y);

      if (rotate !== 0) {
        ctx.rotate(rotate);
      } // symbolSize


      var symbolSize = style.symbolSize[idx];
      IconShape.prototype.buildPath(ctx, {
        x: -symbolSize,
        y: -symbolSize,
        width: symbolSize * 2,
        height: symbolSize * 2,
        iconType: symbol
      });
      ctx.closePath();
      ctx.fill();
      ctx.stroke();
      ctx.restore();
    },

    /**
     * 返回矩形区域，用于局部刷新和文字定位
     * @param {Object} style
     */
    getRect: function (style) {
      style.curveness > 0 ? curveInstance.getRect(style) : lineInstance.getRect(style);
      return style.__rect;
    },
    isCover: function (x, y) {
      var originPos = this.transformCoordToLocal(x, y);
      x = originPos[0];
      y = originPos[1]; // 快速预判并保留判断矩形

      if (this.isCoverRect(x, y)) {
        // 矩形内
        return this.style.curveness > 0 ? area.isInside(curveInstance, this.style, x, y) : area.isInside(lineInstance, this.style, x, y);
      }

      return false;
    }
  };
  zrUtil.inherits(MarkLine, Base);
  return MarkLine;
}(require);