/**
 * echarts扩展zrender shape
 *
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 * shape类：icon
 * 可配图形属性：
   {
       // 基础属性
       shape  : 'icon',       // 必须，shape类标识，需要显式指定
       id     : {string},       // 必须，图形唯一标识，可通过'zrender/tool/guid'方法生成
       zlevel : {number},       // 默认为0，z层level，决定绘画在哪层canvas中
       invisible : {boolean},   // 默认为false，是否可见

       // 样式属性，默认状态样式样式属性
       style  : {
           x             : {number},  // 必须，左上角横坐标
           y             : {number},  // 必须，左上角纵坐标
           width         : {number},  // 必须，宽度
           height        : {number},  // 必须，高度
           iconType      : {string},  // 必须，icon类型
       },

       // 样式属性，高亮样式属性，当不存在highlightStyle时使用基于默认样式扩展显示
       highlightStyle : {
           // 同style
       }

       // 交互属性，详见shape.Base

       // 事件属性，详见shape.Base
   }
 */
module.exports = function (require) {
  var zrUtil = require('zrender/tool/util');

  function _iconMark(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x, y + style.height);
    ctx.lineTo(x + 5 * dx, y + 14 * dy);
    ctx.lineTo(x + style.width, y + 3 * dy);
    ctx.lineTo(x + 13 * dx, y);
    ctx.lineTo(x + 2 * dx, y + 11 * dy);
    ctx.lineTo(x, y + style.height);
    ctx.moveTo(x + 6 * dx, y + 10 * dy);
    ctx.lineTo(x + 14 * dx, y + 2 * dy);
    ctx.moveTo(x + 10 * dx, y + 13 * dy);
    ctx.lineTo(x + style.width, y + 13 * dy);
    ctx.moveTo(x + 13 * dx, y + 10 * dy);
    ctx.lineTo(x + 13 * dx, y + style.height);
  }

  function _iconMarkUndo(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x, y + style.height);
    ctx.lineTo(x + 5 * dx, y + 14 * dy);
    ctx.lineTo(x + style.width, y + 3 * dy);
    ctx.lineTo(x + 13 * dx, y);
    ctx.lineTo(x + 2 * dx, y + 11 * dy);
    ctx.lineTo(x, y + style.height);
    ctx.moveTo(x + 6 * dx, y + 10 * dy);
    ctx.lineTo(x + 14 * dx, y + 2 * dy);
    ctx.moveTo(x + 10 * dx, y + 13 * dy);
    ctx.lineTo(x + style.width, y + 13 * dy);
  }

  function _iconMarkClear(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x + 4 * dx, y + 15 * dy);
    ctx.lineTo(x + 9 * dx, y + 13 * dy);
    ctx.lineTo(x + 14 * dx, y + 8 * dy);
    ctx.lineTo(x + 11 * dx, y + 5 * dy);
    ctx.lineTo(x + 6 * dx, y + 10 * dy);
    ctx.lineTo(x + 4 * dx, y + 15 * dy);
    ctx.moveTo(x + 5 * dx, y);
    ctx.lineTo(x + 11 * dx, y);
    ctx.moveTo(x + 5 * dx, y + dy);
    ctx.lineTo(x + 11 * dx, y + dy);
    ctx.moveTo(x, y + 2 * dy);
    ctx.lineTo(x + style.width, y + 2 * dy);
    ctx.moveTo(x, y + 5 * dy);
    ctx.lineTo(x + 3 * dx, y + style.height);
    ctx.lineTo(x + 13 * dx, y + style.height);
    ctx.lineTo(x + style.width, y + 5 * dy);
  }

  function _iconDataZoom(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x, y + 3 * dy);
    ctx.lineTo(x + 6 * dx, y + 3 * dy);
    ctx.moveTo(x + 3 * dx, y);
    ctx.lineTo(x + 3 * dx, y + 6 * dy);
    ctx.moveTo(x + 3 * dx, y + 8 * dy);
    ctx.lineTo(x + 3 * dx, y + style.height);
    ctx.lineTo(x + style.width, y + style.height);
    ctx.lineTo(x + style.width, y + 3 * dy);
    ctx.lineTo(x + 8 * dx, y + 3 * dy);
  }

  function _iconDataZoomReset(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x + 6 * dx, y);
    ctx.lineTo(x + 2 * dx, y + 3 * dy);
    ctx.lineTo(x + 6 * dx, y + 6 * dy);
    ctx.moveTo(x + 2 * dx, y + 3 * dy);
    ctx.lineTo(x + 14 * dx, y + 3 * dy);
    ctx.lineTo(x + 14 * dx, y + 11 * dy);
    ctx.moveTo(x + 2 * dx, y + 5 * dy);
    ctx.lineTo(x + 2 * dx, y + 13 * dy);
    ctx.lineTo(x + 14 * dx, y + 13 * dy);
    ctx.moveTo(x + 10 * dx, y + 10 * dy);
    ctx.lineTo(x + 14 * dx, y + 13 * dy);
    ctx.lineTo(x + 10 * dx, y + style.height);
  }

  function _iconRestore(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    var r = style.width / 2;
    ctx.lineWidth = 1.5;
    ctx.arc(x + r, y + r, r - dx, 0, Math.PI * 2 / 3);
    ctx.moveTo(x + 3 * dx, y + style.height);
    ctx.lineTo(x + 0 * dx, y + 12 * dy);
    ctx.lineTo(x + 5 * dx, y + 11 * dy);
    ctx.moveTo(x, y + 8 * dy);
    ctx.arc(x + r, y + r, r - dx, Math.PI, Math.PI * 5 / 3);
    ctx.moveTo(x + 13 * dx, y);
    ctx.lineTo(x + style.width, y + 4 * dy);
    ctx.lineTo(x + 11 * dx, y + 5 * dy);
  }

  function _iconLineChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x, y);
    ctx.lineTo(x, y + style.height);
    ctx.lineTo(x + style.width, y + style.height);
    ctx.moveTo(x + 2 * dx, y + 14 * dy);
    ctx.lineTo(x + 7 * dx, y + 6 * dy);
    ctx.lineTo(x + 11 * dx, y + 11 * dy);
    ctx.lineTo(x + 15 * dx, y + 2 * dy);
  }

  function _iconBarChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x, y);
    ctx.lineTo(x, y + style.height);
    ctx.lineTo(x + style.width, y + style.height);
    ctx.moveTo(x + 3 * dx, y + 14 * dy);
    ctx.lineTo(x + 3 * dx, y + 6 * dy);
    ctx.lineTo(x + 4 * dx, y + 6 * dy);
    ctx.lineTo(x + 4 * dx, y + 14 * dy);
    ctx.moveTo(x + 7 * dx, y + 14 * dy);
    ctx.lineTo(x + 7 * dx, y + 2 * dy);
    ctx.lineTo(x + 8 * dx, y + 2 * dy);
    ctx.lineTo(x + 8 * dx, y + 14 * dy);
    ctx.moveTo(x + 11 * dx, y + 14 * dy);
    ctx.lineTo(x + 11 * dx, y + 9 * dy);
    ctx.lineTo(x + 12 * dx, y + 9 * dy);
    ctx.lineTo(x + 12 * dx, y + 14 * dy);
  }

  function _iconPieChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var width = style.width - 2;
    var height = style.height - 2;
    var r = Math.min(width, height) / 2;
    y += 2;
    ctx.moveTo(x + r + 3, y + r - 3);
    ctx.arc(x + r + 3, y + r - 3, r - 1, 0, -Math.PI / 2, true);
    ctx.lineTo(x + r + 3, y + r - 3);
    ctx.moveTo(x + r, y);
    ctx.lineTo(x + r, y + r);
    ctx.arc(x + r, y + r, r, -Math.PI / 2, Math.PI * 2, true);
    ctx.lineTo(x + r, y + r);
    ctx.lineWidth = 1.5;
  }

  function _iconFunnelChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    y -= dy;
    ctx.moveTo(x + 1 * dx, y + 2 * dy);
    ctx.lineTo(x + 15 * dx, y + 2 * dy);
    ctx.lineTo(x + 14 * dx, y + 3 * dy);
    ctx.lineTo(x + 2 * dx, y + 3 * dy);
    ctx.moveTo(x + 3 * dx, y + 6 * dy);
    ctx.lineTo(x + 13 * dx, y + 6 * dy);
    ctx.lineTo(x + 12 * dx, y + 7 * dy);
    ctx.lineTo(x + 4 * dx, y + 7 * dy);
    ctx.moveTo(x + 5 * dx, y + 10 * dy);
    ctx.lineTo(x + 11 * dx, y + 10 * dy);
    ctx.lineTo(x + 10 * dx, y + 11 * dy);
    ctx.lineTo(x + 6 * dx, y + 11 * dy);
    ctx.moveTo(x + 7 * dx, y + 14 * dy);
    ctx.lineTo(x + 9 * dx, y + 14 * dy);
    ctx.lineTo(x + 8 * dx, y + 15 * dy);
    ctx.lineTo(x + 7 * dx, y + 15 * dy);
  }

  function _iconForceChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var width = style.width;
    var height = style.height;
    var dx = width / 16;
    var dy = height / 16;
    var r = Math.min(dx, dy) * 2;
    ctx.moveTo(x + dx + r, y + dy + r);
    ctx.arc(x + dx, y + dy, r, Math.PI / 4, Math.PI * 3);
    ctx.lineTo(x + 7 * dx - r, y + 6 * dy - r);
    ctx.arc(x + 7 * dx, y + 6 * dy, r, Math.PI / 4 * 5, Math.PI * 4);
    ctx.arc(x + 7 * dx, y + 6 * dy, r / 2, Math.PI / 4 * 5, Math.PI * 4);
    ctx.moveTo(x + 7 * dx - r / 2, y + 6 * dy + r);
    ctx.lineTo(x + dx + r, y + 14 * dy - r);
    ctx.arc(x + dx, y + 14 * dy, r, -Math.PI / 4, Math.PI * 2);
    ctx.moveTo(x + 7 * dx + r / 2, y + 6 * dy);
    ctx.lineTo(x + 14 * dx - r, y + 10 * dy - r / 2);
    ctx.moveTo(x + 16 * dx, y + 10 * dy);
    ctx.arc(x + 14 * dx, y + 10 * dy, r, 0, Math.PI * 3);
    ctx.lineWidth = 1.5;
  }

  function _iconChordChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var width = style.width;
    var height = style.height;
    var r = Math.min(width, height) / 2;
    ctx.moveTo(x + width, y + height / 2);
    ctx.arc(x + r, y + r, r, 0, Math.PI * 2);
    ctx.arc(x + r, y, r, Math.PI / 4, Math.PI / 5 * 4);
    ctx.arc(x, y + r, r, -Math.PI / 3, Math.PI / 3);
    ctx.arc(x + width, y + height, r, Math.PI, Math.PI / 2 * 3);
    ctx.lineWidth = 1.5;
  }

  function _iconStackChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var width = style.width;
    var height = style.height;
    var dy = Math.round(height / 3);
    var delta = Math.round((dy - 2) / 2);
    var len = 3;

    while (len--) {
      ctx.rect(x, y + dy * len + delta, width, 2);
    }
  }

  function _iconTiledChart(ctx, style) {
    var x = style.x;
    var y = style.y;
    var width = style.width;
    var height = style.height;
    var dx = Math.round(width / 3);
    var delta = Math.round((dx - 2) / 2);
    var len = 3;

    while (len--) {
      ctx.rect(x + dx * len + delta, y, 2, height);
    }
  }

  function _iconDataView(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    ctx.moveTo(x + dx, y);
    ctx.lineTo(x + dx, y + style.height);
    ctx.lineTo(x + 15 * dx, y + style.height);
    ctx.lineTo(x + 15 * dx, y);
    ctx.lineTo(x + dx, y);
    ctx.moveTo(x + 3 * dx, y + 3 * dx);
    ctx.lineTo(x + 13 * dx, y + 3 * dx);
    ctx.moveTo(x + 3 * dx, y + 6 * dx);
    ctx.lineTo(x + 13 * dx, y + 6 * dx);
    ctx.moveTo(x + 3 * dx, y + 9 * dx);
    ctx.lineTo(x + 13 * dx, y + 9 * dx);
    ctx.moveTo(x + 3 * dx, y + 12 * dx);
    ctx.lineTo(x + 9 * dx, y + 12 * dx);
  }

  function _iconSave(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    var dy = style.height / 16;
    ctx.moveTo(x, y);
    ctx.lineTo(x, y + style.height);
    ctx.lineTo(x + style.width, y + style.height);
    ctx.lineTo(x + style.width, y);
    ctx.lineTo(x, y);
    ctx.moveTo(x + 4 * dx, y);
    ctx.lineTo(x + 4 * dx, y + 8 * dy);
    ctx.lineTo(x + 12 * dx, y + 8 * dy);
    ctx.lineTo(x + 12 * dx, y);
    ctx.moveTo(x + 6 * dx, y + 11 * dy);
    ctx.lineTo(x + 6 * dx, y + 13 * dy);
    ctx.lineTo(x + 10 * dx, y + 13 * dy);
    ctx.lineTo(x + 10 * dx, y + 11 * dy);
    ctx.lineTo(x + 6 * dx, y + 11 * dy);
  }

  function _iconCross(ctx, style) {
    var x = style.x;
    var y = style.y;
    var width = style.width;
    var height = style.height;
    ctx.moveTo(x, y + height / 2);
    ctx.lineTo(x + width, y + height / 2);
    ctx.moveTo(x + width / 2, y);
    ctx.lineTo(x + width / 2, y + height);
  }

  function _iconCircle(ctx, style) {
    var width = style.width / 2;
    var height = style.height / 2;
    var r = Math.min(width, height);
    ctx.moveTo(style.x + width + r, style.y + height);
    ctx.arc(style.x + width, style.y + height, r, 0, Math.PI * 2);
    ctx.closePath();
  }

  function _iconRectangle(ctx, style) {
    ctx.rect(style.x, style.y, style.width, style.height);
    ctx.closePath();
  }

  function _iconTriangle(ctx, style) {
    var width = style.width / 2;
    var height = style.height / 2;
    var x = style.x + width;
    var y = style.y + height;
    var symbolSize = Math.min(width, height);
    ctx.moveTo(x, y - symbolSize);
    ctx.lineTo(x + symbolSize, y + symbolSize);
    ctx.lineTo(x - symbolSize, y + symbolSize);
    ctx.lineTo(x, y - symbolSize);
    ctx.closePath();
  }

  function _iconDiamond(ctx, style) {
    var width = style.width / 2;
    var height = style.height / 2;
    var x = style.x + width;
    var y = style.y + height;
    var symbolSize = Math.min(width, height);
    ctx.moveTo(x, y - symbolSize);
    ctx.lineTo(x + symbolSize, y);
    ctx.lineTo(x, y + symbolSize);
    ctx.lineTo(x - symbolSize, y);
    ctx.lineTo(x, y - symbolSize);
    ctx.closePath();
  }

  function _iconArrow(ctx, style) {
    var x = style.x;
    var y = style.y;
    var dx = style.width / 16;
    ctx.moveTo(x + 8 * dx, y);
    ctx.lineTo(x + dx, y + style.height);
    ctx.lineTo(x + 8 * dx, y + style.height / 4 * 3);
    ctx.lineTo(x + 15 * dx, y + style.height);
    ctx.lineTo(x + 8 * dx, y);
    ctx.closePath();
  }

  function _iconStar(ctx, style) {
    var StarShape = require('zrender/shape/Star');

    var width = style.width / 2;
    var height = style.height / 2;
    StarShape.prototype.buildPath(ctx, {
      x: style.x + width,
      y: style.y + height,
      r: Math.min(width, height),
      n: style.n || 5
    });
  }

  function _iconHeart(ctx, style) {
    var HeartShape = require('zrender/shape/Heart');

    HeartShape.prototype.buildPath(ctx, {
      x: style.x + style.width / 2,
      y: style.y + style.height * 0.2,
      a: style.width / 2,
      b: style.height * 0.8
    });
  }

  function _iconDroplet(ctx, style) {
    var DropletShape = require('zrender/shape/Droplet');

    DropletShape.prototype.buildPath(ctx, {
      x: style.x + style.width * 0.5,
      y: style.y + style.height * 0.5,
      a: style.width * 0.5,
      b: style.height * 0.8
    });
  }

  function _iconPin(ctx, style) {
    var x = style.x;
    var y = style.y - style.height / 2 * 1.5;
    var width = style.width / 2;
    var height = style.height / 2;
    var r = Math.min(width, height);
    ctx.arc(x + width, y + height, r, Math.PI / 5 * 4, Math.PI / 5);
    ctx.lineTo(x + width, y + height + r * 1.5);
    ctx.closePath();
  }

  function _iconImage(ctx, style, refreshNextFrame) {
    var ImageShape = require('zrender/shape/Image');

    this._imageShape = this._imageShape || new ImageShape({
      style: {}
    });

    for (var name in style) {
      this._imageShape.style[name] = style[name];
    }

    this._imageShape.brush(ctx, false, refreshNextFrame);
  }

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

  function Icon(options) {
    Base.call(this, options);
  }

  Icon.prototype = {
    type: 'icon',
    iconLibrary: {
      mark: _iconMark,
      markUndo: _iconMarkUndo,
      markClear: _iconMarkClear,
      dataZoom: _iconDataZoom,
      dataZoomReset: _iconDataZoomReset,
      restore: _iconRestore,
      lineChart: _iconLineChart,
      barChart: _iconBarChart,
      pieChart: _iconPieChart,
      funnelChart: _iconFunnelChart,
      forceChart: _iconForceChart,
      chordChart: _iconChordChart,
      stackChart: _iconStackChart,
      tiledChart: _iconTiledChart,
      dataView: _iconDataView,
      saveAsImage: _iconSave,
      cross: _iconCross,
      circle: _iconCircle,
      rectangle: _iconRectangle,
      triangle: _iconTriangle,
      diamond: _iconDiamond,
      arrow: _iconArrow,
      star: _iconStar,
      heart: _iconHeart,
      droplet: _iconDroplet,
      pin: _iconPin,
      image: _iconImage
    },
    brush: function (ctx, isHighlight, refreshNextFrame) {
      var style = isHighlight ? this.highlightStyle : this.style;
      style = style || {};
      var iconType = style.iconType || this.style.iconType;

      if (iconType === 'image') {
        var ImageShape = require('zrender/shape/Image');

        ImageShape.prototype.brush.call(this, ctx, isHighlight, refreshNextFrame);
      } else {
        var style = this.beforeBrush(ctx, isHighlight);
        ctx.beginPath();
        this.buildPath(ctx, style, refreshNextFrame);

        switch (style.brushType) {
          /* jshint ignore:start */
          case 'both':
            ctx.fill();

          case 'stroke':
            style.lineWidth > 0 && ctx.stroke();
            break;

          /* jshint ignore:end */

          default:
            ctx.fill();
        }

        this.drawText(ctx, style, this.style);
        this.afterBrush(ctx);
      }
    },

    /**
     * 创建矩形路径
     * @param {Context2D} ctx Canvas 2D上下文
     * @param {Object} style 样式
     */
    buildPath: function (ctx, style, refreshNextFrame) {
      if (this.iconLibrary[style.iconType]) {
        this.iconLibrary[style.iconType].call(this, ctx, style, refreshNextFrame);
      } else {
        ctx.moveTo(style.x, style.y);
        ctx.lineTo(style.x + style.width, style.y);
        ctx.lineTo(style.x + style.width, style.y + style.height);
        ctx.lineTo(style.x, style.y + style.height);
        ctx.lineTo(style.x, style.y);
        ctx.closePath();
      }

      return;
    },

    /**
     * 返回矩形区域，用于局部刷新和文字定位
     * @param {Object} style
     */
    getRect: function (style) {
      if (style.__rect) {
        return style.__rect;
      } // pin比较特殊，让尖端在目标x,y上


      style.__rect = {
        x: Math.round(style.x),
        y: Math.round(style.y - (style.iconType == 'pin' ? style.height / 2 * 1.5 : 0)),
        width: style.width,
        height: style.height * (style.iconType === 'pin' ? 1.25 : 1)
      };
      return style.__rect;
    },
    isCover: function (x, y) {
      var originPos = this.transformCoordToLocal(x, y);
      x = originPos[0];
      y = originPos[1]; // 快速预判并保留判断矩形

      var rect = this.style.__rect;

      if (!rect) {
        rect = this.style.__rect = this.getRect(this.style);
      } // 提高交互体验，太小的图形包围盒四向扩大4px


      var delta = rect.height < 8 || rect.width < 8 ? 4 : 0;
      return x >= rect.x - delta && x <= rect.x + rect.width + delta && y >= rect.y - delta && y <= rect.y + rect.height + delta;
    }
  };
  zrUtil.inherits(Icon, Base);
  return Icon;
}(require);