/**
 * inspired from @author Dimitry Kudrayvtsev
 * @author tr4ck3ur
 */

d3.sched = function(EventType) {
    var FIT_TIME_DOMAIN_MODE = "fit";
    var FIXED_TIME_DOMAIN_MODE = "fixed";
    var myname = EventType;
    var margin = {
        top : 15, 
        right : 10,
        bottom : 10, 
        left : 50
    };
    var timeDomainStart = d3.time.hour.offset(new Date(),-2);
    var timeDomainEnd = d3.time.hour.offset(new Date(),+2);
    var timeDomainMode = FIT_TIME_DOMAIN_MODE;// fixed or fit
    var taskTypes = [];
    var taskStatus = [];
    //var height = document.body.clientHeight - margin.top - margin.bottom-5;
    height = 700;
    //var width = document.body.clientWidth - margin.right - margin.left-5;
    var width = 700;// - margin.right - margin.left;
    var tickFormat = "%H:%M";
    var lastscale = -1;

    var xScale = d3.scale.ordinal()
        .domain(taskTypes)
        .rangeRoundBands([ 0, width - margin.left], .1);
    
    var yScale = d3.time.scale()
        .domain([ timeDomainStart, timeDomainEnd ])
        .range([ 0, height - margin.top ]) //- margin.bottom ]);
        .clamp(true);

    var xAxis = d3.svg.axis()
            .scale(xScale)
            .orient("left")
            .tickSize(1);

    var yAxis = d3.svg.axis()
            .scale(yScale)
            .orient("bottom")
            .tickFormat(d3.time.format(tickFormat))
            .tickSubdivide(true)
            .tickSize(8).tickPadding(8);

    var keyFunction = function(d) {
        return d.startDate + d.placeName + d.endDate;
    };

    var rectTransform = function(d) {
        return "translate(" + xScale(d.placeName) + "," + yScale(d.startDate) + ")";
    };

    var initTimeDomain = function(tasks) {
        if (timeDomainMode === FIT_TIME_DOMAIN_MODE) {
            if (tasks === undefined || tasks.length < 1) {
                timeDomainStart = d3.time.day.offset(new Date(), -3);
                timeDomainEnd = d3.time.hour.offset(new Date(), +3);
            return;
            }
            tasks.sort(function(a, b) {
                return a.endDate - b.endDate;
            });
            timeDomainEnd = tasks[tasks.length - 1].endDate;
            tasks.sort(function(a, b) {
                return a.startDate - b.startDate;
            });
            timeDomainStart = tasks[0].startDate;
        }
    };

    var initAxis = function() {

        xScale = d3.scale.ordinal()
            .domain(taskTypes)
            .rangeRoundBands([ 0, width ], .1);    
      
        yScale = d3.time.scale()
            .domain([ timeDomainStart, timeDomainEnd ])
            .range([ 0, height - margin.top - margin.bottom ])
            .clamp(true);    

        xAxis = d3.svg.axis()
            .scale(xScale)
            .orient("top")
            .tickSize(1);

        yAxis = d3.svg.axis()
            .scale(yScale)
            .orient("left")
            .tickFormat(d3.time.format(tickFormat))
            .tickSubdivide(true)
            .tickSize(8)
            .tickPadding(8);
    };
    
    function sched(tasks) {
    
    	initTimeDomain(tasks);
    	initAxis();

    function zoomed() {
      var px = d3.event.translate[0];
      var py = d3.event.translate[1];
      var dx = 0;
      timeDomainStart = d3.time.hour.offset( timeDomainStart, 0)
      if (py>0) {
          dx = timeDomainStart.getTime()-yScale.invert(py).getTime()
      } else {
          dx = -timeDomainStart.getTime()+yScale.invert(-py).getTime()
      }
      NewStart = d3.time.hour.offset( timeDomainStart.getTime()+dx, 0)
      //NewEnd   = d3.time.hour.offset( timeDomainStart.getTime()+dx, 0) //.3*d3.event.scale)      
      //yScale.domain([ NewStart , NewEnd ])
 
      sched.timeDomainMode("fit")
      //sched.timeDomain([ NewStart , NewEnd ]);
      //timeDomainStart = NewStart
      //timeDomainEnd = NewEnd
 
      var dy = py;
      var dz = timeDomainEnd-timeDomainStart
      if (py>0)
        var dx = timeDomainStart-yScale.invert(py).getTime()
      else
        var dx = -timeDomainStart+yScale.invert(-py).getTime()
      
        //yScale.domain([ timeDomainStart, d3.time.hour.offset(timeDomainStart, d3.event.scale*4) ])
        //    .range([ 0, height - margin.top - margin.bottom ])
        //   .clamp(true);
            
        //yScale2.domain([ NewStart, d3.time.hour.offset(NewStart, d3.event.scale*4) ])
        //    .range([ 0, height - margin.top - margin.bottom ])
        //    .clamp(true);
                                
        //
        if (0 && lastscale!=d3.event.scale) {
            lastscale = d3.event.scale;
            yScale.domain([ timeDomainStart, d3.time.hour.offset(timeDomainStart, d3.event.scale*4) ])
                .range([ 0, height - margin.top - margin.bottom ])
                .clamp(true);
            //Saved = chart.attr("transform");
            //coords = Saved.slice(Saved.search(/([0-9]+)/g),Saved.length-1).split(',');
            //chart.attr("transform", "translate(" + px + "," + py + ")");
            //zoom.translate((80,120))
            //zoom.center([121, 21])
            //sched.redraw(this.id, tasks);
            //zoom.translate()
            
            //chart.attr("transform", "translate(" + parseInt(coords[0])+px + "," + parseInt(coords[1])+py + ")");
            //chart.attr("transform", "translate(" + 121 + "," + 21 + ")");
            chart.attr("transform", "translate(" + px + "," + py + ")");
        }
        // else {
        //    chart.attr("transform", "translate(" + px + "," + py + ")");
        //}
 
      var dxr = d3.time.hour.offset( timeDomainStart+dx, 0)
      //ind.text( py +" "+ dz +" => "+ d3.event.scale )
      //if ( DragLimit.xmin < (-px) && (-px) < DragLimit.xmax ) {      
      //  } else {
      //      d3.event.sourceEvent.stopPropagation();
      //  }

        //sched.redraw(tasks);            


        //sched.timeDomain([ d3.time.hour.offset(mystart,0), d3.time.hour.offset(mystart, d3.event.scale) ]);
        if (1) {
        svg.select(".yAxis")
            .attr("transform", "translate("+ margin.left +","+ margin.top +")")// + py + ")")
            .transition()
            .call(yAxis);

        //svg.select(".yAxis2")
        //    .attr("transform", "translate(80,0)")
        //    .call(yAxis2);
          
        svg.select(".xAxis")
            .attr("transform", "translate("+ margin.left +","+ margin.top +")")
            .transition()
            .call(xAxis);
            
        chart.attr("transform", "translate("+ margin.left +","+ margin.top +")");
        }
        
    }

    var zoom = d3.behavior.zoom()
        .scaleExtent([1, 4])
        .on("zoom", zoomed);
    
    var svg = d3.select("#Schedule_"+EventType)
        .append("svg")
        .attr("id", EventType)
        .attr("class", "chart")
        .attr("width",  width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .call(zoom);
        
    var chart = svg.append("g")
        .attr("class", "sched-chart");

    chart.selectAll(".sched-chart")
         .data(tasks, keyFunction).enter()
         .append("rect")
         .attr("class", function(d){ 
             if(taskStatus[d.status] == null)
                { return "bar";}
             return taskStatus[d.status];
             });
             

if (0) {
    chart.selectAll('.foreignObject')
        .data(tasks, keyFunction).enter()
        .append('foreignObject') 
         .attr("x", function(d){ 
            return xScale(d.placeName || "unk");
             })
         .attr("y", function(d){ 
            return yScale(d.startDate);
             })
         //.attr("y", 0)
         //.attr("x", 2)
         //.attr("transform", rectTransform)
         .attr("width", function(d) { 
            return xScale.rangeBand(); 
            })
         .attr("height", function(d) { 
             return (yScale(d.endDate) - yScale(d.startDate)); 
             })    
        .append("xhtml:div")
        .html(function(d) { 
            return '<div style="padding:2px;height:100%"><a href="/event/'+ d.uid +
                '">' + d.desc + '</a></div>'
             });
}
/*     svg.selectAll("text")
        .data(tasks, keyFunction).enter()
        .append("text")    
        .text(function(d) { return d.desc; })
        .attr("x", 2)
        .attr("y", 16)
        .attr("transform", rectTransform)
        .attr("width", function(d) { 
        return x.rangeBand(); 
        })
        .fill('blue');     
*/     

    svg.append("g")
        .attr("class", "xAxis axis");
     
     svg.append("g")
        .attr("class", "yAxis axis");
      
     //zoomed();
     //sched.redraw(tasks);
     return sched;

    };
    
    sched.redraw = function(who, tasks) {

        //initTimeDomain(tasks);
        //initAxis();
        var svg = d3.select("#"+who);

        var schedChartGroup = svg.select(".sched-chart");
        
        var rect = schedChartGroup.selectAll("rect")
            .data(tasks, keyFunction);
        
        rect.enter()
            .insert("rect",":first-child")
            .attr("rx", 5)
            .attr("ry", 5)
            .attr("class", function(d){ 
                 if(taskStatus[d.status] == null)
                    { return "bar";}
                 return taskStatus[d.status];
                })
            //.transition()
             .attr("x", function(d){ 
                return xScale(d.placeName || "unk");
                 })
             .attr("y", function(d){ 
                return yScale(d.startDate);
                 })
            //.attr("transform", rectTransform)
            .attr("width", function(d) { 
                return xScale.rangeBand(); 
            })
            .attr("height", function(d) { 
                return (yScale(d.endDate) - yScale(d.startDate));
            });

        rect.transition()
            //.attr("transform", rectTransform)
             .attr("x", function(d){ 
                return xScale(d.placeName || "unk");
                 })
             .attr("y", function(d){ 
                return yScale(d.startDate);
                 })
            .attr("width", function(d) { 
                return xScale.rangeBand(); 
                 })
            .attr("height", function(d) { 
                return (yScale(d.endDate) - yScale(d.startDate)); 
                 });
        
        rect.exit()
            .remove();

        var content = schedChartGroup.selectAll("foreignObject")
            .data(tasks, keyFunction);        

        content.enter()
            .insert("foreignObject",":first-child")
            //.transition()
             .attr("x", function(d){ 
                return xScale(d.placeName || "unk");
                 })
             .attr("y", function(d){ 
                return yScale(d.startDate);
                 })
            //.attr("transform", rectTransform)
            .attr("width", function(d) { 
                return xScale.rangeBand(); 
            })
            .attr("height", function(d) { 
                return (yScale(d.endDate) - yScale(d.startDate));
            })            
            .append("xhtml:div")
            .html(function(d) { 
                return '<div style="padding:2px;height:100%"><a href="/event/'+ d.uid +
                    '">' + d.desc + '</a></div>'
                 });

        content.transition()
            //.attr("transform", rectTransform)
             .attr("x", function(d){ 
                return xScale(d.placeName || "unk");
                 })
             .attr("y", function(d){ 
                return yScale(d.startDate);
                 })
            .attr("width", function(d) { 
                return xScale.rangeBand(); 
                 })
            .attr("height", function(d) { 
                return (yScale(d.endDate) - yScale(d.startDate)); 
                 });                 
        
        content.exit()
            .remove();



	return sched;
    };

    sched.margin = function(value) {
        if (!arguments.length)
            return margin;
        margin = value;
        return sched;
    };

    sched.timeDomain = function(value) {
        if (!arguments.length)
            return [ timeDomainStart, timeDomainEnd ];
        timeDomainStart = +value[0], timeDomainEnd = +value[1];
        return sched;
    };

    /**
     * @param {string}
     *                vale The value can be "fit" - the domain fits the data or
     *                "fixed" - fixed domain.
     */
    sched.timeDomainMode = function(value) {
        if (!arguments.length)
            return timeDomainMode;
        timeDomainMode = value;
            return sched;
    };

    sched.taskTypes = function(value) {
        if (!arguments.length)
            return taskTypes;
        taskTypes = value;
        return sched;
    };
    
    sched.taskStatus = function(value) {
        if (!arguments.length)
            return taskStatus;
        taskStatus = value;
        return sched;
    };

    sched.width = function(value) {
        if (!arguments.length)
            return width;
        width = +value;
        return sched;
    };

    sched.height = function(value) {
        if (!arguments.length)
            return height;
        height = +value;
        return sched;
    };

    sched.tickFormat = function(value) {
        if (!arguments.length)
            return tickFormat;
        tickFormat = value;
        return sched;
    };

    sched.name = function(value) {
        if (!arguments.length)
            return myname;
        myname = value;
        return sched;
    };

    return sched;
};
