jui.define("chart.brush.stackbar", [ "util.base" ], function(_) {

	/**
	 * @class chart.brush.stackbar
	 * @extends chart.brush.bar
	 *
	 */
	var StackBarBrush = function(chart, axis, brush) {
		var g, height, bar_height;

		this.addBarElement = function(elem) {
			if(this.barList == null) {
				this.barList = [];
			}

			this.barList.push(elem);
		}

		this.getBarElement = function(dataIndex, targetIndex) {
			var style = this.getBarStyle(),
				color = this.color(targetIndex),
				value = this.getData(dataIndex)[this.brush.target[targetIndex]];

			var r = this.chart.svg.rect({
				fill : color,
				stroke : style.borderColor,
				"stroke-width" : style.borderWidth,
				"stroke-opacity" : style.borderOpacity
			});

			// 데이타가 0이면 화면에 표시하지 않음.
			if (value == 0) {
                r.attr({ display : 'none' });
			}

			if(value != 0) {
				this.addEvent(r, dataIndex, targetIndex);
			}

			return r;
		}

		this.setActiveEffect = function(group) {
			var style = this.getBarStyle(),
				columns = this.barList,
				tooltips = this.stackTooltips;

			for(var i = 0; i < columns.length; i++) {
				var opacity = (group == columns[i]) ? 1 : style.disableOpacity;

				if (tooltips) {			// bar 가 그려지지 않으면 tooltips 객체가 없을 수 있음.
                    if(opacity == 1 || _.inArray(i, this.tooltipIndexes) != -1) {
                        tooltips[i].attr({ opacity: 1 });
                    } else {
                        tooltips[i].attr({ opacity: 0 });
                    }
				}

                columns[i].attr({ opacity: opacity });
            }
		}

		this.setActiveEffectOption = function() {
			var active = this.brush.active;

			if(this.barList && this.barList[active]) {
				this.setActiveEffect(this.barList[active]);
			}
		}

		this.setActiveEvent = function(group) {
			var self = this;

			group.on(self.brush.activeEvent, function (e) {
				self.setActiveEffect(group);
			});
		}

		this.setActiveEventOption = function(group) {
			if(this.brush.activeEvent != null) {
				this.setActiveEvent(group);
				group.attr({ cursor: "pointer" });
			}
		}

		this.getTargetSize = function() {
			var height = this.axis.y.rangeBand();

			if(this.brush.size > 0) {
				return this.brush.size;
			} else {
				var size = height - this.brush.outerPadding * 2;
				return (size < this.brush.minSize) ? this.brush.minSize : size;
			}
		}

        this.setActiveTooltips = function(minIndex, maxIndex) {
            var type = this.brush.display,
                activeIndex = (type == "min") ? minIndex : maxIndex;

            for(var i = 0; i < this.stackTooltips.length; i++) {
                if(i == activeIndex || type == "all") {
                    this.stackTooltips[i].css({
                        opacity: 1
                    });

                    this.tooltipIndexes.push(i);
                }
            }
        }

        this.drawStackTooltip = function(group, index, value, x, y, pos) {
            var fontSize = this.chart.theme("tooltipPointFontSize"),
				orient = "middle",
				dx = 0,
				dy = 0;

            if(pos == "left") {
            	orient = "start";
            	dx = 3;
            	dy = fontSize / 3;
            } else if(pos == "right") {
            	orient = "end";
                dx = -3;
                dy = fontSize / 3;
            } else if(pos == "top") {
				dy = -(fontSize / 3);
			} else {
				dy = fontSize;
			}

            var tooltip = this.chart.text({
                fill : this.chart.theme("tooltipPointFontColor"),
                "font-size" : fontSize,
                "font-weight" : this.chart.theme("tooltipPointFontWeight"),
                "text-anchor" : orient,
				dx: dx,
                dy: dy,
                opacity: 0
            }).text(this.format(value)).translate(x, y);

            this.stackTooltips[index] = tooltip;
            group.append(tooltip);
        }

        this.drawStackEdge = function(g) {
            var borderWidth = this.chart.theme("barStackEdgeBorderWidth");

            for(var i = 1; i < this.edgeData.length; i++) {
                var pre = this.edgeData[i - 1],
                    now = this.edgeData[i];

                for(var j = 0; j < this.brush.target.length; j++) {
                	if(now[j].width > 0 && now[j].height > 0) {
                        g.append(this.svg.line({
                            x1: pre[j].x + pre[j].width - pre[j].ex,
                            x2: now[j].x + now[j].dx - now[j].ex,
                            y1: pre[j].y + pre[j].height - pre[j].ey,
                            y2: now[j].y + now[j].dy,
                            stroke: now[j].color,
                            "stroke-width": borderWidth
                        }));
                    }
                }
            }
        }

		this.drawBefore = function() {
			g = chart.svg.group();
			height = axis.y.rangeBand();
			bar_height = this.getTargetSize();

            this.stackTooltips = [];
            this.tooltipIndexes = [];
            this.edgeData = [];
		}

		this.draw = function() {
            var maxIndex = null,
                maxValue = 0,
                minIndex = null,
                minValue = this.axis.x.max(),
				isReverse = this.axis.get("x").reverse;

			this.eachData(function(data, i) {
				var group = chart.svg.group();
				
				var offsetY = this.offset("y", i),
					startY = offsetY - bar_height / 2,
                    startX = axis.x(0),
                    value = 0,
                    sumValue = 0;
				
				for(var j = 0; j < brush.target.length; j++) {
					var xValue = data[brush.target[j]] + value,
                        endX = axis.x(xValue),
						opts = {
                            x : (startX < endX) ? startX : endX,
                            y : startY,
                            width : Math.abs(startX - endX),
                            height : bar_height
                        },
						r = this.getBarElement(i, j).attr(opts);

                    if(!this.edgeData[i]) {
                        this.edgeData[i] = {};
                    }

                    this.edgeData[i][j] = _.extend({
                    	color: this.color(j),
						dx: opts.width,
						dy: 0,
						ex: (isReverse) ? opts.width : 0,
						ey: 0
					}, opts);

					startX = endX;
					value = xValue;
                    sumValue += data[brush.target[j]];

                    group.append(r);
				}

                // min & max 인덱스 가져오기
                if(sumValue > maxValue) {
                    maxValue = sumValue;
                    maxIndex = i;
                }
                if(sumValue < minValue) {
                    minValue = sumValue;
                    minIndex = i;
                }

                this.drawStackTooltip(group, i, sumValue, startX, offsetY, (isReverse) ? "right" : "left");
				this.setActiveEventOption(group); // 액티브 엘리먼트 이벤트 설정
				this.addBarElement(group);
				g.append(group);
			});

			// 스탭 연결선 그리기
            if(this.brush.edge) {
                this.drawStackEdge(g);
            }

            // 최소/최대/전체 값 표시하기
            if(this.brush.display != null) {
                this.setActiveTooltips(minIndex, maxIndex);
            }

			// 액티브 엘리먼트 설정
			this.setActiveEffectOption();

            return g;
		}
	}

	StackBarBrush.setup = function() {
		return {
			/** @cfg {Number} [outerPadding=15] Determines the outer margin of a stack bar. */
			outerPadding: 15,
            /** @cfg {Boolean} [edge=false] */
			edge: false
		};
	}

	return StackBarBrush;
}, "chart.brush.bar");