isys.namespace("controls.calendar");

var LongMonthNames = ['January','February','March','April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var ShortMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
var LongDayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thurday', 'Friday', 'Saturday'];
var ShortDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

Date.prototype.startOfTheMonth = function() {
    var retVal = new Date(this.getFullYear(), this.getMonth(), 1, 0, 0, 0);
    return retVal;
};
Date.prototype.startOfTheYear = function() {
    return new Date(this.getFullYear(), 0, 1, 0, 0, 0);
};
Date.prototype.endOfTheYear = function() {
    return new Date(this.getFullYear(), 11, 31, 0, 0, 0);
};
Date.prototype.endOfTheMonth = function(trunc) {
    var retVal = this.startOfTheMonth();
    retVal.setMonth(this.getMonth() + 1);
    retVal.setSeconds(-1);
    return new Date(retVal.getFullYear(), retVal.getMonth(), retVal.getDate(), 0, 0, 1);
};
Date.prototype.startOfDay = function() {
    return new Date(this.getFullYear(), this.getMonth(), this.getDate());
};
Date.prototype.endOfDay = function() {
    return new Date(this.getFullYear(), this.getMonth(), this.getDate(), 23, 59, 59);
};
Date.prototype.daysInMonth = function() {
    return this.endOfTheMonth().getDate() - this.startOfTheMonth().getDate() + 1;
};
Date.prototype.incDay = function(amount) {
    var retVal = new Date(this);
    retVal.setDate(this.getDate() + amount);
    return retVal;
};
Date.prototype.incMonth = function(amount) {
    var retVal = new Date(this);
    retVal.setMonth(this.getMonth() + amount);
    return retVal;
};
Date.prototype.incYear = function(amount) {
    var retVal = new Date(this);
    retVal.setFullYear(this.getFullYear() + amount);
    return retVal;
};
Date.prototype.incHour = function(amount) {
    var retVal = new Date(this);
    retVal.setHours(this.getHours() + amount);
    return retVal;
};
Date.prototype.incMinute = function(amount) {
    var retVal = new Date(this);
    retVal.setMinutes(this.getMinutes() + amount);
    return retVal;
};
Date.prototype.incSecond = function(amount) {
    var retVal = new Date(this);
    retVal.setSeconds(this.getSeconds() + amount);
    return retVal;
};
Date.prototype.monthName = function(abbr) {
    if (abbr)
        return ShortMonthNames[this.getMonth()];
    else
        return LongMonthNames[this.getMonth()];
};
Date.prototype.inc = function(interval, value) {
    switch (interval) {
        case "yyyy":
            return this.incYear(value);
        case "m":
            return this.incMonth(value);
        case "y":
        case "d":
        case "w":
            return this.incDay(value);
        case "ww":
            return this.incDay(value * 7);
        case "h":
            return this.incHour(value);
        case "n":
            return this.incMinute(value);
        case "s":
            return this.incSecond(value);
    }
};
Date.prototype.millisecondsBetween = function(date) {
    return this - date;
};
Date.prototype.secondsBetween = function(date) {
    return this.millisecondsBetween(date) / 1000;
};    
Date.prototype.minutesBetween = function(date) {
    return this.secondsBetween(date) / 60;
};    
Date.prototype.hoursBetween = function(date) {
    return this.minutesBetween(date) / 60;
};    
Date.prototype.daysBetween = function(date) {
    return this.hoursBetween(date) / 24;
};
Date.prototype.weeksBetween = function(date) {
    return this.daysBetween(date) / 7;
};
Date.prototype.rowsRequired = function() {
    var start = this.startOfTheMonth();
    start = start.incDay(-start.getDay());
    var end = this.endOfTheMonth(true);

    return Math.ceil(end.weeksBetween(start));
};
Date.prototype.firstCell = function() {
    var retVal = this.startOfTheMonth();
    return retVal.incDay(-retVal.getDay());
};
Date.prototype.sameDay = function(date) {
    return (this.getFullYear() == date.getFullYear())
        && (this.getMonth() == date.getMonth())
        && (this.getDate() == date.getDate());
};

isys.controls.calendar.Month = function(date) {
    if (date)
        this.m_date = date;
    else
        this.m_date = new Date();
        
	this.onSelectDate = null;
};
isys.controls.calendar.Month.prototype = {
    m_date: null,
    m_cells: [],
    m_dest: null,
    highlightToday: true,
    onSelectDate: null,

    _renderMonth: function(table) {
        var row;
        var row = table.insertRow(-1);
        left = row.insertCell(-1);
        middle = row.insertCell(-1);
        right = row.insertCell(-1);

        var img = isys.createElement("img", left);
        img.src = "/WebShared/js/isysCalendar/prev.gif";
        this._hookImage(img, -1);

        var img = isys.createElement("img", right);
        img.src = "/WebShared/js/isysCalendar/next.gif";
        this._hookImage(img, 1);

        middle.className = "isysCalMonthName";
        middle.colSpan = 5;
        middle.innerHTML = LongMonthNames[this.m_date.getMonth()] + " " + this.m_date.getFullYear();
    },
    _hookImage: function(img, dir) {
        var me = this;
        img.onclick = function() {
            if (dir > 0)
                me.next();
            else
                me.previous();
        };
    },


    render: function(dest) {
        if (!dest)
            dest = this.m_dest;
        this.m_dest = dest;
        this.m_dest.innerHTML = "";

        var tbl = isys.createElement("table", dest, "isysCalendarSmall");
        tbl.border = 0;
        tbl.cellPadding = 0;
        tbl.cellSpacing = 0;
        var dt = this.m_date.firstCell();
        var now = new Date();

        var head = tbl.createTHead();
        this._renderMonth(head);

        var row = head.insertRow(-1);
        for (var c = 0; c < 7; c++) {
            var cell = row.insertCell(-1);
            cell.width = "14%";
            cell.className = "isysCalHeader";
            cell.innerHTML = ShortDayNames[c].substring(0, 2); ;
        }

        m_cells = [];
        rowCount = 6; //this.m_date.rowsRequired()
        for (var r = 0; r < rowCount; r++) {
            m_cells[r] = [];
            var row = tbl.insertRow(-1);
            for (var c = 0; c < 7; c++) {
                m_cells[r][c] = [];
                m_cells[r][c].inMonth = dt.getMonth() == this.m_date.getMonth();
                m_cells[r][c].date = dt;

                var cell = row.insertCell(-1);
                cell.width = "14%";
                if (m_cells[r][c].inMonth)
                    cell.className = "isysCalDay ";
                else
                    cell.className = "isysCalDay isysCalDiffMonth";

                cell.className += (c == 0 ? " isysCalCellLeft" : "")
                    + (r == rowCount - 1 ? " isysCalCellBottom" : "")
                    + (this.highlightToday && now.sameDay(dt) ? " isysCalCellToday" : "");

                var div = isys.createElement("div", cell);

                div.innerHTML = dt.getDate();
                dt = dt.incDay(1);

                m_cells[r][c].cell = cell;

                this._syncEvents(m_cells[r][c]);
            }
        }

        tbl.style.width = tbl.offsetHeight + "px";
    },
    _syncEvents: function(item) {
        if (item.inMonth) {
            var me = this;
            item.cell.onmouseover = function(e) {
                isys.addClass(item.cell, "isysCalCellOver");
            };
            item.cell.onmouseout = function(e) {
                isys.removeClass(item.cell, "isysCalCellOver");
            };
            item.cell.onclick = function(e) {
                if (me.onSelectDate && me.onSelectDate(item.date))
                    me.hide();
            };
        }
    },

    setDate: function(date) {
        this.m_date = date;
        this.render(null);
    },
    getDate: function() {
        return this.m_date;
    },
    previous: function() {
        this.setDate(this.getDate().incMonth(-1));
    },

    next: function() {
        this.setDate(this.getDate().incMonth(1));
    },

    popup: function(x, y) {
        if (!this.m_dest) {
            this.m_dest = document.createElement("div");
            this.m_dest.style.backgroundColor = "white";
            document.body.appendChild(this.m_dest);

            this.m_dest.style.position = "absolute";
            this.m_dest.style.left = "-1000px";
            this.m_dest.style.top = "-1000px";
            this.m_dest.className = "isysCalendar";
            this.render(this.m_dest);
            this.m_dest.style.display = "none";
        }

        this.m_dest.style.left = x + "px";
        this.m_dest.style.top = y + "px";
        this.m_dest.style.position = "absolute";
        this.m_dest.style.display = "inline";

        var me = this;
        evnt = function(e) {
            if (!e) e = window.event;
            var target = e.target || e.srcElement;

            if (!isys.controls.isChildOf(target, me.m_dest)) {
                me.hide();

                isys.events.detachEvent(document, "mousedown", me.mouseDownEvent);
                me.mouseDownEvent = null;
            }
        };
        me.mouseDownEvent = evnt;

        isys.events.attachEvent(document, "mousedown", me.mouseDownEvent);
    },
    hide: function() {
        this.m_dest.style.display = "none";
    }
};


isys.controls.calendar.Monthly = function() {
    this.m_date = new Date();
    this.ondatechange = null;
    this.onrendercell = null;
    this.cells = [];
};
isys.controls.calendar.Monthly.prototype = {
    m_date: null,
    m_dest: null,
    m_selected: null,
    cells: [],
    ondatechange: null,
    onrendercell: null,
    headerHeight: 20,
    
    showLoading: function(show) {
        if (show) {
            this.m_loading = isys.ajaxLoading(this.div);
            this.m_loading.style.display = "inline";
        } else if (this.m_loading) {
            this.m_loading.style.display = "none";
        }
    },    
    
    render: function(dest) {
        this.m_selected = null;
        this.cells = [];
        if (dest)
            this.m_dest = dest;
        
        this.m_dest.innerHTML = "";
        var size = isys.getPos(this.m_dest);
        size.height -= this.headerHeight + 1;

        var start = this.m_date.startOfTheMonth();
        start = start.incDay(-start.getDay());
        var end = this.m_date.endOfTheMonth(true);
        var rowCount = Math.ceil(end.weeksBetween(start));
        var colCount = 7;
        var colWidth = Math.floor(size.width / colCount);
        var rowHeight = Math.floor(size.height / rowCount);

        this.rangeFrom = new Date(start);
        this.rangeTo = end.endOfDay();

        //window.status = end.weeksBetween(start); //"RowCount: " + rowCount + "; Width: " + colWidth + "; Height: " + rowHeight 
        
        this.div = isys.createElement("div", this.m_dest, "isyscalendar");
        var hdr = isys.createElement("div", this.div, "isysCalendarHeaderRow");
        for (var i = 0; i < colCount; i++) {
            var cell = isys.createElement("div", hdr, "isysCalendarDay");
            cell.style.left = Math.round(i * colWidth) + "px";
            cell.style.width = Math.round(colWidth) + "px";
            cell.style.height = this.headerHeight + "px";
            cell.innerHTML = LongDayNames[i];
        }
        
        var lastMonth = -1;
        for (var r = 0; r < rowCount; r++) {
            for (var c = 0; c < colCount; c++) {
                var cell = isys.createElement("div", this.div, "isysCalendarCell isysCalendarCell" + c);
                cell.style.left = Math.round(c * colWidth) + "px";
                cell.style.top = Math.round(r * rowHeight) + this.headerHeight + "px";
                cell.style.width = Math.round(colWidth) + "px";
                cell.style.height = Math.round(rowHeight) + "px";
                if (start.getMonth() != this.m_date.getMonth())
                    isys.addClass(cell, "isysCalendarCellDiffMonth");
                
                var header = isys.createElement("div", cell, "isysCalendarCellHeader " + (start.getMonth() != this.getDate().getMonth()?"isysCalendarCellHeaderDiff":""));
                if (lastMonth != start.getMonth()) 
                    header.innerHTML = start.getDate() + " " + ShortMonthNames[start.getMonth()];
                else
                    header.innerHTML = start.getDate();                    
                    
                var body = isys.createElement("div", cell, "isysCalendarCellBody");
                body.style.height = rowHeight - header.offsetHeight - 3 + "px";
                body.style.width = colWidth - 1 + "px";
                body.date = start;
                if (this.onrendercell)
                    this.onrendercell(this, start, body);
               
                this.cells[start.startOfDay()] = [];
                this.cells[start.startOfDay()].cell = cell;
                this.cells[start.startOfDay()].body = body;
                    
                this.syncBody(body);
               
                lastMonth = start.getMonth();
                start = start.incDay(1);
            }
        }

        if (this.ondatechange)
            this.ondatechange(this);
    },
    syncBody: function(body) {
        var me = this;
        body.onclick = function(e) {
            me.select(body);
        }
    },
    
    select: function(item) {
        if (this.m_selected)
            this.m_selected.style.backgroundColor = "";
        item.style.backgroundColor = "#F8E49B";

        this.m_selected = item;
    
    },
    
    setDate: function(date) {
        this.m_date = date;
        this.render(null);
    },
    
    getDate: function() {
        return this.m_date;
    },
    
    previous: function() {
        this.setDate(this.getDate().incMonth(-1));
    },
    
    next: function() {
        this.setDate(this.getDate().incMonth(1));
    },
    today: function() {
        this.setDate(new Date());
    },
    getCell: function(when) {
        var dt = new Date(when).startOfDay();
        return this.cells[dt.startOfDay()];
    },
    
    createCalendarItem: function(dest) {
        var retVal = isys.createElement("div", dest, "isysCalendarItem");
        isys.createElement("div", retVal, "isysCalendarItemBorder");
        var body = isys.createElement("div", retVal, "isysCalendarItemBody");
        isys.createElement("div", retVal, "isysCalendarItemBorder");
        
        return body;
    }
};
