/*global $, document, window, webdecalendar, tbd, tb, getRelativeStartTime, findEventContainer, isDailyContinuation, buildEventElement, adjustSpacing */

if (!window.webdecalendar) {
    window.webdecalendar = {};
}
window.webdecalendar.lastEvent = null;
window.webdecalendar.events = [];
window.webdecalendar.cancelAdd = true;

function dateAdjust(i) {
    if (parseInt(i, 10) < 10) {
        i = '0' + i;
    }
    return i;
}

/** buildEventUrl will create a url to open the event creation window.
 *
 * The popup window will either be the detailed or simple window, depending on user setting.
 * the extra parameter gets appended to the url. Kind of a gimp way to let different functionality
 * happen when needed, but it was the easiest solution. It was do it that way or have a bunch of
 * parameters to account for different functionality.
 */
function buildEventUrl(details, extra) {
    var url = "";
    if (details) {
        url += "/details.php?";
    } else {
        url = "/event.php?";
    }

    if ($('#updateForm').length > 0 && $.simBox.avail === false) { //called from the event popup
        url += $('#updateForm').serialize();
    } else { //called from render.php, make new event link
        if (window.webdecalendar.user && window.webdecalendar.user !== "") {
            url += 'user=' + window.webdecalendar.user + '&';
        }
        if (window.webdecalendar.token && window.webdecalendar.token !== "") {
            url += 'token=' + window.webdecalendar.token + '&';
        }
        if (extra) {
            url += extra;
        }
    }
    return url;
}

function buildEventTitle(el) {
    var skipTime = $('td.halfHour').length;
    var a;
    if ($(el).find('id').length !== 0) {
        a = $(document.createElement('a'));
        var eventDetailed = window.webdecalendar.eventView;
        if ($(el).find('owner').text() !== webdecalendar.user) {
            eventDetailed = false;
        }
        var eventURL = buildEventUrl(eventDetailed, 'event=' + $(el).find('id').text());
        a.attr('href', eventURL);
        a.css({'color': 'black'});
        if (eventDetailed) {
            a.click(function (e) {
                e.stopPropagation();
                $.simBox({url: eventURL, style: {height: tbd.height, width: tbd.width}});
                return false;
            });
        } else {
            a.click(function (e) {
                e.stopPropagation();
                $.simBox({url: eventURL, style: {height: tb.height, width: tb.width}});
                return false;
            });
        }
    } else {
        a = $(document.createElement('span'));
    }
    var aText = '';
    if ($(el).find('isAllDay').length === 0 && !skipTime) {
        var sec = getRelativeStartTime(el);
        var cd = new Date(sec);
        var c_hour = cd.getUTCHours() % 12;
        if (c_hour === 0) {
            c_hour = 12;
        }
        var meridian = cd.getUTCHours() > 11 ? 'p' : 'a';
        var eTime = c_hour + ':' + dateAdjust(cd.getUTCMinutes()) + meridian;
        aText += eTime + ' ';
    }
    aText += $(el).find('name').text(); 
    a.text(aText);
    // also add the title
    a.attr('title', aText);
    if ($(el).find('image').text() !== '') {
        var img = $(document.createElement('img'));
        img.attr('src', $(el).find('image').text());
        img.attr('alt', $(el).find('name').text());
        img.attr('height', 16);
        img.attr('width', 16);
        a.prepend(img);
    }

    return a;
}

function getRelativeStartTime(el) {
    var st = parseInt($(el).find('startTime').text(), 10);
    return getRelativeTime(st);
}

function getRelativeTime(t) {
    var st = parseInt(t, 10) * 1000;
    // use the browser's time setting
    // getTimezoneOffset is minutes (?)
    st -= new Date(st).getTimezoneOffset() * 60000;
    if (window.webdecalendar.tzOffset) {
        // user is logged in and has a timezone set
        st += window.webdecalendar.tzOffset;
    }

    return st;
}


function clearEvents() {
    $('.allday').remove();
    $('.event').remove();
    $('.lockedEvent').remove();
    $('.clone').remove();
    window.webdecalendar.events = [];
}

function dateIncrement(curTime, recPeriod) {
    var curDate = new Date();
    curDate.setTime(curTime);
    if (recPeriod === 'day') {
        curDate.setDate(curDate.getDate() + 1);
    } else if (recPeriod === 'week') {
        curDate.setDate(curDate.getDate() + 7);
    } else if (recPeriod === 'month') {
        curDate.setMonth(curDate.getMonth() + 1);
    } else if (recPeriod === 'year') {
        curDate.setFullYear(curDate.getFullYear() + 1);
    } else {
        return;
    }
    return curDate.getTime();
}

function getNumberOfInstances(i) {
    if (i.indexOf('_') > 0) {
        i = i.substring(0, i.indexOf('_'));
    }
    var total = 0;
    for (var events in window.webdecalendar.events) {
        if (events) {
            var testId = events.id;
            if (testId && testId.indexOf('_') > 0) {
                testId = testId.substring(0, testId.indexOf('_'));
            }
            if (testId && testId  === i) {
                total += 1;
            }
        }
    }
    return total;
}

function processEvent(index, eventElement) {
    var elem = $(eventElement);
    var e = {
        recurs:     elem.find('startRecur').text() === '' ? false : {
            period: elem.find('period').text(),
            start:  parseInt(elem.find('startRecur').text(), 10) * 1000,
            end:    parseInt(elem.find('endRecur').text(), 10) * 1000
        },
        color:      elem.find('color').text(),
        time:       { 
            start:  parseInt(elem.find('startTime').text(), 10) * 1000,
            end:    parseInt(elem.find('endTime').text(), 10) * 1000,
            duration: parseInt(elem.find('length').text(), 10) * 1000,
            allday: elem.find('isAllDay').length === 1
        },
        owner:      elem.find('owner').text(),
        id:         elem.find('id').text(),
        description:    elem.find('description').text()
    };
    e.title = buildEventTitle(elem);

    if (e.recurs) {
        var d = getRelativeStartTime(elem);
        while (d < e.recurs.end && d < window.webdecalendar.dates.end * 1000) {
            e.lastContainer = e.container;
            // while we have a valid container....
            e.container = findEventContainer(elem, d);
            if (!e.container) {
                d = dateIncrement(d, e.recurs.period);
                continue;
            }

            if (isDailyContinuation(e)) {
                var placeHolder = e.element.clone().css({zIndex: -1, opacity: 0}).attr('class', 'clone');
                var containerContents = $('.event', e.container).get(0);
                if (containerContents) {
                    $(containerContents).before(placeHolder);
                } else {
                    e.container.append(placeHolder);
                }
                while (placeHolder.height() + placeHolder.offset().top <= e.lastCreatedElement.offset().top) {
                    placeHolder.height(e.lastCreatedElement.height() + placeHolder.height());
                }
                
                e.lastCreatedElement.width(e.lastCreatedElement.width() + placeHolder.width()).css({
                    position: 'absolute',
                    zIndex: 10,
                    top: e.lastCreatedElement.offset().top,
                    left: e.lastCreatedElement.offset().left
                });
            } else {
                e.element = buildEventElement(elem, e);
                e.lastCreatedElement = e.element.clone(true).appendTo(e.container);
                window.webdecalendar.events[window.webdecalendar.events.length] = {
                    recurs: e.recurs,
                    time:   { 
                        start:    d,
                        end:      d + e.time.duration,
                        duration: e.time.duration,
                        allday:   e.time.allday
                    },
                    id:     e.id,
                    seq:    getNumberOfInstances(e.id)
                };
            }
            d = dateIncrement(d, e.recurs.period);
        }
    } else {
        e.container = findEventContainer(elem);
        if (e.container) {
            e.element   = buildEventElement(elem, e);
            window.webdecalendar.events[window.webdecalendar.events.length] = e;
            e.container.append(e.element);
        }
    }
}

function getEventsInRange(start, end) {
    var rData = { action: 'getEvents',
        start: start,
        end: end
    };
    
    if (window.webdecalendar.resource) {
        rData.resource = window.webdecalendar.resource;
    } else {
        rData.user = window.webdecalendar.user;
        if (window.webdecalendar.token) {
            rData.token = window.webdecalendar.token;
        }
    }
    if (window.webdecalendar.cal) {
        rData.calendar = window.webdecalendar.cal;
    }
    var events = $.ajax({
        url: '/api.php',
        data: rData,
        success: function (data, status) {
            if ($(data).find('error').find('message').text() !== '') {
                $('#status').text($(data).find('error').find('message').text()).attr({ 'class': 'error' });
            } else if ($(data).find('Event') || $(data).find('Holiday') || $(data).find('RecurringEvent')) {
                clearEvents();
                $(data).find("Holiday").each(processEvent);
                $(data).find("Event").each(processEvent);
                $(data).find("RecurringEvent").each(processEvent);
                adjustSpacing();
            }
        },
        error: function (xhr, status, errorThrown) {
            if (status  === 'parsererror') {
                // TODO: i18n
                $('#status').html('No events in range.');
            } else {
                $('#status').html('Unknown Error.');
            }
        }
    });
    return events;
}

function getMiniCal(month) {
    if (typeof month === 'undefined') {
        month = '2008-3';
    }
    var cal = $.ajax({
        url: '/api.php',
        data: {
            action: 'getMiniCal',
            month: month,
            user: window.webdecalendar.user,
            format: 'plain'
        },
        success: function (data, status) {
            $('#miniCal').html($(data));
        },
        error: function (xhr, status, errorThrown) {
            $('#status').text('Unknown Error.');
        }
    });
    return cal;
}



function nozeros(input) {
    if ((input.length > 1) && (input.substr(0, 1) === "0")) {
        return input.substr(1);
    } else {
        return input;
    }
}

function parseTime(t) {
    var y = t.substring(0, 4);
    var m = nozeros(t.substring(5, 7));
    var d = nozeros(t.substring(8, 10));
    var h = nozeros(t.substring(11, 13));
    var i = nozeros(t.substring(14, 16));
    var s = nozeros(t.substring(17, 19));
    // month counts from 0, not 1
    var thisDate = new Date(y, m - 1, d, h, i, s);
    return thisDate.getTime() / 1000;
}

function updateView() {
    if (window.webdecalendar && window.webdecalendar.dates) {
        return getEventsInRange(window.webdecalendar.dates.start, window.webdecalendar.dates.end);
    }
    window.location.reload();
}


function reloadPage() {
    window.location.reload();
}

