/*jshint shadow:true*/
/*globals jQuery, alert*/

//(function ($) {
define(function(require) {return function($) {
    "use strict";

    $.fn.gantt = function (options) {

        var cookieKey = "jquery.fn.gantt";
        var scales = ["hours", "days", "weeks", "months"];

        var settings = {
            source: null,
            itemsPerPage: 10,
            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
            dow: ["Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"],
            startPos: new Date(),
            navigate: "buttons",
            scale: "days",
            useCookie: false,
            maxScale: "months",
            minScale: "hours",
            waitText: "Please wait...",
            onItemClick: function(data) { return; },
            onAddClick: function(data) { return; },
            scrollToToday: true
        };

        $.extend($.expr[":"], {
            findday: function (a, i, m) {
                var cd = new Date(parseInt(m[3],10));
                var id = $(a).attr("id");
                id = id ? id : "";
                var si = id.indexOf("-") + 1;
                var ed = new Date(parseInt(id.substring(si, id.length),10));
                cd = new Date(cd.getFullYear(), cd.getMonth(), cd.getDate());
                ed = new Date(ed.getFullYear(), ed.getMonth(), ed.getDate());
                return cd.getTime() === ed.getTime();
            }
        });

        $.extend($.expr[":"], {
            findweek: function (a, i, m) {
                var cd = new Date(parseInt(m[3],10));
                var id = $(a).attr("id");
                id = id ? id : "";
                var si = id.indexOf("-") + 1;
                cd = cd.getFullYear() + "-" + cd.getDayForWeek().getWeekOfYear();
                var ed = id.substring(si, id.length);
                return cd === ed;
            }
        });

        $.extend($.expr[":"], {
            findmonth: function (a, i, m) {
                var cd = new Date(parseInt(m[3],10));
                cd = cd.getFullYear() + "-" + cd.getMonth();
                var id = $(a).attr("id");
                id = id ? id : "";
                var si = id.indexOf("-") + 1;
                var ed = id.substring(si, id.length);
                return cd === ed;
            }
        });

        Date.prototype.getWeekId = function () {
            var y = this.getFullYear();
            var w = this.getDayForWeek().getWeekOfYear();
            var m = this.getMonth();
            if (m === 11 && w === 1) {
                y++;
            }
            return 'dh-' + y + "-" + w;
        };



        Date.prototype.genRepDate = function () {
            switch (settings.scale) {
                case "hours":
                    return this.getTime();
                case "weeks":
                    return this.getDayForWeek().getTime();
                case "months":
                    return new Date(this.getFullYear(), this.getMonth(), 1).getTime();
                default:
                    return this.getTime();
            }
        };
        Date.prototype.getDayOfYear = function () {
            var fd = new Date(this.getFullYear(), 0, 0);
            var sd = new Date(this.getFullYear(), this.getMonth(), this.getDate());
            return Math.ceil((sd - fd) / 86400000);
        };
        Date.prototype.getWeekOfYear = function () {
            var ys = new Date(this.getFullYear(), 0, 1);
            var sd = new Date(this.getFullYear(), this.getMonth(), this.getDate());
          
            //首先判断相隔的两年的共同拥有的星期归属：是去年的最后一个星期还是本年的第一个星期
            if(ys.getDay()>0 && ys.getDay()<5){//当前日期在一个星期中至少占四天则算为本年的第一个星期即1
            	 ys = new Date(sd.getFullYear(), 0, (7-(ys.getDay()+6)%7));//第二个星期的开始日期的前一天
                 var daysCount= sd.getDayOfYear() - ys.getDayOfYear();//距离本年第二个星期第一天的天数
            	 if(daysCount<=0){//不在本年第二个星期内，则为第一个星期
            		 return 1;
            	 }else{
            		  return Math.ceil(daysCount / 7) + 1;
            	 }
            }
            else{//当前日期在一个星期中至多占三天则算为去年的最后一个星期即52
            	 ys = new Date(sd.getFullYear(), 0, (7-(ys.getDay()+6)%7));//本年第一个星期的开始日期的前一天
                 var daysCount= sd.getDayOfYear() - ys.getDayOfYear();//距离本年第一个星期第一天的天数
                if(daysCount<=0){////不在本年第一个星期内，则为去年的最后一个星期
                	return 52;
                }else{
                	 return Math.ceil(daysCount / 7);
                }
            }           
            //return Math.ceil(daysCount / 7);
        };
        Date.prototype.getDaysInMonth = function () {
            return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate();
        };
        Date.prototype.hasWeek = function () {
            var df = new Date(this.valueOf());
            df.setDate(df.getDate() - df.getDay());
            var dt = new Date(this.valueOf());
            dt.setDate(dt.getDate() + (6 - dt.getDay()));

            if (df.getMonth() === dt.getMonth()) {
                return true;
            } else {
                return (df.getMonth() === this.getMonth() && dt.getDate() < 4) || (df.getMonth() !== this.getMonth() && dt.getDate() >= 4);
            }
        };
        Date.prototype.getDayForWeek = function () {
            var df = new Date(this.valueOf());
            df.setDate(df.getDate() - df.getDay());
            var dt = new Date(this.valueOf());
            dt.setDate(dt.getDate() + (6 - dt.getDay()));
            if ((df.getMonth() === dt.getMonth()) || (df.getMonth() !== dt.getMonth() && dt.getDate() >= 4)) {
                return new Date(dt.setDate(dt.getDate() - 3));
            } else {
                return new Date(df.setDate(df.getDate() + 3));
            }
        };

        /**
        * Core functions for creating grid.
        */
        var core = {

            elementFromPoint: function (x, y) {

                if ($.browser.msie) {
                    x -= $(document).scrollLeft();
                    y -= $(document).scrollTop();
                } else {
                    x -= window.pageXOffset;
                    y -= window.pageYOffset;
                }

                return document.elementFromPoint(x, y);
            },
            /**
            * Create header
            */
            create: function (element) {
                /**
                * Retrieve data
                */
                if (typeof settings.source !== "string") {
                    element.data = settings.source;
                    element.segment = settings.segment;
                    element.usability = settings.usability;
                    element.currentSeg = settings.currentSeg;
                    element.dayViewUrl = settings.dayViewUrl;
                    element.weekViewUrl = settings.weekViewUrl;
                    element.monthViewUrl = settings.monthViewUrl;
                    core.init(element);
                    settings.onSuccess();
                } else {
                    $.getJSON(settings.source, function (jsData) {
                        element.data = jsData;
                        core.init(element);
                    });
                }
            },
            init: function (element) {
                element.rowsNum = element.data.length||1;
                element.pageCount = Math.ceil(element.rowsNum / settings.itemsPerPage);
                element.rowsOnLastPage = element.rowsNum - (Math.floor(element.rowsNum / settings.itemsPerPage) * settings.itemsPerPage);
                
                var startDate =  new Date(settings.startPos);
                element.dateStart = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate(),
                		startDate.getHours()-1,startDate.getMinutes());
                tools.getEndDateValidateScale(element,startDate);

                // core.render(element);
                core.waitToggle(element, true, function () { core.render(element); });
            },
            render: function (element) {
                var content = $('<div class="fn-content"/>');
                var $leftPanel = core.leftPanel(element);
                content.append($leftPanel);
                var $rightPanel = core.rightPanel(element, $leftPanel);
                var mLeft, hPos;

                content.append($rightPanel);
                content.append(core.navigation(element));

                var $dataPanel = $rightPanel.find(".dataPanel");

                element.gantt = $('<div class="fn-gantt" />').append(content);

                $(element).html(element.gantt);

                element.scrollNavigation.panelMargin = parseInt($dataPanel.css("margin-left").replace("px", ""),10);
                element.scrollNavigation.panelMaxPos = ($dataPanel.width() - $rightPanel.width());

                element.scrollNavigation.canScroll = ($dataPanel.width() > $rightPanel.width());

                core.markNow(element);
                if(element.segment != null){
                	core.fillStableData(element, $dataPanel, $leftPanel);
                }
                core.fillData(element, $dataPanel, $leftPanel);

                if (settings.useCookie) {
                    var sc = $.cookie(this.cookieKey + "ScrollPos");
                    if (sc) {
                        element.hPosition = sc;
                    }
                }

                if (settings.scrollToToday) {
                    var startPos = Math.round((settings.startPos / 1000 - element.dateStart / 1000) / 86400) - 2;
                    if ((startPos > 0 && element.hPosition !== 0)) {
                        if (element.scaleOldWidth) {
                            mLeft = ($dataPanel.width() - $rightPanel.width());
                            hPos = mLeft * element.hPosition / element.scaleOldWidth;
                            hPos = hPos > 0 ? 0 : hPos;
                            $dataPanel.css({ "margin-left": hPos + "px" });
                            element.scrollNavigation.panelMargin = hPos;
                            element.hPosition = hPos;
                            element.scaleOldWidth = null;
                        } else {
                            $dataPanel.css({ "margin-left": element.hPosition + "px" });
                            element.scrollNavigation.panelMargin = element.hPosition;
                        }
                        core.repositionLabel(element);
                    } else {
                        core.repositionLabel(element);
                    }
                } else {
                    if ((element.hPosition !== 0)) {
                        if (element.scaleOldWidth) {
                            mLeft = ($dataPanel.width() - $rightPanel.width());
                            hPos = mLeft * element.hPosition / element.scaleOldWidth;
                            hPos = hPos > 0 ? 0 : hPos;
                            $dataPanel.css({ "margin-left": hPos + "px" });
                            element.scrollNavigation.panelMargin = hPos;
                            element.hPosition = hPos;
                            element.scaleOldWidth = null;
                        } else {
                            $dataPanel.css({ "margin-left": element.hPosition + "px" });
                            element.scrollNavigation.panelMargin = element.hPosition;
                        }
                        core.repositionLabel(element);
                    } else {
                        core.repositionLabel(element);
                    }
                }

                $dataPanel.css({ height: $leftPanel.height() });
                core.waitToggle(element, false);
            },
            leftPanel: function (element) {
                /* Left panel */
                var ganttLeftPanel = $('<div class="leftPanel"/>')
                    .append($('<div class="row spacer"/>')
                    .css("height", tools.getCellSize() * element.headerRows/2 + "px")
                    .css("width", "100%"));
                
                //terry mark leftpanel
                
                //usability cell height is 1 
                //bolder is consider as 1 px
                //segment is null when draw the driver condition map;
                if(element.usability != null){
                    var heightLength = (element.segment.length + 1) * tools.getCellSize()/2 - 1;
                    
                    for (var i = 0; i < element.usability.length ; i ++) {
                    	var segmentArea = []; 
                    	
                    	var categoryName = element.usability[i].categoryName;
                    	var categoryId = element.usability[i].categoryId;
                    	
                    	var div = $('<div class="categoryName segmentArea ' + i + '" style="height: '+heightLength+'px; width: 100%; cursor: pointer;" />');
                    	if(element.segment.length > 0){
                    		div.append($('<span class="fn-label undefined" id = "'+ categoryId +'"></span>').html(categoryName));
                    	}else{
                    		div.append($('<span class="fn-label undefined" id = "'+ categoryId +'"></span>').html(categoryName).click(function (){ $("#categoryId").val($(this).attr("id"));tools.reload (0);}));
                    	}
                    	ganttLeftPanel.append(div);
                    }
                }
                
                //var entries = [];
                $.each(element.data, function (i, entry) {
                    if (i >= element.pageNum * settings.itemsPerPage && i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {
                        //entries.push('<div class="row name row' + i + '" id="rowheader' + i + '" offset="' + i * tools.getCellSize() + '">');
                        //entries.push('<span class="fn-label ' + entry.cssClass + '">' + entry.name + '</span>');
                        //entries.push('</div>');
                        //entries.push('<div class="row desc row' + i + ' " id="RowdId_' + i + '" data-id="' + entry.id + '">');
                        //entries.push('<span class="fn-label ' + entry.cssClass + '">' + entry.desc + '</span>');
                        //entries.push('</div>');
                    	
                    	var divName = $('<div class="row name row' + i + '" id="rowheader' + i + '" offset="' + i * tools.getCellSize() + '"/>');
                    	divName.append($('<span class="fn-label ' + entry.cssClass + '"/>')
                    			.css({
                            		cursor: 'pointer'
                                })
                                .data("id", entry.id)
                    			.html(entry.name).click(function () {settings.onMenuNameClick($(this).data("id"));}));
                    	
                    	var divDes = $('<div class="row desc row' + i + ' " id="RowdId_' + i + '"/>');
                    	divDes.append($('<span class="fn-label ' + entry.cssClass + '">' + entry.desc + '</span>'));
                    	
                    	ganttLeftPanel.append(divName);
                    	ganttLeftPanel.append(divDes);
                    }
                });
                //ganttLeftPanel.append(entries.join(""));
                return ganttLeftPanel;
            },
            dataPanel: function (element, width) {
                var dataPanel = $('<div class="dataPanel" style="width: ' + width + 'px;"/>');
                /*
                * Mouse wheel events
                */
                var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";

                if (document.attachEvent) {
                    element.attachEvent("on" + mousewheelevt, function (e) { core.wheelScroll(element, e); });
                } else if (document.addEventListener) {
                    element.addEventListener(mousewheelevt, function (e) { core.wheelScroll(element, e); }, false);
                }


                // addNEwClick
                dataPanel.click(function (e) {

                    e.stopPropagation();
                    var corrX, corrY;
                    var leftpanel = $(element).find(".fn-gantt .leftPanel");
                    var datapanel = $(element).find(".fn-gantt .dataPanel");
                    switch (settings.scale) {
                        case "weeks":
                            corrY = tools.getCellSize() * 2;
                            break;
                        case "months":
                            corrY = tools.getCellSize();
                            break;
                        case "hours":
                        case "days":
                            corrY = tools.getCellSize() * 3;
                            break;
                        default:
                            corrY = tools.getCellSize() * 2;
                            break;
                    }

                    // Adjust, so get middle of elm
                    // corrY -= Math.floor(tools.getCellSize() / 2);

                    //find column
                    var col = core.elementFromPoint(e.pageX, datapanel.offset().top + corrY);
                    // hit the label?
                    if (col.className === "fn-label") {
                        col = $(col.parentNode);
                    } else {
                        col = $(col);
                    }

                    var dt = col.attr("repdate");
                    //find row
                    var row = core.elementFromPoint(leftpanel.offset().left + leftpanel.width() - 10, e.pageY);
                    // hit the label?
                    if (row.className.indexOf("fn-label") === 0) {
                        row = $(row.parentNode);
                    } else {
                        row = $(row);
                    }
                    var rowId = row.data().id;

                    settings.onAddClick(dt, rowId);
                });
                return dataPanel;
            },
            // Creates Data container with header
            rightPanel: function (element, leftPanel) {
            	//terry mark right
                var range = null;
                var dowClass = [" sn", " wd", " wd", " wd", " wd", " wd", " sa"];
                var gridDowClass = [" sn", "", "", "", "", "", " sa"];

                var yearArr = ['<div class="row"/>'];
                var daysInYear = 0;

                var monthArr = ['<div class="row"/>'];
                var daysInMonth = 0;

                var weekArr = ['<div class="row"/>'];
                var daysInWeek = 0;

                var dayArr = [];

                var hoursInDay = 0;

                var dowArr = [];

                var horArr = [];


                var today = new Date();
                today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
                var holidays = settings.holidays ? settings.holidays.join() : '';

                switch (settings.scale) {
                    // hours /////////////////////////////////////////////////////////////////////////////////////////                      
                    case "hours":

                        range = tools.parseTimeRange(element.dateStart, element.dateEnd, element.scaleStep);

                        var year = range[0].getFullYear();
                        var month = range[0].getMonth();
                        var day = range[0];

                        for (var i = 0; i < range.length; i++) {
                            var rday = range[i];
                            /*
                            * Fill years
                            */
                            var rfy = rday.getFullYear();
                            if (rfy !== year) {
                                yearArr.push(
                                    ('<div class="row header year" style="width: '
                                        + tools.getCellSize() * (daysInYear-1)
                                        + 'px;"><div class="fn-label">'
                                        + year
                                        + '</div></div>'));

                                year = rfy;
                                daysInYear = 0;
                            }
                            daysInYear++;

                            /*
                            * Fill months
                            */
                            var rm = rday.getMonth();
                            if (rm !== month) {
                                monthArr.push(
                                    ('<div class="row header month" style="width: '
                                    + tools.getCellSize() * (daysInMonth-1) + 'px"><div class="fn-label">'
                                    + settings.months[month]
                                    + '</div></div>'));

                                month = rm;
                                daysInMonth = 0;
                            }
                            daysInMonth++;

                            /*
                            * Fill days & hours
                            */
                            var rgetDay = rday.getDay();
                            var getDay = day.getDay();
                            var day_class = dowClass[rgetDay];
                            var getTime = day.getTime();
                            if (holidays.indexOf((new Date(rday.getFullYear(), rday.getMonth(), rday.getDate())).getTime()) > -1) {
                                day_class = "holiday";
                            }
                            if (rgetDay !== getDay) {

                                var day_class2 = (today - day === 0) ? 'today' : (holidays.indexOf(getTime) > -1) ? "holiday" : dowClass[getDay];

                                dayArr.push('<div class="row day ' + day_class2 + '" '
                                        + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
                                        + ' <div class="fn-label">' + day.getDate() + '</div></div>');
                                
                                dowArr.push('<div class="row day ' + day_class2 + '" '
                                        + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
                                        + ' <div class="fn-label">' + settings.dow[getDay] + '</div></div>');

                                day = rday;
                                hoursInDay = 0;
                            }
                            hoursInDay++;

                            horArr.push('<div class="row day '
                                    + day_class
                                    + '" id="dh-'
                                    + rday.getTime()
                                    + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                    + rday.getHours()
                                    + '</div>');
                        }                        


                        /*
                        * Last year
                        */

                        yearArr.push(
                            '<div class="row header year" style="width: '
                            + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
                            + year
                            + '</div></div>');
                        /*
                        * Last month
                        */
                        monthArr.push(
                            '<div class="row header month" style="width: '
                            + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
                            + settings.months[month]
                            + '</div></div>');

                        var day_class2 = (today - day === 0) ? 'today' : (holidays.indexOf(getTime) > -1) ? "holiday" : dowClass[getDay];

                        dayArr.push('<div class="row day ' + day_class2 + '" '
                                + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
                                + ' <div class="fn-label">' + day.getDate() + '</div></div>');

                        dowArr.push('<div class="row day ' + day_class2 + '" '
                                + ' style="width: ' + tools.getCellSize() * hoursInDay + 'px;"> '
                                + ' <div class="fn-label">' + settings.dow[getDay] + '</div></div>');

                        var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());

                        /*
                        * Append panel elements
                        */

                        dataPanel.append(yearArr.join(""));
                        dataPanel.append(monthArr.join(""));
                        dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
                        dataPanel.append($('<div class="row"/>').html(dowArr.join("")));
                        dataPanel.append($('<div class="row"/>').html(horArr.join("")));
                        
                        
                      //segment is null when draw the driver condition map;
                        if(element.usability != null){
                        for (var j = 0; j < element.usability.length ; j ++) {
                        	
                            var usabilityArr = [];    
                           	for (var i = 0; i < range.length; i++) {
                           		var rday = range[i];
                           		var use=element.usability[j].usability[i * element.scaleStep]; 
                           		var color=element.usability[j].color[i * element.scaleStep]; 
                           		if(use<=0){
                           			usabilityArr.push('<div class="row day '
                                            + ''
                                            + '" id="dh-'
                                            + rday.getTime()
                                            + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                            + ''
                                            + '</div>');       
                           		}else{
                           			if(color<=0){
                           				usabilityArr.push('<div class="row day usabilityGreen'
                                                + ''
                                                + '" id="dh-'
                                                + rday.getTime()
                                                + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                                + use
                                                + '</div>');    
                           			}else{
                               		 	usabilityArr.push('<div class="row day usabilityRed '
                                                + 'wd'
                                                + '" id="dh-'
                                                + rday.getTime()
                                                + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                                + use
                                                + '</div>');   
                           			}
                           		}                            
                           	}
                           	
                           	dataPanel.append($('<div class="row"/>').html(usabilityArr.join("")));
                       }
                       	 
                        
                        }

                        break;

                    // weeks /////////////////////////////////////////////////////////////////////////////////////////                      
                    case "weeks":
                        range = tools.parseWeeksRange(element.dateStart, element.dateEnd);
                        yearArr = ['<div class="row"/>'];
                        monthArr = ['<div class="row"/>'];
                        var year = range[0].getFullYear();
                        var month = range[0].getMonth();
                        var day = range[0];

                        for (var i = 0; i < range.length; i++) {
                            var rday = range[i];
                            /*
                            * Fill years
                            */
                            if (rday.getFullYear() !== year) {
                                yearArr.push(
                                    ('<div class="row header year" style="width: '
                                        + tools.getCellSize() * daysInYear
                                        + 'px;"><div class="fn-label">'
                                        + year
                                        + '</div></div>'));
                                year = rday.getFullYear();
                                daysInYear = 0;
                            }
                            daysInYear++;

                            /*
                            * Fill months
                            */
                            if (rday.getMonth() !== month) {
                                monthArr.push(
                                    ('<div class="row header month" style="width:'
                                       + tools.getCellSize() * daysInMonth
                                       + 'px;"><div class="fn-label">'
                                       + settings.months[month]
                                       + '</div></div>'));
                                month = rday.getMonth();
                                daysInMonth = 0;
                            }
                            daysInMonth++;
                            /*
                            * Fill weeks
                            */
                            dayArr.push('<div class="row day wd" '
                                    + ' id="' + rday.getWeekId() + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '"> '
                                    + ' <div class="fn-label">' + rday.getWeekOfYear() + '</div></div>');
                        }

                        /*
                        * Last year
                        */
                        yearArr.push(
                            '<div class="row header year" style="width: '
                            + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
                            + year
                            + '</div></div>');
                        /*
                        * Last month
                        */
                        monthArr.push(
                            '<div class="row header month" style="width: '
                            + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
                            + settings.months[month]
                            + '</div></div>');

                        var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());


                        dataPanel.append(yearArr.join("") + monthArr.join("") + dayArr.join("") + (dowArr.join("")));



                        break;
                    // months ////////////////////////////////////////////////////////////////////////////////////////                      
                    case 'months':
                        range = tools.parseMonthsRange(element.dateStart, element.dateEnd);

                        var year = range[0].getFullYear();
                        var month = range[0].getMonth();
                        var day = range[0];

                        for (var i = 0; i < range.length; i++) {
                            var rday = range[i];
                            /*
                            * Fill years
                            */
                            if (rday.getFullYear() !== year) {
                                yearArr.push(
                                    ('<div class="row header year" style="width: '
                                        + tools.getCellSize() * daysInYear
                                        + 'px;"><div class="fn-label">'
                                        + year
                                        + '</div></div>'));
                                year = rday.getFullYear();
                                daysInYear = 0;
                            }
                            daysInYear++;
                            monthArr.push('<div class="row day wd" id="dh-' + tools.genId(rday.getTime()) + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '">' + (1 + rday.getMonth()) + '</div>');



                        }

                        /*
                        * Last year
                        */
                        yearArr.push(
                            '<div class="row header year" style="width: '
                            + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
                            + year
                            + '</div></div>');
                        /*
                        * Last month
                        */
                        monthArr.push(
                            '<div class="row header month" style="width: '
                            + tools.getCellSize() * daysInMonth + 'px">"<div class="fn-label">'
                            + settings.months[month]
                            + '</div></div>');

                        var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());

                        /*
                        * Append panel elements
                        */
                        dataPanel.append(yearArr.join(""));
                        dataPanel.append(monthArr.join(""));
                        dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
                        dataPanel.append($('<div class="row"/>').html(dowArr.join("")));


                        break;
                    // days //////////////////////////////////////////////////////////////////////////////////////////                      
                    case "days":
                        range = tools.parseDateRange(element.dateStart, element.dateEnd);

                        var year = range[0].getFullYear();
                        var month = range[0].getMonth();       
                        var once=true;

                        for (var i = 0; i < range.length; i++) {
                            var rday = range[i];
                            /*
                            * Fill years
                            */
                            if (rday.getFullYear() !== year) {
                                yearArr.push(
                                    ('<div class="row header year" style="width:'
                                        + tools.getCellSize() * (daysInYear-1)
                                        + 'px;"><div class="fn-label">'
                                        + year
                                        + '</div></div>'));
                                year = rday.getFullYear();
                                daysInYear = 0;
                            }
                            daysInYear++;

                            /*
                            * Fill months
                            */
                            if (rday.getMonth() !== month) {
                            	if(once==true){
                                monthArr.push(
                                    ('<div class="row header month" style="width:'
                                       + tools.getCellSize() * (daysInMonth-1)
                                       + 'px;"><div class="fn-label">'
                                       + settings.months[month]
                                       + '</div></div>'));
                            		 once=false;
                            	}else{
                                monthArr.push(
                                             ('<div class="row header month" style="width:'
                                                + tools.getCellSize() * (daysInMonth)
                                                + 'px;"><div class="fn-label">'
                                                + settings.months[month]
                                                + '</div></div>'));
                            	}                              
                                month = rday.getMonth();
                                daysInMonth = 0;
                            }
                            daysInMonth++;
                            
                            /*
                             * Fill weeks
                             */   
                             if (rday.getDay()==0&&daysInWeek!=0) {
                                 weekArr.push(
                                     ('<div class="row day wd" style="width:'
                                        + tools.getCellSize() * (daysInWeek)
                                        + 'px;"><div class="fn-label">'
                                        + (rday.getWeekOfYear())
                                        + '</div></div>'));                   
                                 daysInWeek = 0;
                             }
                             daysInWeek++;

                            var getDay = rday.getDay();
                            var day_class = dowClass[getDay];
                            if (holidays.indexOf((new Date(rday.getFullYear(), rday.getMonth(), rday.getDate())).getTime()) > -1) {
                                day_class = "holiday";
                            }

                            dayArr.push('<div class="row day ' + day_class + '" '
                                    + ' id="dh-' + tools.genId(rday.getTime()) + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '> '
                                    + ' <div class="fn-label">' + rday.getDate() + '</div></div>');
                            dowArr.push('<div class="row day ' + day_class + '" '
                                    + ' id="dw-' + tools.genId(rday.getTime()) + '"  repdate="' + rday.genRepDate() + '"> '
                                    + ' <div class="fn-label">' + settings.dow[getDay] + '</div></div>');
                        } //for

                        /*
                        * Last year
                        */
                        yearArr.push(
                            '<div class="row header year" style="width: '
                            + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
                            + year
                            + '</div></div>');
                        /*
                        * Last month
                        */
                        monthArr.push(
                            '<div class="row header month" style="width: '
                            + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
                            + settings.months[month]
                            + '</div></div>');
                        
                        /*
                         * Last week
                         */
                        if(daysInWeek>1)
                         weekArr.push(
                             '<div class="row day wd" style="width: '
                             + tools.getCellSize() * (daysInWeek-1) + 'px"><div class="fn-label">'
                             + (rday.getWeekOfYear())
                             + '</div></div>');

                        var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());

                        /*
                        * Append panel elements
                        */
                        dataPanel.append(yearArr.join(""));
                        dataPanel.append(monthArr.join(""));
                        dataPanel.append(weekArr.join(""));
                        dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
                        dataPanel.append($('<div class="row"/>').html(dowArr.join("")));
                        
                        //segment is null when draw the driver condition map;
                        if(element.usability != null){
                        	for (var j = 0; j < element.usability.length ; j ++) {
                        	
                        		var usabilityArr = [];    
                        		for (var k = 0; k < range.length; k++) {
                        			 var rday = range[k];  
                        			 var use=element.usability[j].usability[k];
                                   	 var color=element.usability[j].color[k]; 
                                   		if(use<=0){
                                   			usabilityArr.push('<div class="row day '
                                                    + ''
                                                    + '" id="dh-'
                                                    + rday.getTime()
                                                    + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                                    + ''
                                                    + '</div>');       
                                   		}else{
                                   			if(color<=0){
                                   				usabilityArr.push('<div class="row day usabilityGreen'
                                                        + ''
                                                        + '" id="dh-'
                                                        + rday.getTime()
                                                        + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                                        + use
                                                        + '</div>');    
                                   			}else{
                                       		 	usabilityArr.push('<div class="row day usabilityRed '
                                                        + 'wd'
                                                        + '" id="dh-'
                                                        + rday.getTime()
                                                        + '"  offset="' + i * tools.getCellSize() + '"  repdate="' + rday.genRepDate() + '"> '
                                                        + use
                                                        + '</div>');   
                                   			}
                                   		}   
                        	
                        	}
                           	
                           	dataPanel.append($('<div class="row"/>').html(usabilityArr.join("")));
                       }
                        }
                        break;
                    default:
                        range = tools.parseDateRange(element.dateStart, element.dateEnd)/2;

                        var year = range[0].getFullYear();
                        var month = range[0].getMonth();
                        var day = range[0];

                        for (var i = 0; i < range.length; i++) {
                            var rday = range[i];
                            /*
                            * Fill years
                            */
                            if (rday.getFullYear() !== year) {
                                yearArr.push(
                                    ('<div class="row header year" style="width:'
                                        + tools.getCellSize() * daysInYear
                                        + 'px;"><div class="fn-label">'
                                        + year
                                        + '</div></div>'));
                                year = rday.getFullYear();
                                daysInYear = 0;
                            }
                            daysInYear++;

                            /*
                            * Fill months
                            */
                            if (rday.getMonth() !== month) {
                                monthArr.push(
                                    ('<div class="row header month" style="width:'
                                       + tools.getCellSize() * daysInMonth
                                       + 'px;"><div class="fn-label">'
                                       + settings.months[month]
                                       + '</div></div>'));
                                month = rday.getMonth();
                                daysInMonth = 0;
                            }
                            daysInMonth++;

                            var getDay = rday.getDay();
                            var day_class = dowClass[getDay];
                            if (holidays.indexOf((new Date(rday.getFullYear(), rday.getMonth(), rday.getDate())).getTime()) > -1) {
                                day_class = "holiday";
                            }

                            dayArr.push('<div class="row day ' + day_class + '" '
                                    + ' id="dh-' + tools.genId(rday.getTime()) + '" offset="' + i * tools.getCellSize() + '" repdate="' + rday.genRepDate() + '> '
                                    + ' <div class="fn-label">' + rday.getDate() + '</div></div>');
                            dowArr.push('<div class="row day ' + day_class + '" '
                                    + ' id="dw-' + tools.genId(rday.getTime()) + '"  repdate="' + rday.genRepDate() + '"> '
                                    + ' <div class="fn-label">' + settings.dow[getDay] + '</div></div>');
                        } //for

                        /*
                        * Last year
                        */
                        yearArr.push(
                            '<div class="row header year" style="width: '
                            + tools.getCellSize() * daysInYear + 'px;"><div class="fn-label">'
                            + year
                            + '</div></div>');
                        /*
                        * Last month
                        */
                        monthArr.push(
                            '<div class="row header month" style="width: '
                            + tools.getCellSize() * daysInMonth + 'px"><div class="fn-label">'
                            + settings.months[month]
                            + '</div></div>');

                        var dataPanel = core.dataPanel(element, range.length * tools.getCellSize());

                        /*
                        * Append panel elements
                        */
                        dataPanel.append(yearArr.join(""));
                        dataPanel.append(monthArr.join(""));
                        dataPanel.append($('<div class="row"/>').html(dayArr.join("")));
                        dataPanel.append($('<div class="row"/>').html(dowArr.join("")));

                        break;
                }

                return $('<div class="rightPanel"></div>').append(dataPanel);
            },


            navigation: function (element) {
                var ganttNavigate = null;
                if (settings.navigate === "scroll") {
                	var nextDay='Next Day';var preDay='Prev Day';
                	var nextWeek='Next Week';var preWeek='Prev Week';        
                	if (settings.scale === 'days') {
                		nextDay='Next Week';preDay='Prev Week';
                    	nextWeek='Next Two Week';preWeek='Prev Two Week';
                      } 
                	var rightDiv=$('<div class="nav-slider-right" />')
                    .append($('<span role="button" class="nav-link nav-next-day" title="'+nextDay+'"+tooltip="'+nextDay+'"/>')
                        .html('&gt;')
                        .click(function () {
                        	 if (settings.scale === 'hours') {
                             	tools.nextDays(1);
                             } else if (settings.scale === 'days') {
                             	tools.nextWeeks(1);
                             } 
                            /*if (settings.scale === 'hours') {
                                core.navigateTo(element, tools.getCellSize() * -4);
                            } else if (settings.scale === 'days') {
                                core.navigateTo(element, tools.getCellSize() * -7);
                            } else if (settings.scale === 'weeks') {
                                core.navigateTo(element, tools.getCellSize() * -4);
                            } else  if (settings.scale === 'months') {
                                core.navigateTo(element, tools.getCellSize() * -3);
                            }*/                              
                        }))
                .append($('<span role="button" class="nav-link nav-next-week" title="'+nextWeek+'"+tooltip="'+nextWeek+'"/>')
                        .html('&gt;&gt;')
                        .click(function () {
                        	if (settings.scale === 'hours') {
                             	tools.nextWeeks(1);
                             } else if (settings.scale === 'days') {
                             	tools.nextWeeks(2);
                             } 
                            /*if (settings.scale === 'hours') {
                                core.navigateTo(element, tools.getCellSize() * -8);
                            } else if (settings.scale === 'days') {
                                core.navigateTo(element, tools.getCellSize() * -30);
                            } else if (settings.scale === 'weeks') {
                                core.navigateTo(element, tools.getCellSize() * -12);
                            } else if (settings.scale === 'months') {
                                core.navigateTo(element, tools.getCellSize() * -6);
                            }*/                              
                        }))
//                    .append($('<span role="button" class="nav-link nav-zoomIn" title="Zoom In" tooltip="Zoom In"/>')
//                        .html('&#43;')
//                        .click(function () {
//                            core.zoomInOut(element, -1);
//                        }))
//                    .append($('<span role="button" class="nav-link nav-zoomOut" title="Zoom Out" tooltip="Zoom Out"/>')
//                        .html('&#45;')
//                        .click(function () {
//                            core.zoomInOut(element, 1);
//                        }));
                	if(element.dayViewUrl&&element.dayViewUrl.length>0){
                		rightDiv.append($('<span role="button" class="nav-link nav-day" title="Daily View" tooltip="Daily View"/>')
                                .html('&#43;')
                                .click(function () {
                                	
                                	location.href = element.dayViewUrl;
                                }));
                	}
                	if(element.weekViewUrl&&element.weekViewUrl.length>0){
                		rightDiv.append($('<span role="button" class="nav-link nav-week" title="Weekly View" tooltip="Weekly View"/>')
                                .html('&gt;&gt;')
                                .click(function () {
                                	location.href = element.weekViewUrl;
                                }));
                	}
                	if(element.monthViewUrl&&element.monthViewUrl.length>0){
                		rightDiv.append($('<span role="button" class="nav-link nav-month" title="Monthly View" tooltip="Monthly View"/>')
                                .html('&gt;&gt;')
                                .click(function () {
                                	location.href = element.monthViewUrl;
                                }));
                	}        
                    ganttNavigate = $('<div class="navigate" />')
                        .append($('<div class="nav-slider" />')
                            .append($('<div class="nav-slider-left" />')
                                .append($('<span role="button" class="nav-link nav-page-back"  title="Prev Page" tooltip="Prev Page"/>')
                                    .html('&lt;')
                                    .click(function () {
                                        core.navigatePage(element, -1);
                                    }))
                                .append($('<div class="page-number"/>')
                                        .append($('<span/>')
                                            .html(element.pageNum + 1 + ' of ' + element.pageCount)))
                                .append($('<span role="button" class="nav-link nav-page-next"  title="Next Page" tooltip="Next Page"/>')
                                    .html('&gt;')
                                    .click(function () {
                                        core.navigatePage(element, 1);
                                    }))
                                .append($('<span role="button" class="nav-link nav-now" title="Today" tooltip="Today"/>')
                                    .html('&#9679;')
                                    .click(function () {
                                        core.navigateTo(element, 'now');
                                    }))
                                .append($('<span role="button" class="nav-link nav-prev-week" title="'+preWeek+'"+tooltip="'+preWeek+'"/>')
                                    .html('&lt;&lt;')
                                    .click(function () {
                                    	 if (settings.scale === 'hours') {
                                         	tools.prevWeeks(1);
                                         } else if (settings.scale === 'days') {
                                         	tools.prevWeeks(2);
                                         } 
                                        /*if (settings.scale === 'hours') {
                                            core.navigateTo(element, tools.getCellSize() * 8);
                                        } else if (settings.scale === 'days') {
                                            core.navigateTo(element, tools.getCellSize() * 30);
                                        } else if (settings.scale === 'weeks') {
                                            core.navigateTo(element, tools.getCellSize() * 12);
                                        } else if (settings.scale === 'months') {
                                            core.navigateTo(element, tools.getCellSize() * 6);
                                        }*/                                 
                                    }))
                                .append($('<span role="button" class="nav-link nav-prev-day" title="'+preDay+'"+tooltip="'+preDay+'"/>')
                                    .html('&lt;')
                                    .click(function () {
                                        if (settings.scale === 'hours') {
                                        	tools.prevDays(1);
                                        } else if (settings.scale === 'days') {
                                        	tools.prevWeeks(1);
                                        } 
                                        /*else if (settings.scale === 'weeks') {
                                            core.navigateTo(element, tools.getCellSize() * 4);
                                        } else if (settings.scale === 'months') {
                                            core.navigateTo(element, tools.getCellSize() * 3);
                                        }*/
                                    	
                                    })))
                            .append($('<div class="nav-slider-content" />')
                                    .append($('<div class="nav-slider-bar" />')
                                            .append($('<a class="nav-slider-button" />')
                                                )
                                                .mousedown(function (e) {
                                                    if (e.preventDefault) {
                                                        e.preventDefault();
                                                    }
                                                    element.scrollNavigation.scrollerMouseDown = true;
                                                    core.sliderScroll(element, e);
                                                })
                                                .mousemove(function (e) {
                                                    if (element.scrollNavigation.scrollerMouseDown) {
                                                        core.sliderScroll(element, e);
                                                    }
                                                })
                                            )
                                        )
                            .append(rightDiv)
                                );
                    $(document).mouseup(function () {
                        element.scrollNavigation.scrollerMouseDown = false;
                    });
                } else {
                    /* Navigation panel */
                    ganttNavigate = $('<div class="navigate" />')
                        .append($('<span role="button" class="nav-link nav-page-back"/>')
                            .html('&lt;')
                            .click(function () {
                                core.navigatePage(element, -1);
                            }))
                        .append($('<div class="page-number"/>')
                                .append($('<span/>')
                                    .html(element.pageNum + 1 + ' of ' + element.pageCount)))
                        .append($('<span role="button" class="nav-link nav-page-next"/>')
                            .html('&gt;')
                            .click(function () {
                                core.navigatePage(element, 1);
                            }))
                        .append($('<span role="button" class="nav-link nav-begin"/>')
                            .html('&#124;&lt;')
                            .click(function () {
                                core.navigateTo(element, 'begin');
                            }))
                        .append($('<span role="button" class="nav-link nav-prev-week"/>')
                            .html('&lt;&lt;')
                            .click(function () {
                                core.navigateTo(element, tools.getCellSize() * 7);
                            }))
                        .append($('<span role="button" class="nav-link nav-prev-day"/>')
                            .html('&lt;')
                            .click(function () {
                                core.navigateTo(element, tools.getCellSize());
                            }))
                        .append($('<span role="button" class="nav-link nav-now"/>')
                            .html('&#9679;')
                            .click(function () {
                            	//terry mark: add timer picker
                                core.navigateTo(element, 'now');
                            }))
                        .append($('<span role="button" class="nav-link nav-next-day"/>')
                            .html('&gt;')
                            .click(function () {
                                core.navigateTo(element, tools.getCellSize() * -1);
                            }))
                        .append($('<span role="button" class="nav-link nav-next-week"/>')
                            .html('&gt;&gt;')
                            .click(function () {
                                core.navigateTo(element, tools.getCellSize() * -7);
                            }))
                        .append($('<span role="button" class="nav-link nav-end"/>')
                            .html('&gt;&#124;')
                            .click(function () {
                                core.navigateTo(element, 'end');
                            }))
                        .append($('<span role="button" class="nav-link nav-zoomIn"/>')
                            .html('&#43;')
                            .click(function () {
                                core.zoomInOut(element, -1);
                            }))
                        .append($('<span role="button" class="nav-link nav-zoomOut"/>')
                            .html('&#45;')
                            .click(function () {
                                core.zoomInOut(element, 1);
                            }));
                }
                return $('<div class="bottom"/>').append(ganttNavigate);
            },
            createProgressBar: function (days, cls, desc, label, id , currentRentalNo ,conflictRentalNos, confilctIds) {
                var cellWidth = tools.getCellSize();
                var barMarg = tools.getProgressBarMargin() || 0;
                var widthValue = ((cellWidth * days) - barMarg) + 5;
                if(widthValue < cellWidth){
                	widthValue = cellWidth;
                }
                var bar = $('<div class="bar"><div class="fn-label">' + label + '</div></div>')
                        .addClass(cls)
                        .css({
                            width: widthValue
                        })
                        .data("id", id)
                        .data("currentRentalNo",currentRentalNo)
                		.data("conflictRentalNos", conflictRentalNos)
                		.data("confilctIds", confilctIds);

                if (desc) {
                    bar
                      .mouseover(function (e) {
                          var hint = $('<div class="fn-gantt-hint" />').html(desc);
                          $("body").append(hint);
                          hint.css("left", e.pageX);
                          hint.css("top", e.pageY);
                          hint.show();
                      })
                      .mouseout(function () {
                          $(".fn-gantt-hint").remove();
                      })
                      .mousemove(function (e) {
                          $(".fn-gantt-hint").css("left", e.pageX);
                          $(".fn-gantt-hint").css("top", e.pageY + 15);
                      });
                }
                bar.click(function (e) {
                    e.stopPropagation();
                    //use flash class to determination what type of the segment
                    var className = $(this).attr("class");
                    switch (className){
                    case "bar ganttFlash":
                    	settings.onConflictItemClick($(this).data("id"),$(this).data("currentRentalNo"),$(this).data("confilctIds"),$(this).data("conflictRentalNos"));
                    	break;
                    case "bar ganttMagenta":
                    	settings.onNoneBillItemClick($(this).data("id"));
                    	break;
                    case "bar ganttRed":
                    	settings.onItemClick($(this).data("id"));
                    	break;
                    case "bar ganttDarkRed":
                    	settings.onItemClick($(this).data("id"));
                    	break;
                    case "bar ganttBlack":                  
                    	break;
                    default :
                    	settings.onDispatchItemClick($(this).data("id"));
                    	break;
                    }
                });
                return bar;
            },
            markNow: function (element) {
                switch (settings.scale) {
                    case "weeks":
                        var cd = Date.parse(new Date());
                        cd = (Math.floor(cd / 36400000) * 36400000);
                        $(element).find(':findweek("' + cd + '")').removeClass('wd').addClass('today');
                        break;
                    case "months":
                        $(element).find(':findmonth("' + new Date().getTime() + '")').removeClass('wd').addClass('today');
                        break;
                    case "hours":              
                        break;
                    default:
                        var cd = Date.parse(new Date());
                        cd = (Math.floor(cd / 36400000) * 36400000);
                        $(element).find(':findday("' + cd + '")').removeClass('wd').addClass('today');
                        break;
                }
            },
            fillStableData: function (element, datapanel, leftpanel) {
            	var invertColor = function (colStr) {
                    try {
                        colStr = colStr.replace("rgb(", "").replace(")", "");
                        var rgbArr = colStr.split(",");
                        var R = parseInt(rgbArr[0],10);
                        var G = parseInt(rgbArr[1],10);
                        var B = parseInt(rgbArr[2],10);
                        var gray = Math.round((255 - (0.299 * R + 0.587 * G + 0.114 * B)) * 0.9, 1);
                        return "rgb(" + gray + ", " + gray + ", " + gray + ")";
                    } catch (err) {
                        return "";
                    }
                };
                
                $.each(element.segment, function (i, entry) {                    
                         var _bar = null;
                         switch (settings.scale) {
                             case "hours":                             	
                            	 var day = entry.values[0];
                                 var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime(), element.scaleStep);
                                 var from = $(element).find('#dh-' + dFrom);
                                
                                 var endDate = tools.reduceOneSecond(day.to);
                                 var dTo = tools.genId(tools.dateDeserialize(endDate).getTime(), element.scaleStep);
                                 var to = $(element).find('#dh-' + dTo);
                                 
                                 var cFrom = from.attr("offset");
                                 var cTo = to.attr("offset");
                                 var dl = Math.floor((cTo - cFrom) / tools.getCellSize()) + 1;

                                 _bar = core.createProgressBar(
                                             dl,
                                             day.customClass ? day.customClass : "",
                                             day.desc ? day.desc : "",
                                             day.label ? day.label : "",
                                             day.id ? day.id : null,
                                             day.rentalNo ? day.rentalNo : null,
                                             day.conflictRentalNos	?  day.conflictRentalNos: null,
                                             day.confilctIds ? 	 day.confilctIds : null
                                         );

                                 // find row
                                 //var topEl = $(element).find("#rowheader" + i);
                                 //terry mark 24pix each cell
                                 // year month date day hour usablility each row,total 6
                                 // + 3 mean is left contain 3 part panel edge , each bold is 1
                                 var top = tools.getCellSize() * (6 + i) + 2 ;//+ parseInt(topEl.attr("offset"),10);
                                 _bar.css({ 'margin-top': top/2, 'margin-left': Math.floor(cFrom) - 48});

                                 datapanel.append(_bar);
                                 break;
                             case "weeks":
                            	 var day = entry.values[0];
                                 var dtFrom = tools.dateDeserialize(day.from);
                                 var dtTo = tools.dateDeserialize(day.to);

                                 if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
                                     dtFrom.setDate(dtFrom.getDate() + 4);
                                 }

                                 if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
                                     dtFrom.setDate(dtFrom.getDate() + 4);
                                 }

                                 if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
                                     dtTo.setDate(dtTo.getDate() + 4);
                                 }

                                 var from = $(element).find("#" + dtFrom.getWeekId());

                                 var cFrom = from.attr("offset");

                                 var to = $(element).find("#" + dtTo.getWeekId());
                                 var cTo = to.attr("offset");

                                 var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;

                                 _bar = core.createProgressBar(
                                          dl,
                                          day.customClass ? day.customClass : "",
                                          day.desc ? day.desc : "",
                                          day.label ? day.label : "",
                                          day.id ? day.id : null,
                                          day.rentalNo ? day.rentalNo : null,
                                          day.conflictRentalNos	?  day.conflictRentalNos: null,
                                          day.confilctIds ? 	 day.confilctIds : null
                                     );

                                 // find row
                                 var topEl = $(element).find("#rowheader" + i);

                                 var top = tools.getCellSize() * 3 + 2 + parseInt(topEl.attr("offset"),10);
                                 _bar.css({ 'margin-top': top/2, 'margin-left': Math.floor(cFrom) });

                                 datapanel.append(_bar);
                                 break;
                             // Days                  
                             case "days":
                            	 	var _bar = null;          	                        
                             			$.each(entry.values, function (k, val) {
                             				if(val.label!=null){
                             					var day = val;
                                 				var dFrom=tools.genId(tools.dateDeserialize(day.from).getTime()); 
                                 				var from = $(element).find("#dh-" + (dFrom-86400000));
                                 				var cFrom = from.attr("offset");
                                 				_bar = core.createProgressBar(
                                                        1,
                                                        day.customClass ? day.customClass : "",
                                                        day.desc ? day.desc : "",
                                                        day.label ? day.label: "",
                                                        day.id ? day.id : null,
                                                        day.rentalNo ? day.rentalNo : null,
                                                        day.conflictRentalNos	?  day.conflictRentalNos: null,
                                                        day.confilctIds ? 	 day.confilctIds : null
                                                      );      			  
                                 				var top = tools.getCellSize() * (6) + 2 ;
                                 				_bar.css({ 'margin-top': top/2, 'margin-left': Math.floor(cFrom) });
                                 				datapanel.append(_bar); 
                             				}                          					
                             			});                  				
                             		break;
                             	 // Days 
                             default:
                            	 var day = entry.values[0];
                                 var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime());
                                 var dTo = tools.genId(tools.dateDeserialize(day.to).getTime());

                                 var from = $(element).find("#dh-" + dFrom);
                                 var cFrom = from.attr("offset");

                                 var dl = Math.floor(((dTo / 1000) - (dFrom / 1000)) / 86400) + 1;
                                 _bar = core.createProgressBar(
                                             dl,
                                             day.customClass ? day.customClass : "",
                                             day.desc ? day.desc : "",
                                             day.label ? day.label : "",
                                             day.id ? day.id : null
                                     );

                                 // find row
                                 var topEl = $(element).find("#rowheader" + i);

                                 var top = tools.getCellSize() * 4 + 2 + parseInt(topEl.attr("offset"),10);
                                 _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });

                                 datapanel.append(_bar);

                                 break;
                         }
                       if(_bar){
                         var $l = _bar.find(".fn-label");
                         if ($l && _bar.length) {
                             var gray = invertColor(_bar[0].style.backgroundColor);
                             $l.css("color", gray);
                         } else if ($l) {
                             $l.css("color", "");
                         }
                       }
                     });
                
            },
            fillData: function (element, datapanel, leftpanel) {
                var invertColor = function (colStr) {
                    try {
                        colStr = colStr.replace("rgb(", "").replace(")", "");
                        var rgbArr = colStr.split(",");
                        var R = parseInt(rgbArr[0],10);
                        var G = parseInt(rgbArr[1],10);
                        var B = parseInt(rgbArr[2],10);
                        var gray = Math.round((255 - (0.299 * R + 0.587 * G + 0.114 * B)) * 0.9, 1);
                        return "rgb(" + gray + ", " + gray + ", " + gray + ")";
                    } catch (err) {
                        return "";
                    }
                };
                $.each(element.data, function (i, entry) {
                    if (i >= element.pageNum * settings.itemsPerPage && i < (element.pageNum * settings.itemsPerPage + settings.itemsPerPage)) {

                        $.each(entry.values, function (j, day) {
                            var _bar = null;
                            switch (settings.scale) {
                                case "hours":
                                    var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime(), element.scaleStep);
                                    var from = $(element).find('#dh-' + dFrom);
                                   
                                    var endDate = tools.reduceOneSecond(day.to);
                                    var dTo = tools.genId(tools.dateDeserialize(endDate).getTime(), element.scaleStep);
                                    var to = $(element).find('#dh-' + dTo);
                                    
                                    var cFrom = from.attr("offset");
                                    var cTo = to.attr("offset");
                                    var dl = Math.floor((cTo - cFrom) / tools.getCellSize()) + 1;

                                    _bar = core.createProgressBar(
                                                dl,
                                                day.customClass ? day.customClass : "",
                                                day.desc ? day.desc : "",
                                                day.label ? day.label : "",
                                                day.id ? day.id : null,
                                                day.rentalNo ? day.rentalNo : null,
                                                day.conflictRentalNos ? day.conflictRentalNos: null,
                                                day.confilctIds ?  day.confilctIds : null
                                            );

                                    // find row
                                    var topEl = $(element).find("#rowheader" + i);
                                    //terry mark 24pix each cell
                                    // year month date day hour usablility each row,total 6
                                    // + 3 mean is left contain 3 part panel edge , each bold is 1
                                    // if the segment isnull , we wont draw useblility row.
                                    var segmentLength = element.segment == null ? -1: element.segment.length;
                                    var marginTopLength = segmentLength - element.pageNum * settings.itemsPerPage;
                                    var top = tools.getCellSize() * (6 + marginTopLength) + 2  + parseInt(topEl.attr("offset"),10);
                                    _bar.css({ 'margin-top': top/2, 'margin-left': Math.floor(cFrom) - 48});

                                    datapanel.append(_bar);
                                    break;
                                case "weeks":
                                    var dtFrom = tools.dateDeserialize(day.from);
                                    var dtTo = tools.dateDeserialize(day.to);

                                    if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
                                        dtFrom.setDate(dtFrom.getDate() + 4);
                                    }

                                    if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
                                        dtFrom.setDate(dtFrom.getDate() + 4);
                                    }

                                    if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
                                        dtTo.setDate(dtTo.getDate() + 4);
                                    }

                                    var from = $(element).find("#" + dtFrom.getWeekId());

                                    var cFrom = from.attr("offset");

                                    var to = $(element).find("#" + dtTo.getWeekId());
                                    var cTo = to.attr("offset");

                                    var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;

                                    _bar = core.createProgressBar(
                                             dl,
                                             day.customClass ? day.customClass : "",
                                             day.desc ? day.desc : "",
                                             day.label ? day.label : "",
                                            day.id ? day.id : null
                                        );

                                    // find row
                                    var topEl = $(element).find("#rowheader" + i);

                                    var top = tools.getCellSize() * 3 + 2 + parseInt(topEl.attr("offset"),10);
                                    _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });

                                    datapanel.append(_bar);
                                    break;
                                case "months":

                                    var dtFrom = tools.dateDeserialize(day.from);
                                    var dtTo = tools.dateDeserialize(day.to);

                                    if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
                                        dtFrom.setDate(dtFrom.getDate() + 4);
                                    }

                                    if (dtFrom.getDate() <= 3 && dtFrom.getMonth() === 0) {
                                        dtFrom.setDate(dtFrom.getDate() + 4);
                                    }

                                    if (dtTo.getDate() <= 3 && dtTo.getMonth() === 0) {
                                        dtTo.setDate(dtTo.getDate() + 4);
                                    }

                                    var from = $(element).find("#dh-" + tools.genId(dtFrom.getTime()));
                                    var cFrom = from.attr("offset");
                                    var to = $(element).find("#dh-" + tools.genId(dtTo.getTime()));
                                    var cTo = to.attr("offset");
                                    var dl = Math.round((cTo - cFrom) / tools.getCellSize()) + 1;

                                    _bar = core.createProgressBar(
                                        dl,
                                        day.customClass ? day.customClass : "",
                                        day.desc ? day.desc : "",
                                        day.label ? day.label : "",
                                        day.id ? day.id : null
                                    );

                                    // find row
                                    var topEl = $(element).find("#rowheader" + i);

                                    var top = tools.getCellSize() * 2 + 2 + parseInt(topEl.attr("offset"),10);
                                    _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom)});

                                    datapanel.append(_bar);
                                    break;
                                 // Days                  
                                case "days":
                                	if(day.label){
                                		var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime());
                                		var from = $(element).find("#dh-" + (dFrom-86400000));                                
                                		var cFrom = from.attr("offset");                       		
                                		_bar = core.createProgressBar(
                                				1,
                                				day.customClass ? day.customClass : "",
                                				day.desc ? day.desc: "",
                                				day.label ? day.label : "",
                                				day.id ? day.id : null,
                                				day.rentalNo ? day.rentalNo : null,
                                				day.conflictRentalNos ? day.conflictRentalNos: null,
                                				day.confilctIds ?  day.confilctIds : null
                                		);
                                		// find row
                                		var topEl = $(element).find("#rowheader" + i);
                                		var segmentLength = element.segment == null ? -1: element.segment.length;
                                        var marginTopLength = segmentLength - element.pageNum * settings.itemsPerPage;
                                		var top = tools.getCellSize() * (6 + marginTopLength) + 2 + parseInt(topEl.attr("offset"),10);
                                		_bar.css({ 'margin-top': top/2, 'margin-left': Math.floor(cFrom) });

                                		datapanel.append(_bar); 
                                	}
                                    break;
                                                  
                                default:
                                    var dFrom = tools.genId(tools.dateDeserialize(day.from).getTime());
                                    var dTo = tools.genId(tools.dateDeserialize(day.to).getTime());

                                    var from = $(element).find("#dh-" + dFrom);
                                    var cFrom = from.attr("offset");

                                    var dl = Math.floor(((dTo / 1000) - (dFrom / 1000)) / 86400) + 1;
                                    _bar = core.createProgressBar(
                                                dl,
                                                day.customClass ? day.customClass : "",
                                                day.desc ? day.desc : "",
                                                day.label ? day.label : "",
                                                day.id ? day.id : null,
                                                day.rentalNo ? day.rentalNo : null,
                                                day.conflictRentalNos ? day.conflictRentalNos: null,
                                                day.confilctIds ?  day.confilctIds : null
                                        );

                                    // find row
                                    var topEl = $(element).find("#rowheader" + i);
                                    var marginTopLength = element.segment == null ? -1: element.segment.length;
                                    var top = tools.getCellSize() * (6 + marginTopLength) + 2 + parseInt(topEl.attr("offset"),10);
                                    _bar.css({ 'margin-top': top, 'margin-left': Math.floor(cFrom) });

                                    datapanel.append(_bar);

                                    break;
                            }
                           if(_bar){
                            var $l = _bar.find(".fn-label");
                            if ($l && _bar.length) {
                                var gray = invertColor(_bar[0].style.backgroundColor);
                                $l.css("color", gray);
                            } else if ($l) {
                                $l.css("color", "");
                            }
                           }
                        });

                    }
                });
            },

            navigateTo: function (element, val) {
                var $rightPanel = $(element).find(".fn-gantt .rightPanel");
                var $dataPanel = $rightPanel.find(".dataPanel");
                $dataPanel.click = function () {
                    alert(arguments.join(""));
                };
                var rightPanelWidth = $rightPanel.width();
                var dataPanelWidth = $dataPanel.width();

                switch (val) {
                    case "begin":
                        $dataPanel.animate({
                            "margin-left": "0px"
                        }, "fast", function () { core.repositionLabel(element); });
                        element.scrollNavigation.panelMargin = 0;
                        break;
                    case "end":
                        var mLeft = dataPanelWidth - rightPanelWidth;
                        element.scrollNavigation.panelMargin = mLeft * -1;
                        $dataPanel.animate({
                            "margin-left": "-" + mLeft + "px"
                        }, "fast", function () { core.repositionLabel(element); });
                        break;
                    case "now":
                        if (!element.scrollNavigation.canScroll) {
                            return false;
                        }
                        var max_left = (dataPanelWidth - rightPanelWidth) * -1;
                        var cur_marg = $dataPanel.css("margin-left").replace("px", "");
                        var val = $dataPanel.find(".today").offset().left - $dataPanel.offset().left;
                        val *= -1;
                        if (val > 0) {
                            val = 0;
                        } else if (val < max_left) {
                            val = max_left;
                        }
                        $dataPanel.animate({
                            "margin-left": val + "px"
                        }, "fast", core.repositionLabel(element));
                        element.scrollNavigation.panelMargin = val;
                        break;
                    default:
                        var max_left = (dataPanelWidth - rightPanelWidth) * -1;
                        var cur_marg = $dataPanel.css("margin-left").replace("px", "");
                        var val = parseInt(cur_marg,10) + val;
                        if (val <= 0 && val >= max_left) {
                            $dataPanel.animate({
                                "margin-left": val + "px"
                            }, "fast", core.repositionLabel(element));
                        }
                        element.scrollNavigation.panelMargin = val;
                        break;
                }



            },
            navigatePage: function (element, val) {
                if ((element.pageNum + val) >= 0 && (element.pageNum + val) < Math.ceil(element.rowsNum / settings.itemsPerPage)) {
                    core.waitToggle(element, true, function () {
                        element.pageNum += val;
                        element.hPosition = $(".fn-gantt .dataPanel").css("margin-left").replace("px", "");
                        element.scaleOldWidth = false;
                        core.init(element);
                    });
                }
            },
            zoomInOut: function (element, val) {
                core.waitToggle(element, true, function () {

                    var zoomIn = (val < 0);

                    var scaleSt = element.scaleStep + val * 3;
                    scaleSt = scaleSt <= 1 ? 1 : scaleSt === 4 ? 3 : scaleSt;
                    var scale = settings.scale;
                    var headerRows = element.headerRows;
                    if (settings.scale === "hours" && scaleSt >= 13) {
                        scale = "days";
                        headerRows = 4;
                        scaleSt = 13;
                    } else if (settings.scale === "days" && zoomIn) {
                        scale = "hours";
                        headerRows = 5;
                        scaleSt = 12;
                    } else if (settings.scale === "days" && !zoomIn) {
                        scale = "weeks";
                        headerRows = 3;
                        scaleSt = 13;
                    } else if (settings.scale === "weeks" && !zoomIn) {
                        scale = "months";
                        headerRows = 2;
                        scaleSt = 14;
                    } else if (settings.scale === "weeks" && zoomIn) {
                        scale = "days";
                        headerRows = 4;
                        scaleSt = 13;
                    } else if (settings.scale === "months" && zoomIn) {
                        scale = "weeks";
                        headerRows = 3;
                        scaleSt = 13;
                    }

                    if ((zoomIn && $.inArray(scale, scales) < $.inArray(settings.minScale, scales))
                        || (!zoomIn && $.inArray(scale, scales) > $.inArray(settings.maxScale, scales))) {
                        core.init(element);
                        return;
                    }
                    element.scaleStep = scaleSt;
                    settings.scale = scale;
                    element.headerRows = headerRows;
                    var $rightPanel = $(element).find(".fn-gantt .rightPanel");
                    var $dataPanel = $rightPanel.find(".dataPanel");
                    element.hPosition = $dataPanel.css("margin-left").replace("px", "");
                    element.scaleOldWidth = ($dataPanel.width() - $rightPanel.width());

                    if (settings.useCookie) {
                        $.cookie(this.cookieKey + "CurrentScale", settings.scale);
                        // reset scrollPos
                        $.cookie(this.cookieKey + "ScrollPos", null);
                    }
                    core.init(element);
                });
            },
            mouseScroll: function (element, e) {
                var $dataPanel = $(element).find(".fn-gantt .dataPanel");
                $dataPanel.css("cursor", "move");
                var bPos = $dataPanel.offset();
                var mPos = element.scrollNavigation.mouseX === null ? e.pageX : element.scrollNavigation.mouseX;
                var delta = e.pageX - mPos;
                element.scrollNavigation.mouseX = e.pageX;

                core.scrollPanel(element, delta);

                clearTimeout(element.scrollNavigation.repositionDelay);
                element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 50, element);
            },
            wheelScroll: function (element, e) {
                var delta = e.detail ? e.detail * (-50) : e.wheelDelta / 120 * 50;

                core.scrollPanel(element, delta);

                clearTimeout(element.scrollNavigation.repositionDelay);
                element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 50, element);

                if (e.preventDefault) {
                    e.preventDefault();
                } else {
                    return false;
                }
            },
            sliderScroll: function (element, e) {
                var $sliderBar = $(element).find(".nav-slider-bar");
                var $sliderBarBtn = $sliderBar.find(".nav-slider-button");
                var $rightPanel = $(element).find(".fn-gantt .rightPanel");
                var $dataPanel = $rightPanel.find(".dataPanel");

                var bPos = $sliderBar.offset();
                var bWidth = $sliderBar.width();
                var wButton = $sliderBarBtn.width();

                var pos, mLeft;

                if ((e.pageX >= bPos.left) && (e.pageX <= bPos.left + bWidth)) {
                    pos = e.pageX - bPos.left;
                    pos = pos - wButton / 2;
                    $sliderBarBtn.css("left", pos);

                    mLeft = $dataPanel.width() - $rightPanel.width();

                    var pPos = pos * mLeft / bWidth * -1;
                    if (pPos >= 0) {
                        $dataPanel.css("margin-left", "0px");
                        element.scrollNavigation.panelMargin = 0;
                    } else if (pos >= bWidth - (wButton * 1)) {
                        $dataPanel.css("margin-left", mLeft * -1 + "px");
                        element.scrollNavigation.panelMargin = mLeft * -1;
                    } else {
                        $dataPanel.css("margin-left", pPos + "px");
                        element.scrollNavigation.panelMargin = pPos;
                    }
                    clearTimeout(element.scrollNavigation.repositionDelay);
                    element.scrollNavigation.repositionDelay = setTimeout(core.repositionLabel, 5, element);
                }
            },
            scrollPanel: function (element, delta) {
                if (!element.scrollNavigation.canScroll) {
                    return false;
                }
                var _panelMargin = parseInt(element.scrollNavigation.panelMargin,10) + delta;
                if (_panelMargin > 0) {
                    element.scrollNavigation.panelMargin = 0;
                    $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
                } else if (_panelMargin < element.scrollNavigation.panelMaxPos * -1) {
                    element.scrollNavigation.panelMargin = element.scrollNavigation.panelMaxPos * -1;
                    $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
                } else {
                    element.scrollNavigation.panelMargin = _panelMargin;
                    $(element).find(".fn-gantt .dataPanel").css("margin-left", element.scrollNavigation.panelMargin + "px");
                }
                core.synchronizeScroller(element);
            },
            synchronizeScroller: function (element) {
                if (settings.navigate === "scroll") {
                    var $rightPanel = $(element).find(".fn-gantt .rightPanel");
                    var $dataPanel = $rightPanel.find(".dataPanel");
                    var $sliderBar = $(element).find(".nav-slider-bar");
                    var $sliderBtn = $sliderBar.find(".nav-slider-button");

                    var bWidth = $sliderBar.width();
                    var wButton = $sliderBtn.width();

                    var mLeft = $dataPanel.width() - $rightPanel.width();
                    var hPos = 0;
                    if ($dataPanel.css("margin-left")) {
                        hPos = $dataPanel.css("margin-left").replace("px", "");
                    }
                    var pos = hPos * bWidth / mLeft - $sliderBtn.width() * 0.25;
                    pos = pos > 0 ? 0 : (pos * -1 >= bWidth - (wButton * 0.75)) ? (bWidth - (wButton * 1.25)) * -1 : pos;
                    $sliderBtn.css("left", pos * -1);
                }
            },
            repositionLabel: function (element) {
                setTimeout(function () {
                    var $dataPanel;
                    if (!element) {
                        $dataPanel = $(".fn-gantt .rightPanel .dataPanel");
                    } else {
                        var $rightPanel = $(element).find(".fn-gantt .rightPanel");
                        $dataPanel = $rightPanel.find(".dataPanel");
                    }

                    if (settings.useCookie) {
                        $.cookie(this.cookieKey + "ScrollPos", $dataPanel.css("margin-left").replace("px", ""));
                    }
                }, 500);
            },
            /*waitToggle: function (element, show, fn) {
                if (show) {
                    var eo = $(element).offset();
                    var ew = $(element).outerWidth();
                    var eh = $(element).outerHeight();

                    if (!element.loader) {
                        element.loader = $('<div class="fn-gantt-loader" style="position: absolute; top: ' + eo.top + 'px; left: ' + eo.left + 'px; width: ' + ew + 'px; height: ' + eh + 'px;">'
                        + '<div class="fn-gantt-loader-spinner"><span>' + settings.waitText + '</span></div></div>');
                    }
                    $("body").append(element.loader);
                    setTimeout(fn, 100);

                } else {
                    if (element.loader) {
                        element.loader.remove();
                    }
                    element.loader = null;
                    
                }
            }*/
            
            //we handle the mask layer outside gantt
            waitToggle: function (element, show, fn) {
            	setTimeout(fn, 100);
            }
        };

        /**
        * Additional functions
        */
        var tools = {
        	reduceOneSecond:function (element){
        		var date = new Date(element);
        		return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()-1);
        	},
            getMaxDate: function (element) {
                var maxDate = null;
                $.each(element.data, function (i, entry) {
                    $.each(entry.values, function (i, date) {
                        maxDate = maxDate < tools.dateDeserialize(date.to) ? tools.dateDeserialize(date.to) : maxDate;
                    });
                });

                switch (settings.scale) {
                    case "hours":
                        maxDate.setHours(Math.ceil((maxDate.getHours()) / element.scaleStep) * element.scaleStep);
                        maxDate.setHours(maxDate.getHours() + element.scaleStep * 3);
                        break;
                    case "weeks":
                        var bd = new Date(maxDate.getTime());
                        var bd = new Date(bd.setDate(bd.getDate() + 3 * 7));
                        var md = Math.floor(bd.getDate() / 7) * 7;
                        maxDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
                        break;
                    case "months":
                        var bd = new Date(maxDate.getFullYear(), maxDate.getMonth(), 1);
                        bd.setMonth(bd.getMonth() + 2);
                        maxDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
                        break;
                    default:
                        maxDate.setHours(0);
                        maxDate.setDate(maxDate.getDate() + 3);
                        break;
                }
                return maxDate;
            },
            getMinDate: function (element) {
                var minDate = null;
                $.each(element.data, function (i, entry) {
                    $.each(entry.values, function (i, date) {
                        minDate = minDate > tools.dateDeserialize(date.from) || minDate === null ? tools.dateDeserialize(date.from) : minDate;
                    });
                });
                switch (settings.scale) {
                    case "hours":
                        minDate.setHours(Math.floor((minDate.getHours()) / element.scaleStep) * element.scaleStep);
                        minDate.setHours(minDate.getHours() - element.scaleStep * 3);
                        break;
                    case "weeks":
                        var bd = new Date(minDate.getTime());
                        var bd = new Date(bd.setDate(bd.getDate() - 3 * 7));
                        var md = Math.floor(bd.getDate() / 7) * 7;
                        minDate = new Date(bd.getFullYear(), bd.getMonth(), md === 0 ? 4 : md - 3);
                        break;
                    case "months":
                        var bd = new Date(minDate.getFullYear(), minDate.getMonth(), 1);
                        bd.setMonth(bd.getMonth() - 3);
                        minDate = new Date(bd.getFullYear(), bd.getMonth(), 1);
                        break;
                    default:
                        minDate.setHours(0);
                        minDate.setDate(minDate.getDate() - 3);
                        break;
                }
                return minDate;
            },
            parseDateRange: function (from, to) {
                var current = new Date(from.getTime());
                var end = new Date(to.getTime());
                var ret = [];
                var i = 0;
                do {
                    ret[i++] = new Date(current.getTime());
                    current.setDate(current.getDate() + 1);
                } while (current.getTime() <= to.getTime());
                return ret;

            },
            parseTimeRange: function (from, to, scaleStep) {
                var current = new Date(from);
                var end = new Date(to);
                var ret = [];
                var i = 0;
                do {
                    ret[i] = new Date(current.getTime());
                    current.setHours(current.getHours() + scaleStep);
                    current.setHours(Math.floor((current.getHours()) / scaleStep) * scaleStep);

                    if (current.getDay() !== ret[i].getDay()) {
                        current.setHours(0);
                    }

                    i++;
                } while (current.getTime() <= to.getTime());
                return ret;
            },
            parseWeeksRange: function (from, to) {

                var current = new Date(from);
                var end = new Date(to);

                var ret = [];
                var i = 0;
                do {

                    if (current.getDay() === 0) {
                        ret[i++] = current.getDayForWeek();
                    }
                    current.setDate(current.getDate() + 1);
                } while (current.getTime() <= to.getTime());

                return ret;
            },
            parseMonthsRange: function (from, to) {

                var current = new Date(from);
                var end = new Date(to);

                var ret = [];
                var i = 0;
                do {
                    ret[i++] = new Date(current.getFullYear(), current.getMonth(), 1);
                    current.setMonth(current.getMonth() + 1);
                } while (current.getTime() <= to.getTime());

                return ret;
            },
            dateDeserialize: function (dateStr) {
            	//dateStr = "2011,02,01,15,30,00";
                //var date = eval("new Date(" + dateStr + ")");
            	var date = new Date(dateStr );
                return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes());
            },



            genId: function (ticks) {
                var t = new Date(ticks);
                switch (settings.scale) {
                    case "hours":
                        var hour = t.getHours();
                        if (arguments.length >= 2) {
                            hour = (Math.floor((t.getHours()) / arguments[1]) * arguments[1]);
                        }
                        return (new Date(t.getFullYear(), t.getMonth(), t.getDate(), hour)).getTime();
                    case "weeks":
                        var y = t.getFullYear();
                        var w = t.getDayForWeek().getWeekOfYear();
                        var m = t.getMonth();
                        if (m === 11 && w === 1) {
                            y++;
                        }
                        return y + "-" + w;
                    case "months":
                        return t.getFullYear() + "-" + t.getMonth();
                    default:
                        return (new Date(t.getFullYear(), t.getMonth(), t.getDate())).getTime();
                }
            },
            _getCellSize: null,
            getCellSize: function () {
                if (!tools._getCellSize) {
                    $("body").append(
                        $('<div style="display: none; position: absolute;" class="fn-gantt" id="measureCellWidth"><div class="row"></div></div>')
                    );
                    tools._getCellSize = $("#measureCellWidth .row").height()*2;
                    $("#measureCellWidth").empty().remove();
                }
                return tools._getCellSize;
            },
            getRightPanelSize: function () {
                $("body").append(
                    $('<div style="display: none; position: absolute;" class="fn-gantt" id="measureCellWidth"><div class="rightPanel"></div></div>')
                );
                var ret = $("#measureCellWidth .rightPanel").height();
                $("#measureCellWidth").empty().remove();
                return ret;
            },
            getPageHeight: function (element) {
                return element.pageNum + 1 === element.pageCount ? element.rowsOnLastPage * tools.getCellSize() : settings.itemsPerPage * tools.getCellSize();
            },
            _getProgressBarMargin: null,
            getProgressBarMargin: function () {
                if (!tools._getProgressBarMargin) {
                    $("body").append(
                        $('<div style="display: none; position: absolute;" id="measureBarWidth" ><div class="fn-gantt"><div class="rightPanel"><div class="dataPanel"><div class="row day"><div class="bar" /></div></div></div></div></div>')
                    );
                    tools._getProgressBarMargin = parseInt($("#measureBarWidth .fn-gantt .rightPanel .day .bar").css("margin-left").replace("px", ""),10);
                    tools._getProgressBarMargin += parseInt($("#measureBarWidth .fn-gantt .rightPanel .day .bar").css("margin-right").replace("px", ""),10);
                    $("#measureBarWidth").empty().remove();
                }
                return tools._getProgressBarMargin;
            },
            
            prevDays : function (count){
            	tools.reload (-1 * count);
            },
            
            nextDays : function (count){
            	tools.reload (1 * count);
            },
            
            prevWeeks : function (count){
            	tools.reload (-7 * count);
            },
            
            nextWeeks : function (count){
            	tools.reload (7 * count);
            },
            
            reload : function (day,categoryId) {
            	settings.reload(day,categoryId);
            },
            
            getEndDateValidateScale:function(element,startDate){
            	switch (settings.scale) {
                case "hours": 
                	element.dateEnd = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 3,
                		startDate.getHours()-1,startDate.getMinutes()); break;
                case "days":  element.dateEnd = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 40,
                		startDate.getHours()-1,startDate.getMinutes()); break;
                case "weeks":break;
                case "months":break;
                default: 
            	}
            }
        };
        
        this.each(function () {

            /**
            * Extend options with default values
            */
            if (options) {
                $.extend(settings, options);
            }

            this.data = null;        // Recived data
            this.pageNum = 0;        // Current page number
            this.pageCount = 0;      // Aviable pages count
            this.rowsOnLastPage = 0; // How many rows on last page
            this.rowsNum = 0;        //
            this.hPosition = 0;      // Current position on diagram (Horizontal)
            this.dateStart = null;
            this.dateEnd = null;
            this.scrollClicked = false;
            this.scaleOldWidth = null;
            this.headerRows = null;

            if (settings.useCookie) {
                var sc = $.cookie(this.cookieKey + "CurrentScale");
                if (sc) {
                    settings.scale = $.cookie(this.cookieKey + "CurrentScale");
                } else {
                    $.cookie(this.cookieKey + "CurrentScale", settings.scale);
                }
            }

            switch (settings.scale) {
                case "hours": this.headerRows = 5; this.scaleStep = 1; break;
                case "weeks": this.headerRows = 3; this.scaleStep = 13; break;
                case "months": this.headerRows = 2; this.scaleStep = 14; break;
                case "days": this.headerRows = 5; this.scaleStep = 13; break;
                default: this.headerRows = 4; this.scaleStep = 13; break;
            }

            this.scrollNavigation = {
                panelMouseDown: false,
                scrollerMouseDown: false,
                mouseX: null,
                panelMargin: 0,
                repositionDelay: 0,
                panelMaxPos: 0,
                canScroll: true
            };

            this.gantt = null;
            this.loader = null;

            core.create(this);

        });

    };
};});