var count = {
    us: 0,
    ca: 0,
    reset: function() {
        count.us = 0;
        count.ca = 0;
    }
};

var state = {
    us: 0,
    ca: 0,
    reset: function() {
        state.us = 0; save('us', 0);
        state.ca = 0; save('ca', 0);
    }
};

var urls = {
    us: 'http://www.world66.com/myworld66/visitedStates/statemap?visited=',
    ca: 'http://www.world66.com/myworld66/visitedCanadianStates/countrymap?visited='
}

addEventListener('load', function() {
    applyToAllItems(function(item) {
        item.addEventListener('click', toggle, false);
    });

    $('us-map').addEventListener('click', map, false);
    $('ca-map').addEventListener('click', map, false);

    $('reset').addEventListener('click', reset, false);

    restore('us');
    restore('ca');
    init();
}, false);

function applyToAllItems(func, id) {
    var root = $(id) || document;
    var items = root.getElementsByTagName('a');

    for (var i = 0; i < items.length; i++) {
        var m;
        if ((m = items[i].href.match(/#([A-Z]{2})$/)) == null)
            continue;
        func(items[i], m[1]);
    }
}

function findParent(node, localName) {
    while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName)) {
        node = node.parentNode;
    }
    return node;
}

function findPosition(node) {
    var pos = -1;
    while (node) {
        if (node.nodeType == Node.ELEMENT_NODE) {
            pos++;
        }
        node = node.previousSibling;
    }
    return pos;
}

function init() {
    setTimeout('update("us")', 0)
    setTimeout('update("ca")', 0)
    setTimeout('scrollTo(0, 1)', 100);
}

function toggle(event) {
    var id = findParent(this, 'div').id;
    var pos = findPosition(findParent(this, 'li'));
    var delta;

    if (this.className == 'checked') {
        this.className = '';
        delta = -1;
    } else {
        this.className = 'checked';
        delta = +1;
    }

    count[id] += delta;

    update(id);
    save(id, delta * Math.pow(2, pos));

    event.preventDefault();
}

function update(id) {
    var span = $(id + '-count');
    var list = $(id + '-list');
    var total = list.getElementsByTagName('li').length;
    var percent = Math.round(count[id] / total * 100);
    span.innerHTML = count[id] + ' of ' + total + ' (' + percent + '%)';
}

function save(id, val) {
    state[id] += val;
    document.cookie = id + '=' + state[id].toString(16) + '; expires=' +
        new Date(new Date().getTime() + (30 * 86400000)).toUTCString();
}

function restore(id) {
    var m;
    var re = new RegExp(id + '=(.+)');

    if (m = document.cookie.match(re)) {
        applyToAllItems(function(item) {
            var pos = findPosition(findParent(item, 'li'));
            var val = parseInt(m[1], 16);
            var fact = (pos >= 32) ? 0x100000000 : 0x1;

            if ((val / fact) & Math.pow(2, pos % 32)) {
                item.className = 'checked';
                state[id] += Math.pow(2, pos);
                count[id] += 1;
            }
        }, id);
    }
}

function map(event) {
    var qs = [];
    var id = this.parentNode.id;

    applyToAllItems(function(item, abbr) {
        if (item.className == 'checked') {
            if (id == 'ca') {
                abbr = ({
                    'AB': 'AL',
                    'MB': 'MA',
                    'QC': 'QU',
                    'SK': 'SA',
                    'YT': 'YU',
                })[abbr] || abbr;
            }
            qs.push(abbr);
        }
    }, id);

    open(urls[id] + qs.join(''));

    event.preventDefault();
}

function reset(event) {
    if (confirm('Are you sure you want to reset?')) {
        applyToAllItems(function(item) {
            item.className = '';
        });

        count.reset();
        state.reset();
        init();
    }

    event.preventDefault();
}

function $(id) { return document.getElementById(id); }

