﻿Type.registerNamespace("VacationRoost.Web.Common");

VacationRoost.Web.Common.CalendarBase = function(element) {
    VacationRoost.Web.Common.CalendarBase.initializeBase(this, [element]);

    this._element = element;
    this._cellProperties = null;
    this._firstDate = null;
    this._firstMonthContainer = null;
    this._firstMonthHeader = null;
    this._firstMonthTable = null;
    this._secondMonthContainer = null;
    this._secondMonthHeader = null;
    this._secondMonthTable = null;

    this._nextButton = null;
    this._nextClickDelegate = Function.createDelegate(this, this._nextClickHandler);
    this._previousButton = null;
    this._previousClickDelegate = Function.createDelegate(this, this._previousClickHandler);

    this._dayCells = null;
    this._firstMonthStartIndex = null;
    this._firstMonthEndIndex = null;
    this._secondMonthStartIndex = null;
    this._secondMonthEndIndex = null;

    this._earliestAllowedCheckIn = new Date().getDateOnly();

    this._initialized = false;

    this._dateCellClickDelegate = Function.createDelegate(this, this._dateCellClickHandler);
};

VacationRoost.Web.Common.CalendarBase.GetFirstChildWithNodeName = function(parent, nodeName) {
    for (var i = 0; i < parent.childNodes.length; i++) {
        if (parent.childNodes[i].nodeName == nodeName) {
            return parent.childNodes[i];
        }
    }

    return null;
};

if (!Date.prototype.getDateOnly) {
    Date.prototype.getDateOnly = function Date$getDateOnly() {
        /// <summary>
        /// Gets a Date representing the Date only part of the Date
        /// </summary>
        /// <returns type="Date" />

        return new Date(this.getFullYear(), this.getMonth(), this.getDate());
    }
}

VacationRoost.Web.Common.CalendarBase.prototype = {
    initialize: function ()
    {
        VacationRoost.Web.Common.CalendarBase.callBaseMethod(this, 'initialize');

        this._firstMonthHeader = VacationRoost.Web.Common.CalendarBase.GetFirstChildWithNodeName(this._firstMonthContainer, "H3");
        this._firstMonthTable = VacationRoost.Web.Common.CalendarBase.GetFirstChildWithNodeName(this._firstMonthContainer, "TABLE");

        if (this._secondMonthContainer)
        {
            this._secondMonthHeader = VacationRoost.Web.Common.CalendarBase.GetFirstChildWithNodeName(this._secondMonthContainer, "H3");
            this._secondMonthTable = VacationRoost.Web.Common.CalendarBase.GetFirstChildWithNodeName(this._secondMonthContainer, "TABLE");
        }

        this._initializeDayCellsArray();
        this._setMonthIndices();
        this._initializeDayCells();

        this._initializeNextAndPrevious();

        this._initialized = true;
    },

    _initializeDayCellsArray: function ()
    {
        //Loop through both calendars collecting the td
        //elements in the dayCells array
        this._dayCells = [];

        this._collectDayCells(this._dayCells, this._firstMonthTable);
        if (this._secondMonthContainer)
        {
            this._collectDayCells(this._dayCells, this._secondMonthTable);
        }
    },

    _collectDayCells: function (dayCells, table)
    {
        //Skip the first tr because it is just the header
        var tbody = VacationRoost.Web.Common.CalendarBase.GetFirstChildWithNodeName(table, "TBODY");

        var tbodyChildIndex = 0;
        while (tbody.childNodes[tbodyChildIndex].nodeName != "TR")
        {
            tbodyChildIndex++;
        }

        tbodyChildIndex++;

        while (tbodyChildIndex < tbody.childNodes.length)
        {
            if (tbody.childNodes[tbodyChildIndex].nodeName == "TR")
            {
                var tr = tbody.childNodes[tbodyChildIndex];
                var trChildIndex = 0;
                while (trChildIndex < tr.childNodes.length)
                {
                    if (tr.childNodes[trChildIndex].nodeName == "TD")
                    {
                        dayCells[dayCells.length] = tr.childNodes[trChildIndex];
                    }
                    trChildIndex++;
                }
            }

            tbodyChildIndex++;
        }
    },

    _setMonthIndices: function ()
    {
        //Calculate the indices of the first and last
        //days of the first and second months
        var firstMonthBegin = this._firstDate;
        var secondMonthBegin = new Date(firstMonthBegin.getFullYear(), firstMonthBegin.getMonth() + 1, 1);
        var thirdMonthBegin = new Date(secondMonthBegin.getFullYear(), secondMonthBegin.getMonth() + 1, 1);

        var daysInFirstMonth = new Date(secondMonthBegin.getFullYear(), secondMonthBegin.getMonth(), 0).getDate();
        var daysInSecondMonth = new Date(thirdMonthBegin.getFullYear(), thirdMonthBegin.getMonth(), 0).getDate();

        this._firstMonthStartIndex = firstMonthBegin.getDay()
        this._firstMonthEndIndex = this._firstMonthStartIndex + daysInFirstMonth - 1;

        this._secondMonthStartIndex = secondMonthBegin.getDay() + 42;
        this._secondMonthEndIndex = this._secondMonthStartIndex + daysInSecondMonth - 1;
    },

    _initializeDayCells: function ()
    {
        for (var i = 0; i < this._dayCells.length; i++)
        {
            if (i >= this._firstMonthStartIndex && i <= this._firstMonthEndIndex)
            {
                var currentDate = new Date(this._firstDate.getFullYear(), this._firstDate.getMonth(), i - this._firstMonthStartIndex + 1);
                this._initializeDayCell(this._dayCells[i], currentDate);
            }
            else if (this._secondMonthContainer && i >= this._secondMonthStartIndex && i <= this._secondMonthEndIndex)
            {
                var currentDate = new Date(this._firstDate.getFullYear(), this._firstDate.getMonth() + 1, i - this._secondMonthStartIndex + 1);
                this._initializeDayCell(this._dayCells[i], currentDate);
            }
            else
            {
                this._disposeDayCell(this._dayCells[i]);
            }
        }
    },

    _initializeDayCell: function (cell, date)
    {
        cell.date = date;

        var cellProperties = this._cellProperties[date.localeFormat("d")];

        cell.rateText = cellProperties ? cellProperties.rateText : null;
        cell.checkInDisabled = cellProperties ? cellProperties.checkInDisabled : null;
        cell.checkOutDisabled = cellProperties ? cellProperties.checkOutDisabled : null;
        cell.cellClass = cellProperties ? cellProperties.cellClass : null;

        var checkInAllowed = (!cellProperties || !cellProperties.checkInDisabled);
        var checkOutAllowed = (!cellProperties || !cellProperties.checkOutDisabled);

        if (date >= this._earliestAllowedCheckIn && (checkInAllowed || checkOutAllowed))
        {
            if (!cell.hasClickHandler)
            {
                Sys.UI.DomEvent.addHandler(cell, 'click', this._dateCellClickDelegate);
                cell.hasClickHandler = true;
            }
        }
        else if (cell.hasClickHandler)
        {
            Sys.UI.DomEvent.removeHandler(cell, 'click', this._dateCellClickDelegate);
            cell.hasClickHandler = false;
        }
    },

    _disposeDayCell: function (cell)
    {
        cell.date = null;

        if (cell.hasClickHandler)
        {
            Sys.UI.DomEvent.removeHandler(cell, 'click', this._dateCellClickDelegate);
            cell.hasClickHandler = false;
        }
    },

    _initializeNextAndPrevious: function ()
    {
        Sys.UI.DomEvent.addHandler(this._nextButton, 'click', this._nextClickDelegate);
        Sys.UI.DomEvent.addHandler(this._previousButton, 'click', this._previousClickDelegate);

        this._nextButton.style.visibility = "";
        this._setPreviousButtonVisibility();
    },

    _updateMonthHeaders: function ()
    {
        this._updateHeader(this._firstMonthHeader, this._firstDate);
        if (this._secondMonthContainer)
        {
            this._updateHeader(this._secondMonthHeader, new Date(this._firstDate.getFullYear(), this._firstDate.getMonth() + 1, 1));
        }
    },

    _updateHeader: function (header, date)
    {
        //Clear the text of the header
        while (header.childNodes.length > 0)
        {
            header.removeChild(header.firstChild);
        }

        header.appendChild(document.createTextNode(date.localeFormat("MMMM yyyy")));
    },

    _updateDayCells: function ()
    {
        var containsConflictedDates = false;

        for (var i = 0; i < this._dayCells.length; i++)
        {
            var cell = this._dayCells[i];

            //Clear the text of the cell
            while (cell.childNodes.length > 0)
            {
                cell.removeChild(cell.firstChild);
            }

            cell.className = "";

            if (cell.date)
            {
                var cssClass = this._getCellCssClass(cell);

                if (cssClass == "conflicted")
                {
                    containsConflictedDates = true;
                }

                Sys.UI.DomElement.addCssClass(cell, cssClass);
                if (cell.cellClass)
                {
                    Sys.UI.DomElement.addCssClass(cell, cell.cellClass);
                }

                var dateSpan = document.createElement("span");
                dateSpan.appendChild(document.createTextNode(cell.date.getDate()));
                cell.appendChild(dateSpan);

                var cellPropertiesKey = cell.date.localeFormat("d");
                if (this._cellProperties[cellPropertiesKey] && this._cellProperties[cellPropertiesKey].rateText)
                {
                    cell.appendChild(document.createElement("br"));
                    cell.innerHTML = cell.innerHTML + this._cellProperties[cellPropertiesKey].rateText;
                    //cell.appendChild(document.createTextNode(this._cellProperties[cellPropertiesKey].rateText));
                }
            }
            else
            {
                cell.appendChild(document.createTextNode("\u00a0")); //Put a non breaking space in an empty cell
            }
        }
    },

    _dateCellClickHandler: function (event)
    {
        var dateCell = event.target;

        while (dateCell.tagName != "TD" && dateCell.parentNode)
        {
            dateCell = dateCell.parentNode;
        }

        if (dateCell.tagName != "TD")
        {
            return;
        }

        this._dateCellClickInternal(dateCell);
    },

    _dateCellClickInternal: function (dateCell)
    {
        //empty, this will change depending on the sub-class
    },

    _getCellCssClass: function (cell)
    {
        if (cell.date < this._earliestAllowedCheckIn)
        {
            return "unavailable";
        }

        var checkInDisabled = cell.checkInDisabled;
        var checkOutDisabled = cell.checkOutDisabled;

        if (checkInDisabled && checkOutDisabled)
        {
            return "unavailable";
        }

        if (checkInDisabled)
        {
            return "availableForCheckOut";
        }

        if (checkOutDisabled)
        {
            return "availableForCheckIn";
        }

        return "";
    },

    _nextClickHandler: function ()
    {
        this._changeFirstDate(new Date(this._firstDate.getFullYear(), this._firstDate.getMonth() + 1, 1));
    },

    _previousClickHandler: function ()
    {
        this._changeFirstDate(new Date(this._firstDate.getFullYear(), this._firstDate.getMonth() - 1, 1));
    },

    _changeFirstDate: function (date)
    {
        this._firstDate = date;
        this._setMonthIndices();
        this._initializeDayCells();
        this._updateMonthHeaders();
        this._updateDayCells();
        this._setPreviousButtonVisibility();
    },

    _setPreviousButtonVisibility: function ()
    {
        var today = new Date().getDateOnly();

        if (this._firstDate.getFullYear() == today.getFullYear() && this._firstDate.getMonth() == today.getMonth())
        {
            this._previousButton.style.visibility = "hidden";
        }
        else
        {
            this._previousButton.style.visibility = "";
        }
    },

    get_cellProperties: function ()
    {
        return this._cellProperties;
    },
    set_cellProperties: function (value)
    {
        if (typeof (value) == 'string') value = eval('[' + value + ']')[0];
        this._cellProperties = value;
        if (this._initialized)
        {
            this._changeFirstDate(this._firstDate);
        }
    },

    get_firstDate: function ()
    {
        return this._firstDate;
    },
    set_firstDate: function (value)
    {
        if (typeof (value) == 'string') value = Date.parseLocale(value, 'd');
        this._firstDate = value;
    },

    get_firstMonthContainer: function ()
    {
        return this._firstMonthContainer;
    },
    set_firstMonthContainer: function (value)
    {
        this._firstMonthContainer = value;
    },

    get_secondMonthContainer: function ()
    {
        return this._secondMonthContainer;
    },
    set_secondMonthContainer: function (value)
    {
        this._secondMonthContainer = value;
    },

    get_nextButton: function ()
    {
        return this._nextButton;
    },
    set_nextButton: function (value)
    {
        this._nextButton = value;
    },

    get_previousButton: function ()
    {
        return this._previousButton;
    },
    set_previousButton: function (value)
    {
        this._previousButton = value;
    },

    get_earliestAllowedCheckIn: function ()
    {
        return this._earliestAllowedCheckIn;
    },
    set_earliestAllowedCheckIn: function (value)
    {
        this._earliestAllowedCheckIn = value;
    },

    dispose: function ()
    {
        VacationRoost.Web.Common.CalendarBase.callBaseMethod(this, 'dispose');
    }

};

VacationRoost.Web.Common.CalendarBase.registerClass("VacationRoost.Web.Common.CalendarBase", Sys.UI.Control);
