//<![CDATA[

var useArrowImages = true;
var addNewCatText = "Add new category...";

var lastStatus = "";
var isReordering = false;
var allTodoIDs = new Array();
var todoIDToNote = new Object();
var numCategories = 0;
var months = new Array(12);
var daysInAdvance = 28;
months[0]  = "January";
months[1]  = "February";
months[2]  = "March";
months[3]  = "April";
months[4]  = "May";
months[5]  = "June";
months[6]  = "July";
months[7]  = "August";
months[8]  = "September";
months[9]  = "October";
months[10] = "November";
months[11] = "December";
var days = new Array(7);
days[0] = "Sunday";
days[1] = "Monday";
days[2] = "Tuesday";
days[3] = "Wednesday";
days[4] = "Thursday";
days[5] = "Friday";
days[6] = "Saturday";

function toggleReorder() {
    var reorderButton = document.getElementById("reorderButton");
    if (isReordering) {
        isReordering = false;
        reorderButton.value = "Reorder TODOs";
    } else {
        isReordering = true;
        reorderButton.value = "Done reordering";
    }
    for (var catIndex = 0; catIndex < numCategories; catIndex++) {
        var upHeader = document.getElementById("upHeader" + catIndex);
        upHeader.style.display = getDisplayStyle(isReordering);
        var downHeader = document.getElementById("downHeader" + catIndex);
        downHeader.style.display = getDisplayStyle(isReordering);
    }
    for (var i = 0; i < allTodoIDs.length; i++) {
        curID = allTodoIDs[i];
        var upButton = document.getElementById("up" + curID);
        if (upButton) {
            upButton.style.display = getDisplayStyle(isReordering);
        }
        var downButton = document.getElementById("down" + curID);
        if (downButton) {
            downButton.style.display = getDisplayStyle(isReordering);
        }
    }
}

function setStatus(newStatus, nextRealStatus) {
    var status = document.getElementById("status");
    clearAll(status);
    if (nextRealStatus != "") {
        lastStatus = nextRealStatus;
    }
    status.appendChild(document.createTextNode(newStatus));
} 

function setStatusDone() {
    var status = document.getElementById("status");
    clearAll(status);
    var statusToUse;
    if (lastStatus != "") {
        statusToUse = "Done " + lastStatus + ".";
    } else {
        statusToUse = "Done"
    }
    status.appendChild(document.createTextNode(statusToUse));
}

function refreshTodosStub() {
    // This is a callback function.  If we try to launch another XMLHttpRequest
    // from here, it doesn''t work.  So, set a timeout and refresh 100 msecs
    // later.
    if (xmlhttp.readyState == 4) {
        setTimeout('refreshTodos(todoFileName, true, true, false)', 100);
    }
}

function refreshTodosStubAndClearText() {
    if (xmlhttp.readyState == 4) {
        setTimeout('refreshTodosAndClearText(todoFileName, true, true, false)', 100);
    }
}

function processTodoResponseAndRefreshCalendar() {
    if (xmlhttp.readyState == 4) {
        processTodoResponse();
        //alert('here');
        setTimeout('refreshCalendar()', 300);
    }
}

function refreshTodosAndClearText(xmlName, async, updateStatus, setLastStatus) {
    refreshTodos(xmlName, async, updateStatus, setLastStatus);
    var todoTitleInput = document.getElementById("newTodoTitle");
    todoTitleInput.value = "";
    var todoNextActionInput = document.getElementById("newTodoNextAction");
    todoNextActionInput.value = "";
}

function addTodo(title, nextAction, category) {
    //alert('got title: ' + title + ' and nextAction: ' + nextAction); 
    if (category == addNewCatText) {
        category = prompt('Enter new category name:', '');
    }
    var params = "title=" + encodeMyHtml(title) + "&nextAction=" + encodeMyHtml(nextAction) + "&category=" + encodeMyHtml(category);
    setStatus('Adding...', "adding");
    doRequest(todoAdderScriptName, true, refreshTodosStubAndClearText, "POST", params);
    return true;
}

function updateNote(todoID, note) {
    //alert('got update: text is: ' + note);
    var params = "todoID=" + todoID + "&note=" + encodeMyHtml(note);
    //alert('params is ' + params);
    setStatus("Updating note...", "updating note");
    // TODO - only if request goes through?
    closeNote(todoID);
    doRequest(todoUpdateNoteScriptName, true, refreshTodosStub, "POST", params);
    //return true;
}

function closeNote(todoID) {
    var noteSpan = document.getElementById("notespan" + todoID);
    if (noteSpan.childNodes.length == 1) {
        clearAll(noteSpan);
    }
}

function cancelNote(todoID) {
    var noteSpan = document.getElementById("notespan" + todoID);
    if (noteSpan.childNodes.length == 1) {
        // See if the note has changed and ask if they want to save.
        var noteTextArea = document.getElementById("notetext" + todoID);
        var noteTextAreaValue = noteTextArea.value;
        if (noteTextAreaValue != todoIDToNote[todoID] &&
            !(noteTextAreaValue == "" && todoIDToNote[todoID] === undefined)) {
            //alert('val is "' + noteTextAreaValue + '", tITN is "' + todoIDToNote[todoID] + '"');
            var noSave = confirm('This note has changed - are you sure you want to lose the contents?');
            if (!noSave) {
                return;
            }
        }
        clearAll(noteSpan);
    }
}
function viewNote(todoID) {
    var noteSpan = document.getElementById("notespan" + todoID);
    if (noteSpan.childNodes.length == 1) {
        cancelNote(todoID);
    } else {
        clearAll(noteSpan);
        var noteForm = document.createElement("form");
        noteForm.style.marginButton = "0px";
        var noteTextArea = document.createElement("textarea");
        noteTextArea.name = "notetext" + todoID;
        noteTextArea.id = "notetext" + todoID;
        noteTextArea.rows = "4";
        noteTextArea.cols = "40";
        noteTextArea.style.cssText = "float: left;";
        if (todoIDToNote[todoID]) {
            noteTextArea.value = todoIDToNote[todoID];
        }
        noteForm.style.cssText = "float: none;";
        var noteSave = document.createElement("input");
        noteSave.type = "submit";
        noteSave.name = "save" + todoID;
        noteSave.value = "Save";
        noteSave.style.cssText = "float: left; clear: left;";
        noteForm.appendChild(noteTextArea);
        noteForm.appendChild(noteSave);
        noteForm.action = "javascript:updateNote(" + todoID + ", document.getElementById('notetext" + todoID + "').value); void(0);";
        noteSpan.appendChild(noteForm);
    }
}

function reorder(id, isUp) {
    var params = "todoID=" + id + "&isUp=" + ((isUp) ? 1 : 0);
    setStatus('Reordering...', "reordering");
    doRequest(todoReordererScriptName, true, refreshTodosStub, "POST", params);
}

function updateTodo(todoID) {
    var nextAction = prompt('What is the next action? (leave blank if the task is done)', '');
    if (nextAction != null) {
        var params = "todoID=" + todoID + "&nextAction=" + encodeMyHtml(nextAction);
        if (nextAction == "") {
            setStatus('Removing...', "removing");
            doRequest(todoRemoverScriptName, true, refreshTodosStub, "POST", params);
        } else {
            setStatus('Updating...', "updating");
            doRequest(todoUpdaterScriptName, true, refreshTodosStub, "POST", params);
        }
    } else {
        setStatus('Update cancelled.', "");
    }
}

function changeCategory(todoID) {
}

function getTimeString(parentNode) {
    var hour = parentNode.getElementsByTagName("hour")[0].firstChild.nodeValue;
    var minute = parentNode.getElementsByTagName("minute")[0].firstChild.nodeValue;
    if (parseInt(minute) < 10) {
        minute = "0" + minute;
    }
    return hour + ":" + minute;
}

function clearCalendarTitles() {
    var calendardaysTBody = document.getElementById('calendardaysTBody');
    var curRow = calendardaysTBody.childNodes[0];
    while (curRow != null) {
        var curTD = curRow.childNodes[0];
        while (curTD != null) {
            curTD.title = "";
            curTD = curTD.nextSibling;
        }
        curRow = curRow.nextSibling;
    }
}

function processCalendarResponse() {
    if (xmlhttp.readyState == 4) {
        if (xmlhttp.status == 200) {
            var xmlDoc = xmlhttp.responseXML;
            var calendarTBody = document.getElementById('calendarTBody');
            clearAllAfterFirstElementType(calendarTBody, "tr");
            // TODO - why does this get called so many times in IE?
            clearCalendarTitles();
            var entries = xmlDoc.documentElement.getElementsByTagName("entry");
            //document.getElementById('calendarDiv').appendChild(document.createTextNode(xmlhttp.responseText));
            for (var i = 0; i < entries.length; i++) {
                var curEntry = entries[i];
                var entryRow = document.createElement("tr");
                var entryDate = document.createElement("td");
                var entryTime = document.createElement("td");
                var entryTitle = document.createElement("td");
                var entryCategory = document.createElement("td");
                var entryDateTag = curEntry.getElementsByTagName("curdate")[0];
                var entryCurDate = new Date(entryDateTag.getElementsByTagName("year")[0].firstChild.nodeValue, parseInt(entryDateTag.getElementsByTagName("month")[0].firstChild.nodeValue) - 1, entryDateTag.getElementsByTagName("day")[0].firstChild.nodeValue);
                dateText = days[entryCurDate.getDay()] + " " + months[entryCurDate.getMonth()] + " " + entryCurDate.getDate();
                entryDate.appendChild(document.createTextNode(dateText));
                entryRow.appendChild(entryDate);
                var entryStartTimeArray = curEntry.getElementsByTagName("starttime");
                if (entryStartTimeArray.length > 0) {
                    var timeText = " " + getTimeString(entryStartTimeArray[0]) + " - ";
                    var entryEndTime = curEntry.getElementsByTagName("endtime")[0];
                    timeText = timeText + getTimeString(entryEndTime);
                    entryTime.appendChild(document.createTextNode(timeText));
                } else {
                    entryTime.appendChild(document.createTextNode("none"));
                }
                entryRow.appendChild(entryTime);
                var title = curEntry.getElementsByTagName("title")[0].firstChild.nodeValue;
                entryTitle.appendChild(document.createTextNode(title));
                entryRow.appendChild(entryTitle);
                var categoryArray = curEntry.getElementsByTagName("category");
                if (categoryArray.length > 0) {
                    entryCategory.appendChild(document.createTextNode(categoryArray[0].firstChild.nodeValue));
                } else {
                    entryCategory.appendChild(document.createTextNode("none"));
                }
                entryRow.appendChild(entryCategory);
                calendarTBody.appendChild(entryRow);
                // Make the date bold on the calendar below
                idString = "calendar" + entryCurDate.getMonth() + '-' + entryCurDate.getDate();
                var calEntry = document.getElementById(idString);
                var size = calEntry.style.fontSize;
                if (size == '') {
                    size = "100%";
                }
                size = size.slice(0, -1);
                size = (parseInt(size) + 25) + "%"
                calEntry.style.fontSize = size;
                if (calEntry.title == '') {
                    calEntry.title = title;
                } else {
                    calEntry.title = calEntry.title + ' and ' + title;
                }
            }
        }
    }
}

function createTodoTableHeader(index) {
    var tableHeader = document.createElement('tr');
    var upHeader = document.createElement('th');
    upHeader.id = "upHeader" + index;
    upHeader.style.display = getDisplayStyle(isReordering);
    tableHeader.appendChild(upHeader);
    var downHeader = document.createElement('th');
    downHeader.id = "downHeader" + index;
    downHeader.style.display = getDisplayStyle(isReordering);
    tableHeader.appendChild(downHeader);
    var th1 = document.createElement('th');
    th1.appendChild(document.createTextNode('Title'));
    tableHeader.appendChild(th1);
    var th2 = document.createElement('th');
    th2.appendChild(document.createTextNode('Next action'));
    tableHeader.appendChild(th2);
    tableHeader.appendChild(document.createElement('th'));
    tableHeader.appendChild(document.createElement('th'));
    tableHeader.appendChild(document.createElement('th'));
    return tableHeader;
}

function processTodoResponse() {
    if (xmlhttp.readyState == 4) {
        //alert('calling back');
        var xmlDoc = xmlhttp.responseXML;
        var categories = xmlDoc.documentElement.getElementsByTagName("category");
        var todoUl = document.getElementById('todoUl');
        clearAll(todoUl);
        allTodoIDs = new Array();
        todoIDToNote = new Array();
        var categoryList = document.getElementById('newTodoCategory');
        clearAll(categoryList);
        numCategories = categories.length;
        var curAllTodosIndex = 0;
        for (var catIndex = 0; catIndex < categories.length; catIndex++) {
            var category = categories[catIndex].getAttribute("type");
            var categoryLi = document.createElement('li');
            var categoryP = document.createElement('p');
            var categoryStrong = document.createElement('strong');
            categoryStrong.appendChild(document.createTextNode(category));
            categoryP.appendChild(categoryStrong);
            // TODO - center in relation to something else?
            categoryP.style.textAlign = 'center';
            categoryLi.appendChild(categoryP);
            todoUl.appendChild(categoryLi);
            var catOption = document.createElement('option');
            catOption.setAttribute("value", category);
            catOption.appendChild(document.createTextNode(category));
            categoryList.appendChild(catOption);

            var curLi = document.createElement('li');
            curLi.style.listStyleType = 'none';
            var curTable = document.createElement('table');
            // Using a TBody so IE can handle it - see http://ncyoung.com/entry/494
            var curTBody = document.createElement('tbody');
            curTBody.appendChild(createTodoTableHeader(catIndex));
            var todos = categories[catIndex].getElementsByTagName('todo');
            for (var i = 0; i < todos.length; i++) {
                allTodoIDs[curAllTodosIndex] = todos[i].getAttribute("todoID");
                if (todos[i].getAttribute("note")) {
                    var note = todos[i].getAttribute("note");
                    var parsedNote = "";
                    // Replace the \ns with newlines.
                    var backslashRegex = /^(.*?)\\(.)(.*)$/;
                    var keepGoing = true;
                    while (keepGoing) {
                        var match = backslashRegex.exec(note);
                        if (match == null) {
                            parsedNote = parsedNote + note;
                            keepGoing = false;
                        } else {
                            parsedNote = parsedNote + match[1];
                            if (match[2] == 'n') {
                                parsedNote = parsedNote + "\n";
                            } else {
                                parsedNote = parsedNote + match[2];
                            }
                            note = match[3];
                        }
                    }
                    todoIDToNote[allTodoIDs[curAllTodosIndex]] = parsedNote;
                }
                var todoRow = document.createElement("tr");
                todoRow.id = "row" + allTodoIDs[curAllTodosIndex];
                var upTD = document.createElement("td");
                upTD.setAttribute("id", "up" + allTodoIDs[curAllTodosIndex]);
                upTD.style.display = getDisplayStyle(isReordering);
                var upButton;
                if (!useArrowImages) {
                    upButton = document.createElement("input");
                    upButton.setAttribute("type", "button");
                    upButton.setAttribute("value", "-");
                    upButton.setAttribute("onclick", "return reorder(" + allTodoIDs[curAllTodosIndex] + ", true);");
                } else {
                    upButton = document.createElement("a");
                    upButtonImg = document.createElement("img");
                    upButtonImg.src = "uparrow.png";
                    upButtonImg.alt = "up";
                    upButtonImg.title = "up";
                    upButtonImg.style.borderWidth = "0px";
                    upButton.appendChild(upButtonImg);
                    upButton.href = "javascript:reorder(" + allTodoIDs[curAllTodosIndex] + ", true);";
                }
                if (i == 0) {
                    upButton.style.display = "none";
                }
                upTD.appendChild(upButton);
                todoRow.appendChild(upTD);
                var downTD = document.createElement("td");
                downTD.setAttribute("id", "down" + allTodoIDs[curAllTodosIndex]);
                downTD.style.display = getDisplayStyle(isReordering);
                var downButton;
                if (!useArrowImages) {
                    downButton = document.createElement("input");
                    downButton.setAttribute("type", "button");
                    downButton.setAttribute("value", "+");
                    downButton.setAttribute("onclick", "return reorder(" + allTodoIDs[curAllTodosIndex] + ", false);");
                } else {
                    downButton = document.createElement("a");
                    var downButtonImg = document.createElement("img");
                    downButtonImg.src = "downarrow.png";
                    downButtonImg.alt = "down";
                    downButtonImg.title = "down";
                    downButtonImg.style.borderWidth = "0px";
                    downButton.appendChild(downButtonImg);
                    downButton.href = "javascript:reorder(" + allTodoIDs[curAllTodosIndex] + ", false);";
                }
                if (i == todos.length - 1) {
                    downButton.style.display = "none";
                }
                downTD.appendChild(downButton);
                todoRow.appendChild(downTD);
                var titleTD = document.createElement("td");
                titleTD.appendChild(document.createTextNode(todos[i].getAttribute("title")));
                todoRow.appendChild(titleTD);
                var nextActionTD = document.createElement("td");
                nextActionTD.appendChild(document.createTextNode(todos[i].getAttribute("nextAction")));
                todoRow.appendChild(nextActionTD);
                var removeButtonTD = document.createElement("td");
                var removeButtonForm = document.createElement("form");
                removeButtonForm.style.marginBottom = "0px";
                removeButtonForm.action = "javascript:updateTodo(" + allTodoIDs[curAllTodosIndex] + ");";
                var removeButton = document.createElement("input");
                removeButton.setAttribute("type", "submit");
                removeButton.value = "Done with this action";
                removeButtonForm.appendChild(removeButton);
                removeButtonTD.appendChild(removeButtonForm);
                todoRow.appendChild(removeButtonTD);
    
                var noteIconTD = document.createElement("td");
                var noteIcon = document.createElement("a");
                var noteIconImg = document.createElement("img");
                if (todos[i].getAttribute("note") && todos[i].getAttribute("note") != "") {
                    noteIconImg.src = "noteicon.png";
                    noteIconImg.alt = "Edit note";
                } else {
                    noteIconImg.src = "noteiconnone.png";
                    noteIconImg.alt = "Add note";
                }
                noteIconImg.title = noteIconImg.alt;
                noteIconImg.style.borderWidth = "0px";
                noteIcon.appendChild(noteIconImg);
                noteIcon.href = "javascript:viewNote(" + allTodoIDs[curAllTodosIndex] + ");";
                noteIcon.style.cssText = "float: left;";
                noteIconTD.appendChild(noteIcon);
                var noteSpan = document.createElement("div");
                noteSpan.id = "notespan" + allTodoIDs[curAllTodosIndex];
                noteSpan.style.cssText = "float: left;";
                noteIconTD.appendChild(noteSpan);
                noteIconTD.style.cssText = "float: left;";
                todoRow.appendChild(noteIconTD);

                curTBody.appendChild(todoRow);
                curAllTodosIndex++;
            }
            curTable.appendChild(curTBody);
            curLi.appendChild(curTable);
            todoUl.appendChild(curLi);
        }
        // Append "add new category"
        var addNewCatOption = document.createElement('option');
        addNewCatOption.setAttribute("value", addNewCatText);
        addNewCatOption.appendChild(document.createTextNode(addNewCatText));
        categoryList.appendChild(addNewCatOption);
        setStatusDone();
    }
}

// using doRequest() in gregcommon.js

function refreshTodosAndCalendar(xmlName, async, updateStatus, setLastStatus) {
    refreshTodosCommon(xmlName, async, updateStatus, setLastStatus, processTodoResponseAndRefreshCalendar);
}


function refreshTodos(xmlName, async, updateStatus, setLastStatus) {
    refreshTodosCommon(xmlName, async, updateStatus, setLastStatus, processTodoResponse);
}

// TODO - still doesnt work synchronously
function refreshTodosCommon(xmlName, async, updateStatus, setLastStatus, callbackFunc) {
    //alert('refreshing');
    if (updateStatus) {
        if (setLastStatus) {
            setStatus("Refreshing...", "refreshing");
        } else {
            setStatus("Refreshing...", "");
        }
    }
    doRequest(xmlName + "?" + Math.random(), async, callbackFunc, "GET", null);
    /*var myAjax = new Ajax.Request(xmlName + "?" + Math.random(),
        {method: 'GET', onSuccess: processTodoResponse, parameters: Math.random(), asynchronous: async});
    if (!async) {
        processTodoResponse(myAjax.transport);
    }*/
}

function refreshCalendarWithDays(numDays) {
    var today = new Date();
    doRequest("getcalendarentries.cgi?year=" + today.getFullYear() + "&month=" + (today.getMonth() + 1) + "&day=" + today.getDate() + "&numDays=" + numDays, true, processCalendarResponse, "GET", null);
}

function refreshCalendar() {
    refreshCalendarWithDays(daysInAdvance);
}

function updateCalendar() {
    updateCalendarWithDays(daysInAdvance);
}

function updateCalendarWithDays(numDays) {
    var calendardaysTBody = document.getElementById('calendardaysTBody');
    clearAllAfterFirstElementType(calendardaysTBody, "tr");
    var curDay = new Date();
    var curMonth = curDay.getMonth();
    var endDay = new Date(curDay);
    // Ugh - for some reason this doesn''t work on Firefox 1.0.5 when going
    // past the end of the year
    //endDay.setDate(endDay.getDate() + numDays);
    for (var i = 0; i < numDays; i++) {
        endDay.setDate(endDay.getDate() + 1);
    }
    //alert('endDay is ' + endDay);
    var endMonth = endDay.getMonth();
    var monthText = months[curMonth];
    if (curMonth != endMonth) {
        monthText = monthText + " to " + months[endMonth];
    }
    var calendardaysTitle = document.getElementById("calendardaysTitle");
    clearAll(calendardaysTitle);
    calendardaysTitle.appendChild(document.createTextNode(monthText));//, calendardaysTitle.firstChild);
    var curDayOfWeek = curDay.getDay();
    var curRow = document.createElement("tr");
    // Start out the row with blank entries.
    for (var i = 0; i < curDayOfWeek; i++) {
        curRow.appendChild(document.createElement("td"));
    }
    for (var dayIndex = 0; dayIndex < numDays; dayIndex++) {
        curDayOfWeek = curDay.getDay();
        var curTD = document.createElement("td");
        curTD.id = "calendar" + curDay.getMonth() + '-' + curDay.getDate();
        curTD.appendChild(document.createTextNode(curDay.getDate()));
        curTD.title = "";
        curRow.appendChild(curTD);
        if (curDayOfWeek == 6) {
            calendardaysTBody.appendChild(curRow);
            if (dayIndex < numDays - 1) {
                curRow = document.createElement("tr");
            }
        }
        curDay.setDate(curDay.getDate() + 1);
    }
    // Show the last row.
    curDayOfWeek = curDay.getDay();
    for (var i = curDayOfWeek; i < 7; i++) {
        curRow.appendChild(document.createElement("td"));
    }
    calendardaysTBody.appendChild(curRow);
}

setTimeout('updateCalendar()', 0);
// We dont want to update the status the first time, because the element
// might not be created yet (??) or something.
refreshTodosAndCalendar(todoFileName, true, false, true);

//]]>
