/*  Copyright 2008 Eduardo F. Lutz
    edlutz@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    There is a file called COPYING with the GNU General Public License
    in the same place where you found this program.
 */

function LutzCalendar() {
    
    var ymc = 158210;
    var mtab = new Array(4,0,0,3,5,1,3,6,2,4,0,2);
    var ndtab = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
    var dow = new Array( "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab" );
    var monthNames = new Array("Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez");
    
    function isLeapYear( y ) {
        var res;
        if ((res = y % 100)) {
            return ((res % 4)==0);
        }
        if (y<=1582) {
            return true;
        }
        return (((y/100) % 4)==0);
    }
    
    
    function leapYear( y, m ) {
        return ((m<3) && isLeapYear(y)) ? 1 : 0;
    }
    
    
    function cB( ym, y) {
        var res = null;
        var y100 = Math.floor(y / 100);
        if (ym>ymc) {
            res = Math.floor(((10-2*(y100 % 4)) % 7));
        }
        else {
            res = Math.floor(((15-y100) % 7));
        }
        return res;
    }
    
    
    function cD( bixt, m) {
        var res;
        if (bixt) res = 3*m;
        else res = mtab[m-1];
        return res;
    }
    
    
    
    function cE( y ) {
        var r = ((Math.floor((y % 100) / 4) * 5) + (y % 4)) % 7;
        return r;
    }
    
    
    // Computes the day of the week for the first day of the month.
    function getFirstDOW(year, month) {
        var ym = year*100 + month;
        var bixt = leapYear( year, month );
        return Math.floor((cB(ym,year)+cD(bixt,month)+cE(year)) % 7);
    }
    
    
    
    
    ////////////////////////////////////////////////////////////////////////////////
    // Functions for the widget
    
    
    var thisCalendar = this;
    LutzCalendar.prototype.cells = new Array();
    
    function createEmptyRow (startIndex) {
        var row = document.createElement("tr");
        for (var j=0; j<7; j++) {
            var td = document.createElement("td");
            td.className = "calendarBodyCell";
            var d = document.createElement("div");
            thisCalendar.cells[startIndex+j] = d;
            d.innerHTML = "&nbsp;";
            td.appendChild(d);
            row.appendChild(td);
        }
        return row;
    }
    
    
    function createEmptyTBody () {
        var tbody = document.createElement("tbody");
        var index = 0;
        for (var i=0; i<6; i++) {
            var row = createEmptyRow(index);
            index += 7;
            tbody.appendChild(row);
        }
        return tbody;
    }
    
    
    function createEmptyCalendar () {
        var table = document.createElement("table");
        table.className = "calendarTable";
        var header = document.createElement("thead");
        header.className = "calendarTHead";
        table.appendChild(header);
        var row = document.createElement("tr");
        header.appendChild(row);
        for (var j=0; j<dow.length; j++) {
            var cell = document.createElement("td");
            //cell.style.class = "calendarHeaderCell";
            var text = document.createTextNode(dow[j]);
            cell.appendChild(text);
            row.appendChild(cell);
        }
        var tbody = createEmptyTBody();
        table.appendChild(tbody);
        tbody.className = "calendarTBody";
        return table;
    }
    
    function clearRange(first, last) {
        for (var j=first; j<=last; j++) {
            thisCalendar.cells[j].innerHTML = "&nbsp;";
        }
    }
    
    function updateSpecialCalendar() {
        thisCalendar.cells[0].innerHTML = "&nbsp;";
        var day = 1;
        var j;
        for (j=1; day<32; j++) {
            thisCalendar.cells[j].innerHTML = day++;
            if (day==5) {
                day = 15;
            }
        }
        clearRange(j, 41);
        alert("O calendario muda de Juliano para Gregoriano neste mes.");
    }
    
    function updateCalendar (year, month) {
        var ym = year*100+month;
        if (ym==ymc) {
            updateSpecialCalendar();
            return;
        }
        var start = getFirstDOW(year, month);
        var daysInMonth = ndtab[month-1];
        if (month==2 && isLeapYear(year)) {
            daysInMonth++;
        }
        if (start>0) {
            clearRange(0, start-1);
        }
        var day = 1;
        for (var j=start; day<=daysInMonth; j++) {
            thisCalendar.cells[j].innerHTML = day++;
        }
        clearRange(start+daysInMonth, 41);
    }
    
    function getYearId(prefix) {
        return prefix+"TxYear";
    }
    
    function getMonthId(prefix) {
        return prefix+"CbMonth";
    }
    
    
    function onChange () {
        var year = thisCalendar.yearObj.value*1;
        var month = thisCalendar.monthObj.selectedIndex+1;
        updateCalendar(year, month);
    }
    
    function onPreviousYearClick () {
        var txYear = thisCalendar.yearObj;
        txYear.value = txYear.value*1-1;
        onChange();
    }
    
    
    function onNextYearClick () {
        var txYear = thisCalendar.yearObj;
        txYear.value = txYear.value*1+1;
        onChange();
    }
    
    function onPreviousMonthClick () {
        var index = thisCalendar.monthObj.selectedIndex-1;
        if (index<0) {
            var year = thisCalendar.yearObj.value*1-1;
            thisCalendar.yearObj.value = year;
            index = 11;
        }
        thisCalendar.monthObj.selectedIndex = index;
        onChange();
    }
    
    function onNextMonthClick () {
        var index = thisCalendar.monthObj.selectedIndex+1;
        if (index>11) {
            var year = thisCalendar.yearObj.value*1+1;
            thisCalendar.yearObj.value = year;
            index = 0;
        }
        thisCalendar.monthObj.selectedIndex = index;
        onChange();
    }
    
    
    function createMonthButtons(parent) {
        var btPrev = document.createElement("input");
        btPrev.type = "button";
        btPrev.value = "<";
        btPrev.onclick = function () {
            onPreviousMonthClick();
        };
        parent.appendChild(btPrev);
        var btNext = document.createElement("input");
        btNext.type = "button";
        btNext.value = ">";
        btNext.onclick = function () {
            onNextMonthClick();
        };
        parent.appendChild(btNext);
    }
    
    function createMonthComboBox (month) {
        var container = document.createElement("span");
        var cbMonth = document.createElement("select");
        container.appendChild(cbMonth);
        var id = getMonthId(thisCalendar.prefix);
        cbMonth.id = id;
        cbMonth.name = id;
        for (var j=0; j<12; j++) {
            var opt = document.createElement("option");
            var name = monthNames[j];
            opt.value = name;
            opt.innerHTML = name;
            cbMonth.appendChild(opt);
        }
        cbMonth.selectedIndex = month-1;
        cbMonth.onchange = function () {
            onChange();
        };
        thisCalendar.monthObj = cbMonth;
        createMonthButtons(container);
        return container;
    }
    

    function createYearDiv (year) {
        var id = getYearId(thisCalendar.prefix);
        var d = document.createElement("div");
        var btPreviousYear = document.createElement("input");
        btPreviousYear.type = "button";
        btPreviousYear.value = "<";
        btPreviousYear.onclick = function () {
            onPreviousYearClick();
        };
        d.appendChild(btPreviousYear);
        var btNextYear = document.createElement("input");
        btNextYear.type = "button";
        btNextYear.value = ">";
        btNextYear.onclick = function () {
            onNextYearClick();
        };
        d.appendChild(btNextYear);
        var txYear = document.createElement("input");
        txYear.type = "text";
        txYear.id = id;
        txYear.size = 5;
        txYear.value = year;
        d.appendChild(txYear);
        thisCalendar.yearObj = txYear;
        txYear.onchange = function () {
            onChange();
        };
        return d;
    }
    
    LutzCalendar.prototype.setDate = function (year, month) {
        thisCalendar.yearObj.value = year;
        thisCalendar.monthObj.selectedIndex = month-1;
        onChange();
    };
    
    LutzCalendar.prototype.createWidget = function (parent, id, year, month) {
        thisCalendar.prefix = id;
        var container = document.createElement("div");
        container.id = id;
        var table = document.createElement("table");
        container.appendChild(table);
        table.className = "calendarTable";
        var body = document.createElement("tbody");
        table.appendChild(body);
        var row = document.createElement("tr");
        body.appendChild(row);
        var data = document.createElement("td");
        row.appendChild(data);
        var cbMonth = createMonthComboBox(month);
        var divYear = createYearDiv(year);
        divYear.appendChild(cbMonth);
        data.appendChild(divYear);
        row = document.createElement("tr");
        body.appendChild(row);
        data = document.createElement("td");
        row.appendChild(data);
        var calendar = createEmptyCalendar();
        data.appendChild(calendar);
        parent.appendChild(container);
        updateCalendar(year, month);
    };
    
}


