﻿(function () {
    var validateDiscrecity = function (discrecity) {
        if (discrecity == "D") return true;
        else if (discrecity == "W") return true;
        else if (discrecity == "M") return true;
        else if (discrecity == "Q") return true;
        else if (discrecity == "Y") return true;
        else if (discrecity == "S") return true;
        else throw "unsupported discrecity " + discrecity;
    };

    var getDisplayFormat = function (discrecity, role) {
        if (discrecity == "D") {
            return "dd.MM.yyyy";
        } else if (discrecity == "W") {
            return "dd.MM.yyyy";
        } else if (discrecity == "M") {
            return "MMMM yyyy";
        } else if (discrecity == "Q") {
            return "Q.yyyy";
        } else if (discrecity == "Y") {
            return "yyyy";
        } else if (discrecity == "S") {
            return "dd.MM.yyyy";
        } else {
            throw "unsupported discrecity " + discrecity;
        }
    };

    var getEditFormat = function (discrecity, role) {
        if (discrecity == "D") {
            return "dd.MM.yyyy";
        } else if (discrecity == "W") {
            return "dd.MM.yyyy";
        } else if (discrecity == "M") {
            return "MM.yyyy";
        } else if (discrecity == "Q") {
            return "Q.yyyy";
        } else if (discrecity == "Y") {
            return "yyyy";
        } else if (discrecity == "S") {
            return "dd.MM.yyyy";
        } else {
            throw "unsupported discrecity " + discrecity;
        }
    };

    var formatDate = function (date, format, defaultFormatDate) {
        if (format) {
            var quarter = date && !isNaN(date) ? Math.floor(date.getMonth() / 3 + 1) : "";
            format = format.replace(/Q/g, quarter.toString());
        }

        return defaultFormatDate(date, format);
    }

    // http://www.telerik.com/community/forums/aspnet-ajax/calendar/improved-month-year-picker.aspx
    var setDiscrecity = function (picker, discrecity, role) {
        validateDiscrecity(discrecity);

        var dateinput = picker.get_dateInput();
        var formatter = dateinput.get_dateFormatInfo();
        var textbox = picker.get_textBox();
        var button = picker.get_popupButton();
        var calendar = picker.get_calendar();
        var fastnav = calendar._getFastNavigation();

        // HACK INCOMING!!
        // before doing anything, disable onchanged events
        // this is done to ensure that filter change event will be raised only once (by cbDiscrecity)
        // that's a hack, of course, but I don't have time to come up with cleaner solution
        $.data(picker._element, "disableevents", true);

        // first of all, get currently selected date => it might easily get messed up by subsequent manipulations
        var firstTime = !$.data(picker._element, "notfirsttime");
        $.data(picker._element, "notfirsttime", true);
        var hidden = dateinput._hiddenElement;
        // hack to make SelectedDate property work for Firefox
        if (firstTime && !hidden.value && hidden.defaultValue) hidden.value = hidden.defaultValue;
        var date = picker.get_selectedDate();

        // calculate the mindate => we need to adjust it right now, since trimmed date might not fit it
        var mindate = util.trimDate($.data(picker._element, "mindate"), discrecity, role);
        mindate = new Date(mindate.valueOf() - 1);
        picker.set_minDate(mindate);

        // calculate the maxdate => we need to adjust it right now, since trimmed date might not fit it
        var maxdate = util.trimDate($.data(picker._element, "maxdate"), discrecity, role);
        maxdate = new Date(maxdate.valueOf() + 1);
        picker.set_maxDate(maxdate);

        // prepare custom parsers and formatters
        formatter.DefaultFormatDate = formatter.DefaultFormatDate || formatter.FormatDate;
        formatter.FormatDate = function (date, format) { return formatDate(date, format, function (date, format) { return formatter.DefaultFormatDate(date, format); }); };
        dateinput.set_dateFormat(getEditFormat(discrecity, role));
        dateinput.set_displayDateFormat(getDisplayFormat(discrecity, role));
        dateinput.parseDate = function (s) { var date = util.parseDate(s, discrecity, role); return date; };

        // transform the date according to updated discrecity and/or role
        date = util.trimDate(date, discrecity, role);
        if (date && !isNaN(date) && date < mindate) date = new Date(mindate.valueOf() + 1);
        if (date && !isNaN(date) && date > maxdate) date = new Date(maxdate.valueOf() - 1);
        picker.set_selectedDate(date);

        // finalize the changes
        picker._discrecity = discrecity;
        picker._role = role;
        $.data(picker._element, "disableevents", false);

        // after the stuff above is done, everything is straightforward
        // we just have to override standard event handlers for certain datepicker controls

        if (discrecity == "Q" || discrecity == "Y") $(button).hide(); else $(button).show();
        button.href = "javascript:void(0);";
        $clearHandlers(button);
        $addHandler(button, "click", function (e) {
            if (discrecity == "D") {
                picker.togglePopup();
            } else if (discrecity == "W") {
                picker.togglePopup();
            } else if (discrecity == "M") {
                //synchronize the input date if set with the picker one 
                var date = picker.get_selectedDate();
                if (date) {
                    date = util.trimDate(date, discrecity, role);
                    calendar.get_focusedDate()[0] = date.getFullYear();
                    calendar.get_focusedDate()[1] = date.getMonth() + 1;
                    calendar.get_focusedDate()[2] = date.getDate();
                }

                //adjust where to show the popup table
                var adjustElement = textbox;
                if (textbox.style.display == "none") adjustElement = picker.get_popupImage();
                var pos = picker.getElementPosition(adjustElement);
                var x = pos.x;
                var y = pos.y + adjustElement.offsetHeight;
                $get(calendar._titleID).onclick({ clientX: x, clientY: y - document.documentElement.scrollTop });
            } else if (discrecity == "Q") {
                /* do nothing */
            } else if (discrecity == "Y") {
                /* do nothing */
            } else if (discrecity == "S") {
                picker.togglePopup();
            } else {
                throw "unsupported discrecity " + discrecity;
            }

            e.stopPropagation();
            e.preventDefault();
            return false;
        });

        $addHandler(textbox, "change", function () {
            var discrecity = picker._discrecity;
            var role = picker._role;
            var date = util.parseDate(textbox.value, discrecity, role);
            if (date) { picker.set_selectedDate(date); }
        });

        Telerik.Web.UI.Calendar.MonthYearFastNavigation.prototype.OnOK = function () {
            var pickerId = this.DomElement.id;
            var length = pickerId.length - "_calendar_FastNavPopup".length;
            pickerId = pickerId.slice(0, length);
            var picker = $find(pickerId);
            var discrecity = picker._discrecity;
            var role = picker._role;

            var date = new Date(this.Year, this.Month, 1);
            date = util.trimDate(date, discrecity, role);
            picker.set_selectedDate(date);
            this.Popup.Hide(false);
        };

        Telerik.Web.UI.Calendar.MonthYearFastNavigation.prototype.OnToday = function () {
            var pickerId = this.DomElement.id;
            var length = pickerId.length - "_calendar_FastNavPopup".length;
            pickerId = pickerId.slice(0, length);
            var picker = $find(pickerId);
            var discrecity = picker._discrecity;
            var role = picker._role;

            var date = new Date();
            date = util.trimDate(date, discrecity, role);
            picker.set_selectedDate(date);
            this.Popup.Hide(false);
        };
    };

    window.set_discrecity = function (picker, value, role) {
        if (typeof picker == "string") picker = $find(picker);
        if (!picker || !picker._element) return;

        var mindate = $.data(picker._element, "mindate");
        if (!mindate) $.data(picker._element, "mindate", picker._minDate);

        var maxdate = $.data(picker._element, "maxdate");
        if (!maxdate) $.data(picker._element, "maxdate", picker._maxDate);

        setDiscrecity(picker, value, role);
    }
})();
