var inputs = [];
var currentDate = new Date();
currentDate.setMilliseconds(0);
var currentUseLocal = null;

window.onload = function() {
    inputs['timestamp'] = document.getElementById('timestamp');
    inputs['iso8601'] = document.getElementById('iso8601');
    inputs['rfc2822'] = document.getElementById('rfc2822');

    for (var i in inputs) {
        inputs[i].prevValue = '';
        inputs[i].onkeypress = inputs[i].onkeyup = inputs[i].onchange = update;
    }
    //inputWatcher.setFieldNames(['timestamp', 'iso8601', 'rfc2822']);
    update();
}

function parse_timestamp(s) {
    var timestamp = parseFloat(s);
    return !isNaN(timestamp) ? new Date(1000 * timestamp) : null;
}

var iso8601extended = /^\d{4}(-\d{2}(-\d{2}([T ]\d{2}(:\d{2}(:\d{2})?)?([,.]\d+)?(Z|[+-]\d{2}(:\d{2})?)?)?)?)?$/;
var iso8601basic = new RegExp(iso8601extended.source.replace(/[:-]\\d/g, '\\d'));
var firstNumber = /[^\d]*(\d+)/g;

function parse_iso8601(s, useLocal) {
    s = s.replace(/,/g, '.');
    var matches = iso8601extended.exec(s);
    if (matches) {
        s = s.substr(0, 10).replace(/-/g, '') + s.substr(10).replace(/:/g, '');
    }
    matches = iso8601basic.exec(s);
    if (!matches) {
        return null;
    }
    var d = new Date();
    d.setUTCFullYear(toNumber(matches[0].substring(0, 4)));
    d.setUTCMonth(matches[1] ? toNumber(matches[1].substr(0, 2)) - 1 : 0);
    d.setUTCDate(matches[2] ? toNumber(matches[2].substr(0, 2)) : 1);
    var hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
    var fraction = matches[6] ? parseFloat(matches[6]) : 0;
    if (matches[3]) {
        hours = toNumber(matches[3].substr(1, 2));
        if (matches[4]) {
            minutes = toNumber(matches[4].substr(0, 2));
            if (matches[5]) {
                seconds = toNumber(matches[5].substr(0, 2));
                milliseconds = 1000 * fraction;
            } else {
                seconds = 60 * fraction;
            }
        } else {
            minutes = 60 * fraction;
        }
    }
    if (useLocal && !matches[7]) {
        d.setHours(hours);
        d.setMinutes(minutes);
    } else {
        d.setUTCHours(hours);
        d.setUTCMinutes(minutes);
    }
    d.setUTCSeconds(seconds);
    d.setUTCMilliseconds(milliseconds);
    if (matches[7] && matches[7] != 'Z') {
        offset = toNumber(matches[7].substr(1, 2)) * 60;
        if (matches[8]) {
             offset += toNumber(matches[8].substr(0, 2));
        }
        d.setTime(d.getTime() + 60000 * offset * (matches[7].substr(0, 1) == '-' ? 1 : -1));
    }
    return d;
}

function toNumber(s) {
    return parseInt(s.replace(/^0+(\d)/, '$1'));
}

function parse_rfc2822(s, useLocal) {
    if (!useLocal && !/([a-z]+|[+-][\d:]+)\s*$/i.test(s)) {
        s += ' UTC';
    }
    return new Date(s);
}

function format_timestamp(date, offset) {
    return date.getTime() / 1000;
}

function format_iso8601(date, offset) {
    var d = new Date(date.getTime() - offset * 60000);
    var s = d.getUTCFullYear() + '-' +
        to2digits(d.getUTCMonth() + 1) + '-' +
        to2digits(d.getUTCDate()) + 'T' + 
        to2digits(d.getUTCHours()) + ':' +
        to2digits(d.getUTCMinutes()) + ':' +
        to2digits(d.getUTCSeconds());
    if (d.getUTCMilliseconds()) {
        s += (d.getUTCMilliseconds() / 1000).toString().substr(1);
    }
    if (offset) {
        var absOffset = Math.abs(offset);
        s += (offset > 0 ? '-' : '+') +
            to2digits(Math.floor(absOffset / 60)) + ':' +
            to2digits((absOffset % 60));
    } else {
        s += 'Z';
    }
    return s;
}

function format_rfc2822(date, offset) {
    var d = new Date(date.getTime() - offset * 60000);
    var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    var s = days[d.getUTCDay()] + ', ' +
        d.getUTCDate() + ' ' +
        months[d.getUTCMonth()] + ' ' +
        d.getUTCFullYear() + ' ' +
        to2digits(d.getUTCHours()) + ':' +
        to2digits(d.getUTCMinutes()) + ':' +
        to2digits(d.getUTCSeconds());
    var absOffset = Math.abs(offset);
    s += ' ' + (offset > 0 ? '-' : '+') +
        to2digits(Math.floor(absOffset / 60)) + ':' +
        to2digits((absOffset % 60));
    return s;
}

function to2digits(n) {
    return n < 10 ? '0' + n : n.toString();
}

function update(state) {
    var newDate;
    var useLocal = document.getElementById('timezone_local').checked;

    var lastChanged = false;
    for (var i in inputs) {
        if (inputs[i].value != inputs[i].prevValue) {
            var parseMethod = window['parse_' + i];
            newDate = inputs[i].value ? parseMethod.call(null, inputs[i].value, useLocal) : null;
            if (newDate && isNaN(newDate.getYear())) {
                newDate = null;
            }
            inputs[i].style.backgroundColor = (newDate || inputs[i].value == '') ? '' : 'red';
            inputs[i].prevValue = inputs[i].value;
            lastChanged = i;
            if (newDate) {
                break;
            }
        }
    }

    if (newDate && newDate != currentDate || useLocal != currentUseLocal) {
        if (newDate) {
            currentDate = newDate;
        }
        if (useLocal != currentUseLocal) {
            lastChanged = false;
        }
        currentUseLocal = useLocal;
        var offset = useLocal ? currentDate.getTimezoneOffset() : 0;
        for (var i in inputs) {
            if (i != lastChanged) {
                var formatMethod = window['format_' + i];
                inputs[i].value = formatMethod.call(null, currentDate, offset);
                inputs[i].prevValue = inputs[i].value;
                inputs[i].style.backgroundColor = '';
            }
        }
    }
}
