/**

 * 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

   }

 */

define(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;

});