if (typeof(WWDC) == "undefined") WWDC = {};




WWDC.Descriptions = Class.create({

    initialize: function(initial) {
        this.items = [];
        this.data = [];
        this.initial = initial || 'off';
        this.initial = (this.initial == 'off') ? 'on' : 'off';
    },

    initializeDisplay: function(container) {
        if (!container) return;

        this.container = container;

        this.createAllTrigger();

        this.toggleAllTrigger(this.initial);
        this.toggleAll();
    },

    createAllTrigger: function() {
        this.triggerContainer = document.createElement('div');
        this.triggerContainer.className = 'descriptions';
        this.container.appendChild(this.triggerContainer);

        this.trigger = new Element('a'); // needs to be a extended element
        this.trigger.className = this.initial;
        this.trigger.innerHTML = WWDC.Local.Descriptions;
        this.triggerContainer.appendChild(this.trigger);

        this.trigger.observe('mousedown', WWDC.UpdateUrl.bind(null, { descriptions:false }));
        this.trigger.observe('click', this.toggleAll.bind(this));
    },

    toggleAllTrigger: function(value) {
        if (value) {
            this.trigger.className = value;
        } else {
            if (this.data.length == 0) this.trigger.className = 'off';
            if (this.data.length == this.items.length) this.trigger.className = 'on';
        }
    },

    toggleAll: function(evt) {
        if (this.trigger.className == 'on') {
            this.data = this.items; // turn off
        } else if (this.trigger.className == 'off') {
            this.data = []; // turn on
        }

        // this.items.each(this.toggleById.bind(this, true));
        for (var i=this.items.length-1; i>=0; i--) {
            this.toggleById(true, this.items[i]);
        }
        this.toggleAllTrigger();
    },

    toggle: function(evt) {
        if (!Object.isString(evt)) {
            var row =  evt.findElement('tr');
            if (row) var id = row.identify();
        }
        if (!id) var id = evt;
        this.toggleById(false, id);

        this.toggleAllTrigger();
    },

    toggleById: function(quick, id) {
        var description = $(id+'-desc');
        if (description) description = description.down('div');
        if (description) {
            if (this.data.indexOf(id) > -1) {
                // hide
                this.data = this.data.without(id);
                if (quick) {
                    description.removeClassName('show');
                } else {
                    description.morph('height:0;', { duration:.3,
                        afterFinish: function(obj) {
                            obj.element.removeClassName('show').setStyle({ height:'' });
                        }
                    });
                }
            } else {
                // show
                this.data.push(id);
                if (quick || AC.Detector.isIE()) {
                    description.addClassName('show');
                } else {
                    description.morph('show', { duration:.3 });
                }
            }
        }
    }

});




WWDC.Filters = Class.create({

    initialize: function(filters, initial) {
        this.filters = {};
        this.applied = {};
        for (filter in WWDC.Local.Filters) {
            if (filters.indexOf(filter)>=0) {
                this.filters[filter] = WWDC.Local.Filters[filter];
                this.applied[filter] = [];
            }
        }

        this.initial = initial || {};
    },

    initializeDisplay: function(container, target) {
        if (!container || !target) return;

        this.container = container;
        this.target = target;

        this.createFilters();
        this.init();
    },

    init: function() {
        for (filter in this.filters) {
            if (this.initial[filter]) {
                var initial = this.initial[filter].split(',');
                for (var i=initial.length-1; i>=0; i--) {
                    var trigger = this.container.down('a.'+initial[i]);
                    this.toggle(filter, initial[i], trigger);
                }
            }
        }
    },

    createFilters: function() {
        for (filter in this.filters) {
            this.createFilter(filter, this.filters[filter]);
        }
    },

    createFilter: function(name, items) {
        var wrapper = document.createElement('div');
        wrapper.className = name;
        this.container.appendChild(wrapper);

        for (filter in items) {
            var link = this.createLink(name, items[filter]);
            wrapper.appendChild(link);
            wrapper.appendChild(document.createTextNode(' '));
        }
    },

    createLink: function(name, item) {
        var link = new Element('a', { className:item.id+' on' });
        link.innerHTML = item.title;

        var options = {};
        options[name] = item.id;
        link.observe('mousedown', WWDC.UpdateUrl.bind(null, options));
        link.observe('click', this.toggle.bind(this, name, item.id, link));

        return link;
    },

    toggle: function(type, name, trigger, evt) {
        if (trigger.hasClassName('on')) {
            this.applied[type].push(name);
            trigger.removeClassName('on');
        } else {
            this.applied[type] = this.applied[type].without(name);
            trigger.addClassName('on');
        }

        this.target.className = '';
        for (filter in this.applied) {
            if (this.applied[filter].length>0) {
                this.target.className += ' '+WWDC.Permutations(this.applied[filter]).join(' ');
            }
        }
    }


});




WWDC.SessionsTable = Class.create({

    columns: [ 'title', 'type', 'focus', 'level' ],

    lastSortedBy: false,
    sort: function(className, a, b) {
        if (Object.isArray(a)) a = a[0];
        var A = a;
        if (a.getElementsByClassName(className)[0]) {
            if (a.getElementsByClassName(className)[0].getElementsByTagName('a')[0]) {
                A = a.getElementsByClassName(className)[0].getElementsByTagName('a')[0].innerHTML.toLowerCase();
            } else {
                A = a.getElementsByClassName(className)[0].innerHTML.toLowerCase();
            }
        }

        if (Object.isArray(b)) b = b[0];
        var B = b;
        if (b.getElementsByClassName(className)[0]) {
            if (b.getElementsByClassName(className)[0].getElementsByTagName('a')[0]) {
                B = b.getElementsByClassName(className)[0].getElementsByTagName('a')[0].innerHTML.toLowerCase();
            } else {
                B = b.getElementsByClassName(className)[0].innerHTML.toLowerCase();
            }
        }

        // id
        if (parseInt(A) < parseInt(B)) return -1;
        if (parseInt(A) > parseInt(B)) return 1;

        // else
        if (A < B) return -1;
        if (A > B) return 1;

        // return by title if everything else is the same
        if (className != 'title') return this.sort('title', a, b);

        // if they are identical
        return 0;
    },

    initialize: function(data, options) {
        this.data = data;

        this.options = options || {};
        if (!this.options.restrictBy) this.options.restrictBy = false;

        return this.data;
    },

    initializeDisplay: function(wrapper, loading, initial) {
        if (!wrapper || !loading) return;
        this.loading = $(loading);

        this.wrapper = $(wrapper);
        wrapper.innerHTML = '';

        this.descriptions = new WWDC.Descriptions(initial.descriptions);
        this.filters = new WWDC.Filters(this.columns, initial);

        this.createTable();
        this.setSortEvents();

        this.afterSort = function() {
            this.filters.initializeDisplay($('filters'), this.table);
            this.descriptions.initializeDisplay($('filters'));
            this.showRow(initial.session);
        }.bind(this)
        this.sortEvent(this.tableHead.down('.'+initial.sort));
    },

    createTable: function(by) {
        this.table = new Element('table', { cellpadding:0, cellspacing:0 }); // needs to be a extended element
        this.wrapper.setOpacity(.2);
        this.createHeader();

        this.tableBody = new Element('tbody'); // needs to be a extended element
        this.rows = [];
        if (Object.isArray(this.data)) {
            for (var i=this.data.length-1; i>=0; i--) {
                this.createRow(this.data[i]);
            }
        } else {
            var i = 0;
            for (data in this.data) {
                this.createRow(this.data[data], i);
                i++;
            }
        }

        this.table.appendChild(this.tableHead);
        this.table.appendChild(this.tableBody);
        this.wrapper.appendChild(this.table);
    },

    createHeader: function() {
        this.tableHead = new Element('thead'); // needs to be a extended element

        var row = document.createElement('tr');
        this.tableHead.appendChild(row);

        var total = this.columns.length-1;
        this.headers = [];
        for (var i=0; i<this.columns.length; i++) {
            var cell = document.createElement('th');
            cell.className = this.columns[i];
            cell.innerHTML += '<a class="'+this.columns[i]+'">'+this.columns[i].capitalize()+'</a>';
            this.headers.push(cell);
            row.appendChild(cell);
        }
    },

    createRow: function(data, i) {
        if (this.options.restrictBy) {
            for (restrict in this.options.restrictBy) {
                if (Object.isArray(data[restrict])) {
                    if (data[restrict].indexOf(this.options.restrictBy[restrict]) < 0) return;
                } else if (Object.isString(data[restrict])) {
                    if (data[restrict] != this.options.restrictBy[restrict]) return;
                }
            }
        }

        var row = new Element('tr', { id:data.id }); // needs to be a extended element
        this.addFilterClasses(row, data);
        for (var i=0; i<this.columns.length; i++) {
            this.createCell(row, data, this.columns[i], i);
        }

        row.observe('mousedown', WWDC.UpdateUrl.bind(null, { session:data.id }));
        row.observe('click', this.descriptions.toggle.bind(this.descriptions));

        this.rows.push(row);

        if (data.description) {
            this.descriptions.items.push(data.id);

            var row = new Element('tr', { id:data.id+'-desc', className:'description' }); // needs to be a extended element
            this.createDescCell(row, data);
            this.addFilterClasses(row, data);

            this.rows[this.rows.length-1] = [this.rows[this.rows.length-1], row];
        }
    },

    addFilterClasses: function(row, data) {
        for (var i=this.columns.length-1; i>=0; i--) {
            var column = this.columns[i];
            if (WWDC.Local.Filters[column]) {

                if (Object.isArray(data[column])) {

                    data[column] = data[column].uniq();
                    var string = WWDC.Permutations(data[column]).join(' ');
                    string = string.toLowerCase();
                    row.addClassName(string);

                } else {

                    var value = WWDC.Local.Filters[column][data[column]];
                    if (value) value = value.id;
                    row.addClassName(value);

                }
            }
        }
    },

    createCell: function(row, data, column, i) {
        var cell = document.createElement('td');
        cell.className = column;
        if (Object.isArray(data[column])) {
            cell.innerHTML = data[column].join(', ');
        } else if (data[column]) {
            cell.innerHTML = data[column];
        }

        row.appendChild(cell);
    },

    createDescCell: function(row, data) {
        var cell = new Element('td', { colspan:this.columns.length });
        row.appendChild(cell);

        var description = document.createElement('div');
        description.innerHTML = '<div>'+data.description+'</div>';
        cell.appendChild(description);
    },

    showRow: function(item) {
        if (item && $(item)) {
            this.descriptions.toggle(item);

            var fades = [];
            var appears = [];

            var elements = [];
            elements.push($(item));
            if ($(item+'-desc')) elements.push($(item+'-desc'));
            for (var i=elements.length-1; i>=0; i--) {
                var fade = new Effect.Fade(elements[i], { to:.6, sync:true });
                var appear = new Effect.Appear(elements[i], { from:.6, sync:true });

                fades.push(fade);
                appears.push(appear);
            }

            new Effect.ScrollTo(item, { duration:.7,
                afterFinish: function(effect) {
                    new Effect.Parallel(fades, { duration:.4,
                        afterFinish: function(effect) {
                            new Effect.Parallel(appears, { duration:.3 });
                        }
                    })
                }
            });
        }
    },

    setSortEvents: function() {
        for (var i=this.headers.length-1; i>=0; i--) {
            var header = $(this.headers[i]);
            var link = header.down('a');
            link.observe('mousedown', WWDC.UpdateUrl.bind(null, { sort:link.className }));
            link.observe('click', this.sortEvent.bind(this, header));
        }
    },

    sortEvent: function(header, evt) {
        var sortBy = header.className.toString().replace('sorted', '').replace('leftcap', '').replace('rightcap', '').strip();

        if (header.hasClassName('sorted')) {
            this.rows.reverse();
            if (this.table.hasClassName('reverse')) {
                this.table.removeClassName('reverse');
            } else {
                this.table.addClassName('reverse');
            }

            this.resetTable(sortBy);
        } else {
            this.loading.addClassName('loading');
            var afterFinish = function(sortBy) {

                this.rows.sort(this.sort.bind(this, sortBy));

                this.resetHeaders(sortBy);
                this.resetTable(sortBy);

                this.afterSort();
                this.afterSort = function() {};

            }.bind(this, sortBy);

            if (!AC.Detector.isWebKit() || isLessThanSafari3) {
                new Effect.Parallel([
                  new Effect.Fade($$('#content .sessions .nav')[0], { to:.2, sync: true }), 
                  new Effect.Fade(this.wrapper, { to:.2, sync:true })
                ], {
                  duration: .2,
                  afterFinish: afterFinish
                });
            } else {
                afterFinish();
            }
        }
    },

    resetHeaders: function(sortBy) {
        var last = this.tableHead.down('th.sorted');
        if (last) {
            last.removeClassName('sorted');
            this.table.removeClassName('reverse');
            last = last.down('a');
        }

        var active = this.tableHead.down('th.'+sortBy);
        active.addClassName('sorted');
        active = active.down('a');
    },

    resetTable: function(sortBy) {
        this.tableBody.update(''); // apparantly, this has to be update -- rather than innerHTML -- for IE

        this.loading.removeClassName('loading');
        $$('#content .sessions .nav')[0].setOpacity(1);
        this.wrapper.setOpacity(1);

        for (var i=0; i<this.rows.length; i++) {
            var appendRow = function(row) {
                if (row.down('.sorted')) row.down('.sorted').removeClassName('sorted');
                if (row.down('.'+sortBy)) row.down('.'+sortBy).addClassName('sorted');
                this.tableBody.appendChild(row);
            }.bind(this)

            for (var j=0; j<this.rows[i].length; j++) {
                appendRow(this.rows[i][j]);
            }
        }
    }
});




WWDC.Init = function() {
    var data = WWDC.SessionsData;

    var wrapper = $('sessionlist');
    var loading = $('sessionlist').up('.loading');

    var initial = {};
    if (document.location.hash) var initial = document.location.hash.replace('#', '').toQueryParams();

    // initial variables
    if (!initial.sort) initial.sort = 'title';
    if (!initial.descriptions) initial.descriptions = 'off';

    var sessions = new WWDC.SessionsTable(data);
    sessions.initializeDisplay(wrapper, loading, initial);
}
