// Chart design based on my BulleT that was based on original bullet chart by Mike Bostock:
// http://bl.ocks.org/mbostock/4061961
// with d3.chart.js (0.1.2)
// http://misoproject.com/d3-chart/
d3.chart("LikertEven", {
  initialize: function() {
    var chart = this;
    this.xScale = d3.scale.linear();
    this.tickFormat( function(d){return Math.abs(d)} );
    this.x0 = chart.xScale(0);
    this.axisStyle(function(d) {
      return d.axisStyle;
    }); 
    this.base.classed("LikertEven", true);
    // Default configuration
    this._margin = { top: 0, right: 0, bottom: 0, left: 0 };
    this.duration(0);
    this.percent(function(d) {
      return d.percent;
    });
    this.width(100);
    this.height(40);
    this.reverse(false);
    this.orient("left");
    this.terjedelem(function(d) {
      return d.terjedelem;
    });
/******************************************************************************/
    this.layer("rowBackgroundA", this.base.append("g").classed("rowBackgroundA", true), {
      dataBind: function(data) {
        data = data.rowStyle;
        return this.selectAll("rect").data(data);
      },
      insert: function() {
        return this.append("g");
      },
      events: {
        enter: function(d) {
          this.append("rect").attr("class", function(d){return d;})
              .attr("x", chart.xScale(-110))
              .attr("y", 0)
              .attr("height", chart.height())
              .attr("width", chart.xScale(250));
          this.append("rect").attr("class", function(d){  
            var axisStyle = chart.axisStyle();
            if( axisStyle === "axis" ){
              return "background " + d;
            }else{
              return "background " + "white";
            }
          })
              .attr("x", chart.xScale(100))
              .attr("y",  chart.height()/2)
              .attr("height", chart.height()/2)
              .attr("width", chart.xScale(40));
        }
      }
    }) 
/******************************************************************************/
    this.layer("rowBackgroundB", this.base.append("g").classed("rowBackgroundB", true), {
      dataBind: function() {
        var format = this.chart().tickFormat();
        return this.selectAll("g.tickLine").data(this.chart().xScale.ticks(8), function(d) {
          return d;
        });
      },
      insert: function() {
        var tick = this.append("g").attr("class", "tickLine");
        var height =chart.height();
        var format = chart.tickFormat();
        tick.append("line")
          .attr("y1", 0)
          .attr("y2", chart.height())
          .attr("opacity", function(d) {
              if( d < 100 ){
                return 1;
              }else{
                return 0;
              }
            });
        return tick;
      },
      events: {
        enter: function(d) {  
          var axisStyle = chart.axisStyle();
          this.attr("transform", function(d) {
              return "translate(" + chart.xScale(d) + ",0)";
            })
            .attr("stroke-width", 1)  
            .attr("stroke", "#ffffff");
        },
        "exit:transition": function() {
          this.remove();
        }
      }
    })
/******************************************************************************/
    this.layer("percent", this.base.append("g").classed("percent", true), {
      dataBind: function(data) {
        var data_percent = new Array();
        // @CodeXmonk: a bit of hack too - ToDo later.
        data_percent[0] = (data.percent[0]+data.percent[1])*(-1); // [-80,-45,20,40]
        data_percent[1] = data.percent[1]*(-1);
        data_percent[2] = data.percent[2]+data.percent[3];
        data_percent[3] = data.percent[2];
        return this.selectAll("rect.percent").data(data_percent);
      },
      insert: function() {
        return this.append("rect");
      },
      events: {
        enter: function(d, i) {
          this.attr("class", function(d, i) { return "percent s" + i; })
              .attr("height", chart.height())
              .attr("x", function(d,i) {
                if( d < 0 ){
                  return chart.xScale(d);
                }else{
                  return chart.xScale(0);
                } 
              }) 
              .attr("width", function(d, i) {
                return chart.xScale(Math.abs(d))-chart.xScale(0) ;
              })
              .attr("transform", "translate(" + 0 + ",0)" );
        },
        "merge:transition": function(d, i) {
          this.duration(chart.duration())
            .attr("x", function(d, i) {
              if( d < 0 ){
                return chart.xScale(d);
              }else{
                return chart.xScale(0);
              } 
            })
            .attr("width", function(d, i) {
              if( d < 0 ){
                return chart.xScale(Math.abs(d))-chart.xScale(0) ;
              }else{
                  return chart.xScale(Math.abs(d))-chart.xScale(0) ;
              }
            })
            .attr("transform", "translate(" + 0 + ",0)" );
          },
        exit: function() {
          this.remove();
        }
      }
    });
/******************************************************************************/
    this.layer("text", this.base.append("g").classed("text", true), {
      dataBind: function(data) {
        var data_percent = new Array();
        var dimension = data.dimension;
        var axisStyle = chart.axisStyle();
        // @CodeXmonk: a bit of hack too - ToDo later.
        data_percent[0] = new Array( (data.percent[0]+data.percent[1])*(-1), data.percent[0], dimension ); // [-80,-45,20,40]
        data_percent[1] = new Array( data.percent[1]*(-1), data.percent[1], dimension );
        data_percent[2] = new Array( data.percent[2]+data.percent[3], data.percent[3], dimension );
        data_percent[3] = new Array( data.percent[2], data.percent[2], dimension);
        return this.selectAll("text").data(data_percent);
      },
      insert: function() {
        return this.append("text")
      },
      events: {
        enter: function(d, i) {
          this.text( function(d,i) {
            var axisStyle = chart.axisStyle();
            if( axisStyle === "axis" ){
              return d[2][i+1];
            }else{
              switch (true)
              { 
                case ( d[1] < 5 ):
                  return "";
                  break;
                case ( 5 <= d[1] && d[1] < 8 ):
                  return Math.abs(d[1]);
                  break;
                default:
                  return Math.abs(d[1])+"%";
                  break;
              }
            } 
          })
          .style("opacity", function() {
            var axisStyle = chart.axisStyle();
              if( axisStyle === "axis" ){
                return 1;
              }else{
                return 0;
              }
          })
          this.attr("class", function(d, i) {
            var axisStyle = chart.axisStyle();
              if( axisStyle === "axis" ){
                return "textResultKiem";
              }else{
                return "textResult";
              }
          })
          .attr("y", chart.height() - chart.height()/3)
          .attr("x", function(d, i) {
            return chart.xScale(d[0]); 
          })
          .attr("text-anchor", function(d, i) {
            if( d[0] < 0 ){
              return "start"; 
            }else{
              return "end";
            }
          })
          .attr("transform", function(d, i) {
            if( d[0] < 0 ){
              return "translate(" + 2 + ",0)";
            }else{
              return "translate(" + -2 + ",0)";
            }
          });
        },
        "merge:transition": function(d, i) {
          this.duration(chart.duration())
          .attr("x", function(d, i) {
            return chart.xScale(d[0]); 
          })
          .attr("text-anchor", function(d, i) {
            if( d[0] < 0 ){
              return "start"; 
            }else{
              return "end";
            }
          })
          .attr("transform", function(d, i) {
            if( d[0] < 0 ){
              return "translate(" + 2 + ",0)";
            }else{
              return "translate(" + -2 + ",0)";
            }
          });
          this.duration(chart.duration()*2)
            .style("opacity", function(d){return 1;});
        },
        exit: function() {
          this.remove();
        }
      }
    });
/******************************************************************************/
    this.layer("textLegendA", this.base.append("g").classed("textLegendA", true), {
      dataBind: function(data) {
        var data_tmp = new Array();
        var dimension = data.dimension;
        var axisStyle = chart.axisStyle();
        data_tmp[0] = new Array( dimension );
        return this.selectAll("text").data(data_tmp);
      },
      insert: function() {
        return this.append("text");
      },
      events: {
        enter: function(d) {
          this.text( function(d) {return d[0][0];});
          this.attr("class", function() {
            var axisStyle = chart.axisStyle();
              if( axisStyle === "axis" ){
                return "dimTextKiem";
              }else{
                return "textLegendA";
              }
          })
          this.attr("y", function() {
            var axisStyle = chart.axisStyle();
              if( axisStyle === "axis" ){
                return chart.height()/1.5;
              }else{
                return chart.height()/2.8;
              }
          })
          .attr("x", function() { return chart.xScale(104);})
          .attr("text-anchor", function() {return "start"; });
        },
        "merge:transition": function() {
          this.attr("x", function() {
            return chart.xScale(104); 
          })
          .attr("text-anchor", function() {return "start"; });
        },
        exit: function() {
          this.remove();
        }
      }
    });
/******************************************************************************/
    this.layer("textLegendB", this.base.append("g").classed("textLegendB", true), {
      dataBind: function(data) {
        var data_tmp = new Array();
        var axisStyle = chart.axisStyle();
        /* let's find the greatest value in data.percent array */
        var greatest;
        var indexOfGreatest;
        var array = data.percent;
        for (var i = 0; i < array.length; i++) {
          if (!greatest || array[i] > greatest) {
            greatest = array[i];
            indexOfGreatest = i;
          }
        }
        data_tmp[0] = new Array( data.percent[indexOfGreatest], indexOfGreatest, data.dimension );
        return this.selectAll("text").data(data_tmp);
      },
      insert: function() {
        return this.append("text");
      },
      events: {
        enter: function(d) {
          this.text( function(d) {
            var idx = d[1];
            var axisStyle = chart.axisStyle();
              if( axisStyle === "axis" ){
                return "";
              }else{
                return d[0] + "% " + d[2][idx+1];
              }
          });
          this.attr("class", function(d) {
            var idx = d[1];
            return "subtitle s" + idx;
          })
          this.attr("y", function() {
            var axisStyle = chart.axisStyle();
              if( axisStyle === "axis" ){
                return chart.height()/1.5;
              }else{
                return chart.height()-4;
              }
          })
          .attr("x", function() { return chart.xScale(104);})
          .attr("text-anchor", function() {return "start"; });
        },
        "merge:transition": function() {
          this.attr("x", function() {
            return chart.xScale(104); 
          })
          .attr("text-anchor", function() {return "start"; });
        },
        exit: function() {
          this.selectAll("text").remove();
        }
      }
    });
/******************************************************************************/
    this.layer("ticks", this.base.append("g").classed("ticks", true), {
      dataBind: function() {
        var format = this.chart().tickFormat();
        return this.selectAll("g.tick").data(this.chart().xScale.ticks(8), function(d) {
          return d;
        });
      },
      insert: function() {
        var tick = this.append("g").attr("class", "tick");
        var height =chart.height();
        var format = chart.tickFormat();
        tick.append("line")
          .attr("y1", chart.height())
          .attr("y2", chart.height() * 7 / 6);
        tick.append("text")
          .attr("text-anchor", "middle")
          .attr("dy", "1em")
          .attr("y", chart.height() * 7 / 6)
          .text(format);
        return tick;
      },
      events: {
        enter: function(d) {  
          var axisStyle = chart.axisStyle();
          this.attr("transform", function(d) {
            return "translate(" + chart.xScale(d) + ",0)";
          })
          .style("opacity", function(d){
            if( axisStyle === "axis" ){
              return 1;
            }else{
              return 0;
            }
          });
        },
        "merge:transition": function(d) { 
        var axisStyle = chart.axisStyle();
          this.duration(chart.duration())
          .attr("transform", function(d) {
            return "translate(" + chart.xScale(d) + ",0)";
          })
          .style("opacity", function(d){
            if( axisStyle === "axis" ){
              return 1;
            }else{
              return 0;
            }
          });
          this.select("line")
            .attr("y1", chart.height())
            .attr("y2", chart.height() * 7 / 6);
          this.select("text")
            .attr("y", chart.height() * 7 / 6);
        },
        "exit:transition": function() {
          this.duration(chart.duration())
            .attr("transform", function(d) {
              return "translate(" + chart.xScale(d) + ",0)";
            })
            .style("opacity", 1e-6)
            .remove();
        }
      }
    });
    
    d3.timer.flush();
  },                                                                     

  transform: function(data) {
    var height = this.height();
    // misoproject: Copy data before sorting
    var newData = {
      rowStyle: data.rowStyle,
      dimension: data.dimension,
      randomizer: data.randomizer,
      terjedelem: data.terjedelem.slice(),
      percent: data.percent, 
      item: data.item,
    };
    this.xScale.domain([newData.terjedelem[0], newData.terjedelem[1]]);
    var axisStyle = this.axisStyle();
    if( axisStyle !== "axis" ){
      var select_tmp = d3.selectAll("[name=SVG]");
      select_tmp.attr("height",25);
    }
    return newData;
  },

  // misoproject: reverse or not
  reverse: function(x) {
		if (!arguments.length) return this._reverse;
		this._reverse = x;
		return this;
	},

	// misoproject: left, right, top, bottom
	orient: function(x) {
		if (!arguments.length) return this._orient;
		this._orient = x;
		this._reverse = this._orient == "right" || this._orient == "bottom";
		return this;
	},
  
	axisStyle: function(x) {
		if (!arguments.length) return this._axisStyle;
		this._axisStyle = x;
		return this;
	}, 

	// @CodeXmonk: terjedelem (20,80)
	terjedelem: function(x) {
		if (!arguments.length) return this._terjedelem;
		this._terjedelem = x;
		return this;
	},
  
	percent: function(x) {
		if (!arguments.length) return this._percent;
		this._percent = x;
		return this;
	},
  
	width: function(x) {
		var margin, width_tmp;
		if (!arguments.length) {
			return this._width;
		}
		margin = this.margin(); 
    width_tmp = x[0];
		width_tmp = width_tmp - (margin.left + margin.right);
		this._width = width_tmp; 
		this.xScale.range(this._reverse ? [width_tmp, 0] : [0, width_tmp]);
		this.base.attr("width", width_tmp);
		return this;
	},
  
	height: function(x) {
		var margin, height_tmp;
		if (!arguments.length) {
			return this._height;
		}
		margin = this.margin();
    height_tmp = x[0]; 
		height_tmp = height_tmp - (margin.top + margin.bottom)-10;
		this._height = height_tmp;
		this.base.attr("height", height_tmp);
		return this;
	},
  
	margin: function(margin) {
		if (!margin) {
			return this._margin;
		}
    var margin_tmp = margin;
		["top", "right", "bottom", "left"].forEach(function(dimension) {
			if (dimension in margin_tmp) {
				this._margin[dimension] = margin_tmp[dimension];
			}
		}, this);
		this.base.attr("transform", "translate(" + this._margin.left + "," + this._margin.top + ")");
		return this;
	},

	tickFormat: function(x) {
		if (!arguments.length) return this._tickFormat;
		this._tickFormat = x;
		return this;
	},  

	orientation: function(x) {
		if (!arguments.length) return this._orientation;
		this._orientation = x;
		return this;
	},

	duration: function(x) {
		if (!arguments.length) return this._duration;
		this._duration = x;
		return this;
	}
});