var MONTH_LIST = new Array("janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre");
var DAY_LIST = new Array("Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim");

/**
 * Activation du changement d'affichage des jours passés et du jour d'aujourd'hui.
 */ 
var PAST_ENABLED = true;
var TODAY_ENABLED = true;

/**
 * Instance du calendrier (unique puisqu'un seul affiché à la fois).
 */
var calendar = new Calendar();

/**
 * Constructeur.
 */
function Calendar() {
    this.elementId = "";
    this.element = null;

    this.weekday = 0;
    this.day = 0;
    this.month = 0;
    this.year = 0;

    this.cday = 0;
    this.cmonth = 0;
    this.cyear = 0;
    this.cyear2 = 0;

    this.mappingArray = new Array();

    this.cal = document.getElementById("cal");
    this.cald = document.getElementById("cald");
    this.calm = document.getElementById("calm");
    this.caly = document.getElementById("caly");
}

/**
 * Insère, dans le div d'id 'calendar', les éléments DOM du calendrier.
 */
function insertCalendar() {
    var calendarDiv = document.getElementById("calendar");
    var calendarInserted = (calendarDiv != null);
    if (calendarInserted) {
        // Le calendrier est inséré dans le div d'id "calendar".
        if (document.getElementById("cal") == null) {
            addMainDiv(calendarDiv);
            addMonthDiv(calendarDiv);
            addYearDiv(calendarDiv);
        }
    }
    return calendarInserted;
}

/**
 * Insère, dans le div d'id 'calendar', les éléments DOM relatifs à la partie principale du
 * calendrier.
 */ 
function addMainDiv(calendarDiv) {
    var calDiv = document.createElement("DIV");
    calDiv.id = "cal";
    calDiv.className = "ctx";
    
    var table = document.createElement("TABLE");
    table.id = "calh";
    table.border = "1";
    table.vAlign = "center";
    table.width = "300";
    table.className = "calh";
    
    var row = table.insertRow(0);
    
    var cell = row.insertCell(0);
    cell.id = "cal_m_00";
    cell.onclick = decrementMonth;
    cell.appendChild(getImg("/images/arrow_left.gif"));
    
    cell = row.insertCell(1);
    cell.id = "cal_m_01";
    cell.onclick = incrementMonth;
    cell.appendChild(getImg("/images/arrow_right.gif"));
    
    cell = row.insertCell(2);
    cell.id = "cal_m_02";
    cell.onclick = updateMonthChoiceVisibility;
    cell.width = "140";
    
    cell = row.insertCell(3);
    cell.id = "cal_m_03";
    cell.onclick = updateMonthChoiceVisibility;
    cell.appendChild(getImg("/images/arrow_down.gif"));
    
    cell = row.insertCell(4);
    cell.width = "10";
    
    cell = row.insertCell(5);
    cell.id = "cal_y_00";
    cell.onclick = decrementYear;
    cell.appendChild(getImg("/images/arrow_left.gif"));
    
    cell = row.insertCell(6);
    cell.id = "cal_y_01";
    cell.onclick = incrementYear;
    cell.appendChild(getImg("/images/arrow_right.gif"));
    
    cell = row.insertCell(7);
    cell.id = "cal_y_02";
    cell.onclick = updateYearChoiceVisibility;
    cell.width = "60";
    
    cell = row.insertCell(8);
    cell.id = "cal_y_03";
    cell.onclick = updateYearChoiceVisibility;
    cell.appendChild(getImg("/images/arrow_down.gif"));
    
    cell = row.insertCell(9);
    cell.width = "10";
    
    cell = row.insertCell(10);
    cell.id = "cal_c";
    cell.onclick = hideCalendar;
    var img = getImg("/images/l_cancel.gif");
    img.width = "15";
    img.height = "13";
    cell.appendChild(img);
    
    row = table.insertRow(1);
    
    cell = row.insertCell(0);
    cell.colSpan = 11;
    
    var subTable = document.createElement("TABLE");
    subTable.width = "300";
    subTable.border = "1";
    subTable.className = "cal";
    subTable.id = "cald";
    
    var subRow = subTable.insertRow(0);
    subRow.align = "center";
    subRow.height = "18";
    
    var subCell;
    var i;
    for (i = 0; i < 7; i++) {
        subCell = subRow.insertCell(i);
        subCell.width = (i < 5 ? "46" : "35");
        subCell.innerHTML = DAY_LIST[i];
    }
    
    var j;
    for (i = 0; i < 6; i++) {
        subRow = subTable.insertRow(i + 1);
        subRow.align = "center";
        subRow.style.height = "18";
        for (j = 0; j < 7; j++) {
            subCell = subRow.insertCell(j);
            subCell.id = "cal_d_" + i + j;
        }
    }
    
    cell.appendChild(subTable);
    calDiv.appendChild(table);
    calendarDiv.appendChild(calDiv);
}

/**
 * Insère, dans le div d'id 'calendar', les éléments DOM relatifs au choix du mois du calendrier.
 */
function addMonthDiv(calendarDiv) {
    var calmDiv = document.createElement("DIV");
    calmDiv.id = "calm";
    calmDiv.className = "ctx";
    
    var table = document.createElement("TABLE");
    table.className = "calm";
    table.border = "1";
    table.width = "300";
    var row;
    var cell;
    for (i = 0; i < 3; i++) {
        row = table.insertRow(i);
        row.style.height = "18";
        for (j = 0; j < 4; j++) {
            cell = row.insertCell(j);
            cell.id = "calm_" + (3 * j + i + 1);
            cell.width = (j < 2 ? "23%" : "26%");
        }
    }
    calmDiv.appendChild(table);
    calendarDiv.appendChild(calmDiv);
}

/**
 * Insère, dans le div d'id 'calendar', les éléments DOM relatifs au choix de l'année du
 * calendrier.
 */
function addYearDiv(calendarDiv) {
    var calyDiv = document.createElement("DIV");
    calyDiv.id = "caly";
    calyDiv.className = "ctx";
    
    var table = document.createElement("TABLE");
    var row = table.insertRow(0);
    
    var cell = row.insertCell(0);
    var img = getImg("graphics/arrow_left.gif");
    img.onclick = decreaseYear;
    cell.appendChild(img);
    
    cell = row.insertCell(1);
    var subTable = document.createElement("TABLE");
    subTable.className = "caly";
    subTable.border = "1";
    subTable.width = "240";
    var subRow;
    var subCell;
    for (i = 0; i < 5; i++) {
        subRow = subTable.insertRow(i);
        subRow.style.height = "18";
        for (j = 0; j < 5; j++) {
            subCell = subRow.insertCell(j);
            subCell.id = "caly_" + (5 * j + i + 1);
            subCell.width = "20%";
        }
    }
    cell.appendChild(subTable);
    
    cell = row.insertCell(2);
    img = getImg("graphics/arrow_right.gif");
    img.onclick = increaseYear;
    cell.appendChild(img);
    
    calyDiv.appendChild(table);
    calendarDiv.appendChild(calyDiv);
}

/**
 * Retourne un élément image à insérer dans le calendrier.
 */
function getImg(src) {
    var img = document.createElement("IMG");
    img.src = src;
    img.className = "but";
    img.width = "16";
    img.height = "16";
    return img;
}

function initCalendar(date) {
    calendar.weekday = date.getDay();
    calendar.day = date.getDate();
    calendar.month = date.getMonth() + 1;
    calendar.year = date.getFullYear();

    calendar.cmonth = calendar.month;
    calendar.cyear = calendar.year;

    fillMonthChoice();
    fillYearChoice();
}

function initElement(id, evt) {
    if (!evt) {
        evt = window.event;
    }
    calendar.elementId = "";
    calendar.element = document.getElementById(id);

    var hGap = -92;
    var vGap = 12;
    var elementStyle = calendar.cal.style;
    var clientX = evt.clientX;
    var clientY = evt.clientY;
    var rightedge = document.body.clientWidth - clientX - hGap;
    var bottomedge = document.body.clientHeight - clientY - vGap;
    if (rightedge < calendar.cal.offsetWidth) {
        elementStyle.left = document.body.scrollLeft + clientX - hGap - calendar.cal.offsetWidth;
    } else {
        elementStyle.left = document.body.scrollLeft + clientX + hGap;
    }
    if (bottomedge < calendar.cal.offsetHeight) {
        elementStyle.top = document.body.scrollTop + clientY - vGap - calendar.cal.offsetHeight;
    } else {
        elementStyle.top = document.body.scrollTop + clientY + vGap;
    }

    calendar.calm.style.left = parseInt(elementStyle.left) + 5;
    calendar.calm.style.top = parseInt(elementStyle.top) + 28;
    calendar.caly.style.left = parseInt(elementStyle.left) + 12;
    calendar.caly.style.top = parseInt(elementStyle.top) + 33;
}

function displayCalendar(id, ev) {
    if (insertCalendar()) {
        calendar = new Calendar();
    
        var i;
        var element;
        for (i = 0; i < 4; i++) {
            element = document.getElementById("cal_m_0" + i);
            element.onmouseover = highlightHead;
            element.onmouseout = unhighlightHead;
        }
        for (i = 0; i < 4; i++) {
            element = document.getElementById("cal_y_0" + i);
            element.onmouseover = highlightHead;
            element.onmouseout = unhighlightHead;
        }
        element = document.getElementById("cal_c");
        element.onmouseover = highlightHead;
        element.onmouseout = unhighlightHead;
        
        initElement(id, ev);
        var dateValue = calendar.element.value;
        var validDate = false;
        if (dateValue != "") {
            var s = dateValue.split("/");
            var d;
            var m;
            var y;
            if (s.length == 3) {
                d = s[0];
                m = s[1];
                y = s[2];
                if (!isNaN(d) && !isNaN(m) && !isNaN(y)) {
                    var m2 = parseNumber(m);
                    if (m2 >= 1 && m2 <= 12) {
                        validDate = true;
                        var y2 = parseNumber(y);
                        if (y2 < 100) {
                            y2 += 2000;
                        }
                        var d2 = parseNumber(d);
                        var testDate = new Date(y2, m2 - 1, 1);
                        if (d2 >= 1 && d2 <= getMaxMonthLastDay(testDate)) {
                            initCalendar(new Date(y2, m2 - 1, d2));
                        } else {
                            initCalendar(new Date(y2, m2 - 1, 1));
                        }
                    }
                }
            }
        }
        if (!validDate) {
            initCalendar(new Date());
        }
        fillCalendar();
        showCalendar();
    } else {
        window.status = "Div 'calendar' inexistant : aucun calendrier ajouté.";
    }
}

function showCalendar() {
    calendar.cal.style.visibility = "visible";
    showDayChoice();
    hideMonthChoice();
    hideYearChoice();
}

function hideCalendar() {
    calendar.cal.style.visibility = "hidden";
    hideDayChoice();
    hideMonthChoice();
    hideYearChoice();
}

function showDayChoice() {
    calendar.cald.style.visibility = "visible";
}

function hideDayChoice() {
    calendar.cald.style.visibility = "hidden";
}

function showMonthChoice() {
    calendar.calm.style.visibility = "visible";
}

function hideMonthChoice() {
    calendar.calm.style.visibility = "hidden";
}

function showYearChoice() {
    calendar.caly.style.visibility = "visible";
}

function hideYearChoice() {
    calendar.caly.style.visibility = "hidden";
}

function updateMonthChoiceVisibility() {
    if (calendar.calm.style.visibility == "visible") {
        showDayChoice();
        hideMonthChoice();
    } else {
        hideDayChoice();
        hideYearChoice();
        showMonthChoice();
    }
}

function updateYearChoiceVisibility() {
    if (calendar.caly.style.visibility == "visible") {
        showDayChoice();
        hideYearChoice();
    } else {
        calendar.cyear2 = calendar.cyear;
        hideDayChoice();
        hideMonthChoice();
        fillYearChoice();
        showYearChoice();
    }
}

function fillCalendar() {
    document.getElementById("cal_m_02").innerHTML = getStringMonth(calendar.cmonth);
    document.getElementById("cal_y_02").innerHTML = calendar.cyear;
    var element;

    var i = 0;
    var j = 0;
    for (i = 0; i < 6; i++) {
        for (j = 0; j < 7; j++) {
            element = document.getElementById("cal_d_" + i + j);
            element.innerHTML = "";
            element.onclick = "";
            element.onmouseover = "";
            element.onmouseout = "";
            element.className = "";
        }
    }

    i = 0;
    j = (new Date(calendar.cyear, calendar.cmonth-1, 1)).getDay();
    j = (j + 6) % 7;
    var count = 1;
    var days = getMonthLastDay();
    while (count <= days) {
        element = document.getElementById("cal_d_" + i + j);
        element.innerHTML = count;
        element.onclick = selectDay;
        element.onmouseover = highlightDay;
        element.onmouseout = unhighlightDay;
        element.className = getCellClassNameSuffix(count);
        
        calendar.mappingArray[10 * i + j] = count;
        j++;
        if (j == 7) {
            i++;
            j = 0;
        }
        count++;
    }
}

function fillMonthChoice() {
    var i;
    var element;
    for (i = 1; i <= 12; i++) {
        element = document.getElementById("calm_" + i);
        element.innerHTML = getStringMonth(i);
        element.onclick = selectMonth;
        element.onmouseover = highlightHead;
        element.onmouseout = unhighlightHead;
    }
}

function fillYearChoice() {
    var i;
    var element;
    var gap = calendar.cyear2 - 11;
    for (i = 1; i <= 25; i++) {
        element = document.getElementById("caly_" + i);
        element.innerHTML = gap + i;
        element.onclick = selectYear;
        element.onmouseover = highlightHead;
        element.onmouseout = unhighlightHead;
    }
}

function highlightDay(evt) {
    var element = getEventElement(evt);
    element.className = "sel" + getCellClassNameSuffix(element.innerHTML);
}

function unhighlightDay(evt) {
    //getEventElement(evt).className = "";
    var element = getEventElement(evt);
    element.className = getCellClassNameSuffix(element.innerHTML);
}

function highlightHead(evt) {
    var element = getEventElement(evt);
    if (element.tagName == "IMG") {
        element = element.parentNode;
    }
    element.className = "sel";
    if (element.id == "cal_m_02") {
        document.getElementById("cal_m_03").className = "sel";
    } else if (element.id == "cal_m_03") {
        document.getElementById("cal_m_02").className = "sel";
    } else if (element.id == "cal_y_02") {
        document.getElementById("cal_y_03").className = "sel";
    } else if (element.id == "cal_y_03") {
        document.getElementById("cal_y_02").className = "sel";
    }
}

function unhighlightHead(evt) {
    var element = getEventElement(evt);
    if (element.tagName == "IMG") {
        element = element.parentNode;
    }
    element.className = "";
    if (element.id == "cal_m_02") {
        document.getElementById("cal_m_03").className = "";
    } else if (element.id == "cal_m_03") {
        document.getElementById("cal_m_02").className = "";
    } else if (element.id == "cal_y_02") {
        document.getElementById("cal_y_03").className = "";
    } else if (element.id == "cal_y_03") {
        document.getElementById("cal_y_02").className = "";
    } 
}

function selectDay(evt) {
    var id = getEventElement(evt).id;
    calendar.cday = calendar.mappingArray[parseInt(id.substr(id.length - 2))];
    hideCalendar();
    var d = calendar.cday;
    var m = calendar.cmonth;
    var y = calendar.cyear;
    window.status = d + " - " + m + " - " + y;
    calendar.element.value = (d < 10 ? "0" : "") + d + "/" + (m < 10 ? "0" : "") + m + "/" + y;
}

function selectMonth(evt) {
    var id = getEventElement(evt).id;
    var s = id.split("_");
    calendar.cmonth = parseInt(s[s.length - 1]);
    hideMonthChoice();
    showDayChoice();
    fillCalendar();
}

function selectYear(evt) {
    var id = getEventElement(evt).id;
    var s = id.split("_");
    calendar.cyear = parseInt(s[s.length - 1]) + calendar.cyear2 - 11;
    hideYearChoice();
    showDayChoice();
    fillCalendar();
}

function incrementMonth() {
    if (calendar.cmonth == 12) {
        calendar.cmonth = 1;
        calendar.cyear = calendar.cyear + 1;
    } else {
        calendar.cmonth = calendar.cmonth + 1;
    }
    fillCalendar();
}

function decrementMonth() {
    if (calendar.cmonth == 1) {
        calendar.cmonth = 12;
        calendar.cyear = calendar.cyear - 1;
    } else {
        calendar.cmonth = calendar.cmonth - 1;
    }
    fillCalendar();
}

function incrementYear() {
    calendar.cyear = calendar.cyear + 1;
    fillCalendar();
}

function decrementYear() {
    calendar.cyear = calendar.cyear - 1;
    fillCalendar();
}

function increaseYear() {
    calendar.cyear2 = calendar.cyear2 + 20;
    fillYearChoice();
}

function decreaseYear() {
    calendar.cyear2 = calendar.cyear2 - 20;
    fillYearChoice();
}

function getMonthLastDay() {
    var testDate = new Date(calendar.cyear, calendar.cmonth - 1, 29);
    return getMaxMonthLastDay(testDate);
}

function getMaxMonthLastDay(date) {
    if (date.getDate() == 29) {
        date.setDate(30);
        if (date.getDate() == 30) {
            date.setDate(31);
            if (date.getDate() == 31) {
                return 31
            } else {
                return 30;
            }
        } else {
            return 29;
        }
    } else {
        return 28;
    }
}

function getStringMonth(index) {
    return MONTH_LIST[index - 1];
}

var checkClickEnabled = true;
var clickedElement = null;

function checkClick(evt) {
    if ((checkClickEnabled)
            && (calendar.cal != null)
            && (calendar.cal.style.visibility == "visible")) {
        checkClickEnabled = false;
        if (evt.target != null) {
            clickedElement = evt.target;
        } else {
            clickedElement = window.event.srcElement;
        }
        setTimeout("checkClickAnalysis()", 200);
    }
}

function checkClickAnalysis() {
    var element = clickedElement;
    var calendarElement = false;
    var id;
    var tagName = element.tagName;
    // Vérification que le clic courant n'est pas relatif à une image dont le rôle est justement
    // d'afficher le calendrier.
    if (tagName == "IMG") {
        var imgOnClickFunction = "" + element.onclick;
        calendarElement = (imgOnClickFunction.indexOf("displayCalendar") != -1);
    }
    // Vérification de l'appartenance ou non de l'élément ayant déclenché l'événement 'onclick' au
    // calendrier.
    if (!calendarElement) {
        while (element != null && tagName != "FORM") {
            id = element.id;
            if (id != null && (id == "cal" || id == "calm" || id == "caly") && tagName == "DIV") {
                // L'élément ayant déclenché l'événement 'onclick' appartient au calendrier : on ne
                // doit donc pas masquer ce dernier.
                calendarElement = true;
            }
            element = element.parentNode;
            if (element != null) {
                tagName = element.tagName;
            }
        }
        if (!calendarElement) {
            hideCalendar();
        }
    }
    checkClickEnabled = true;
}

function getEventElement(evt) {
    if (!evt) {
        return window.event.srcElement;
    } else {
        return evt.target;
    }
}

function parseNumber(n) {
    while (n != "" && n.substring(0, 1) == "0") {
        n = n.substring(1);
    }
    return parseInt(n);
}

function getCellClassNameSuffix(day) {
    if (PAST_ENABLED || TODAY_ENABLED) {
        var today = new Date();
        var selectedDate = new Date(calendar.cyear, calendar.cmonth - 1, day);
        if (selectedDate.getYear() < today.getYear()) {
            return (PAST_ENABLED ? "pas" : "");
        } else if (selectedDate.getYear() > today.getYear()) {
            return "";
        } else {
            if (selectedDate.getMonth() < today.getMonth()) {
                return (PAST_ENABLED ? "pas" : "");
            } else if (selectedDate.getMonth() < today.getMonth()) {
                return "";
            } else {
                if (selectedDate.getDate() < today.getDate()) {
                    return (PAST_ENABLED ? "pas" : "");
                } else if (selectedDate.getDate() > today.getDate()) {
                    return "";
                } else {
                    return (TODAY_ENABLED ? "tod" : "");
                }
            }
        }
    } else {
        return "";
    }
}
