jui.define("chart.widget.legend", [ "util.base" ], function(_) {
    var WIDTH = 17, HEIGHT = 13, PADDING = 5, RADIUS = 5.5, RATIO = 1.2, POINT = 2;

    /**
     * @class chart.widget.legend
     * implements legend widget
     * @extends chart.widget.core
     * @alias LegendWidget
     * @requires util.base
     *
     */
    var LegendWidget = function(chart, axis, widget) {
        var columns = [];
        var colorIndex = {};

        function getIndexArray(brush) {
            var list = [ 0 ];

            if(_.typeCheck("array", brush)) {
                list = brush;
            } else if(_.typeCheck("integer", brush)) {
                list = [ brush ];
            }

            return list;
        }

        function getBrushAll() {
            var list = getIndexArray(widget.brush),
                result = [];

            for(var i = 0; i < list.length; i++) {
                result[i] = chart.get("brush", list[i]);
            }

            return result;
        }

        function setLegendStatus(brush) {
            if(!widget.filter) return;

            if(!columns[brush.index]) {
                columns[brush.index] = {};
            }

            for(var i = 0; i < brush.target.length; i++) {
                columns[brush.index][brush.target[i]] = true;
            }
        }

        function changeTargetOption(brushList) {
            var target = [],
                colors = [],
                index = brushList[0].index;

            for(var key in columns[index]) {
                if(columns[index][key]) {
                    target.push(key);
                    colors.push(colorIndex[key]);
                }
            }

            for(var i = 0; i < brushList.length; i++) {
                chart.updateBrush(brushList[i].index, {
                    target: target,
                    colors: colors
                });
            }

            // 차트 렌더링이 활성화되지 않았을 경우
            if(!chart.isRender()) {
                chart.render();
            }

            chart.emit("legend.filter", [ target ]);
        }

		this.getLegendIcon = function(brush) {
            var arr = [],
                data = brush.target,
                count = data.length;
			
			for(var i = 0; i < count; i++) {
                var group = chart.svg.group(),
                    target = brush.target[i],
                    text = target,
                    color = chart.color(i, widget.colors || brush.colors);

                // 컬러 인덱스 설정
                colorIndex[target] = color;

                // 타겟 별 포맷 설정
                if(_.typeCheck("function", widget.format)) {
                    text = this.format(target);
                }

                // 텍스트 길이 구하기
                var rect = chart.svg.getTextSize(text, {
                    fontSize : chart.theme('legendFontSize')
                });

                if(widget.filter) {
                    group.append(chart.svg.line({
                        x1: 0,
                        x2: WIDTH,
                        y1: -(RADIUS / 2),
                        y2: -(RADIUS / 2),
                        stroke: color,
                        "stroke-width": HEIGHT,
                        "stroke-linecap": "round"
                    }));

                    group.append(chart.svg.circle({
                        cx : WIDTH,
                        cy : -(RADIUS / 2),
                        r : RADIUS,
                        fill : chart.theme("legendSwitchCircleColor")
                    }));

                    group.append(chart.text({
                        x : WIDTH + (PADDING * 2),
                        y : 0,
                        "font-size" : chart.theme("legendFontSize"),
                        "fill" : chart.theme("legendFontColor"),
                        "text-anchor" : "start"
                    }, text));

                    arr.push({
                        icon : group,
                        width : WIDTH + rect.width + (PADDING * 2.5),
                        height : HEIGHT + (PADDING / 2)
                    });

                    (function(key, element) {
                        element.attr({
                            cursor: "pointer"
                        });

                        element.on("click", function(e) {
                            if(columns[brush.index][key]) {
                                element.get(0).attr({ stroke: chart.theme("legendSwitchDisableColor") });
                                element.get(2).attr({ fill: chart.theme("legendSwitchDisableColor") });
                                element.get(1).attr({ cx: 0 });
                                columns[brush.index][key] = false;
                            } else {
                                element.get(0).attr({ stroke: colorIndex[key] });
                                element.get(2).attr({ fill: chart.theme("legendFontColor") });
                                element.get(1).attr({ cx: WIDTH });
                                columns[brush.index][key] = true;
                            }

                            changeTargetOption((widget.brushSync) ? getBrushAll() : [ brush ]);
                        });
                    })(target, group);
                } else {
                    var size = chart.theme("legendFontSize");

                    if(widget.icon != null) {
                        var icon = _.typeCheck("function", widget.icon) ? widget.icon.apply(chart, [ target ]) : widget.icon;

                        group.append(chart.text({
                            x: 0,
                            y: POINT,
                            "font-size": size,
                            "fill": color
                        }, icon));
                    } else {
                        group.append(chart.svg.circle({
                            cx : size / 2,
                            cy : -POINT,
                            r : size / 2,
                            fill : color
                        }));
                    }

                    group.append(chart.text({
                        x : size * RATIO,
                        y : 0,
                        "font-size" : size,
                        "fill" : chart.theme("legendFontColor"),
                        "text-anchor" : "start"
                    }, text));

                    arr.push({
                        icon : group,
                        width : size + rect.width + (PADDING * 2),
                        height : HEIGHT + (PADDING / 2)
                    });
                }
			}
			
			return arr;
		}        
        
        this.draw = function() {
            var group = chart.svg.group();
            
            var x = 0,
                y = 0,
                total_width = 0,
                total_height = 0,
                max_width = 0,
                max_height = 0,
                brushes = getIndexArray(widget.brush);

            var total_widthes = [];

            for(var i = 0; i < brushes.length; i++) {
                var index = brushes[i];

                // brushSync가 true일 경우, 한번만 실행함
                if(widget.brushSync && i > 0) continue;

                var brush = chart.get("brush", brushes[index]),
                    arr = this.getLegendIcon(brush);

                for(var k = 0; k < arr.length; k++) {
                    group.append(arr[k].icon);
                    arr[k].icon.translate(x, y);

                    if (widget.orient == "bottom" || widget.orient == "top") {

                        if (x + arr[k].width > chart.area("x2")) {
                            x = 0;
                            y += arr[k].height;
                            max_height += arr[k].height;
                            arr[k].icon.translate(x, y); // HERE
                            total_widthes.push(total_width);
                            total_width = 0; 
                        }

                        // @thanks to canelia04
                        x += arr[k].width + (PADDING * 2.5);
                        total_width += arr[k].width + (PADDING * 2.5);

                        if (max_height < arr[k].height) {
                            max_height = arr[k].height;
                        }
                    } else {
                        y += arr[k].height;
                        total_height += arr[k].height;

                        if (max_width < arr[k].width) {
                            max_width = arr[k].width;
                        }
                    }
                }

                if (total_width > 0) {
                    total_widthes.push(total_width);
                }

                if (total_widthes.length > 0) {
                    total_width = Math.max.apply(Math, total_widthes);
                }

                setLegendStatus(brush);
            }
            
            // legend 위치  선정
            if (widget.orient == "bottom" || widget.orient == "top") {
                var y = ((widget.orient == "bottom") ?
                    chart.area("y2") + chart.padding("bottom") - max_height :
                    chart.area("y") - chart.padding("top")) + PADDING;
                
                if (widget.align == "start") {
                    x = chart.area("x");
                } else if (widget.align == "center") {
                    x = chart.area("x") + (chart.area("width")/2 - total_width / 2);
                } else if (widget.align == "end") {
                    x = chart.area("x2") - total_width;
                }
            } else {
                var x = ((widget.orient == "left") ?
                    chart.area("x") - chart.padding("left") :
                    chart.area("x2") + chart.padding("right") - max_width) + PADDING;
                
                if (widget.align == "start") {
                    y = chart.area("y");
                } else if (widget.align == "center") {
                    y = chart.area("y") + (chart.area("height") / 2 - total_height / 2);
                } else if (widget.align == "end") {
                    y = chart.area("y2") - total_height;
                }
            } 

            group.translate(Math.floor(x) + widget.dx, Math.floor(y) + widget.dy);

            return group;
        }
    }

    LegendWidget.setup = function() {
        return {
            /** @cfg {"bottom"/"top"/"left"/"right" } Sets the location where the label is displayed (top, bottom). */
            orient: "bottom",
            /** @cfg {"start"/"center"/"end" } Aligns the label (center, start, end). */
            align: "center", // or start, end
            /** @cfg {Boolean} [filter=false] Performs filtering so that only label(s) selected by the brush can be shown. */
            filter: false,
            /** @cfg {Function/String} [icon=null]   */
            icon: null,
            /** @cfg {Number} [dx=0] Moves the x coordinate by a set value from the location where the chart is drawn.  */
            dx: 0,
            /** @cfg {Number} [dy=0] Moves the y coordinate by a set value from the location where the chart is drawn. */
            dy: 0,
            /** @cfg {Array} [colors=null]   */
            colors: null,
            /** @cfg {Boolean} [brushSync=false] Applies all brushes equally when using a filter function. */
            brushSync: false,
            /** @cfg {Number/Array} [brush=0] Specifies a brush index for which a widget is used. */
            brush: 0,
            /** @cfg {Function} [format=null] Sets the format of the key that is displayed on the legend. */
            format: null
        };
    }

    /**
     * @event legend_filter
     * Event that occurs when the filter function of the legend widget is activated. (real name ``` legend.filter ```)
     * @param {String} target The selected data field.
     */

    return LegendWidget;
}, "chart.widget.core");