//  ----------------------------------------------------------------------------
//  Initialize
//  ----------------------------------------------------------------------------

requests = new RequestsController();

$(function() {
    $('#textInfo').html(video.date.substr(0, 4));
    images = [];
    imageStep = Math.floor(video.duration / 264 / 40) * 40;
    poster = new Poster();
    $('#file').html(compose('file'));
    $('#download').click(function() { download() });
    $('#help').click(function() { help() });
    $('#editor').click(function() { document.location.href = '/' + video.id });
    $('#map').click(function() { document.location.href = '/' + video.id + '/map'});
    $.get('/static/templates/cell.html', function(html) {
        htmlCell = html;
        infoCell = new Cell($('#info'), 'info', compose('info'), 264);
        infoCell.load();
        textCell = new Cell($('#text'), 'text', compose('text'), 536);
        textCell.load();
        if (video.editable)
            $('#text').append(compose('edit'));
        $('#text').append('<div id="eof" />');
        // this fixes a safari rendering bug:
        $('#menuBottom').css({
            top: (window.innerHeight - 56) + 'px'
        });
        cache = new Cache();
        keyboard = new KeyboardController();
        imagePoster = new Image();
        imagePoster.src = '/' + video.id + '/poster.264.jpg';
        $(imagePoster).load(function() {
            var tree = treesort(264);
            for (var i = 0; i < 264; i++) {
                images[tree[i]] = new Image();
                images[tree[i]].src = '/' + video.id + '/frame/' + getTimecode(tree[i] * imageStep) + '.320.jpg';
            }
        });
    });
    uiPNGCache = [];
    $([
      '/static/images/dialogBottomLeft.png',
      '/static/images/dialogBottomRight.png',
      '/static/images/dialogTopLeft.png',
      '/static/images/dialogTopRight.png',
    ]).each(function() {
      var i = uiPNGCache.length;
      uiPNGCache[i] = new Image();
      uiPNGCache[i].src = this;
    });
});

function treesort(n) {
    var array = [];
    var levels = Math.ceil(Math.log(n) / Math.log(2));
    //alert(levels);
    for (var l = 0; l < levels; l++) {
        var items = Math.pow(2, l);
        var start = n / Math.pow(2, l + 1)
        var step = n / items;
        for (var i = 0; i < items; i++) {
            var value = Math.floor(start + i * step);
            if ($.inArray(value, array) == -1)
                array.push(value);
        }
    }
    return array;
}

//  ----------------------------------------------------------------------------
//  Keyboard controller prototype
//  ----------------------------------------------------------------------------

function KeyboardController() {
    /*
        state: 0 (no focus), 1 (focus on input), 2 (focus on textarea)
    */
    this.state = 0;
    this.keys = [
        {
            72: 'h'
        },
        {
            13: 'enter',
            27: 'escape'
        },
        {
            27: 'escape'
        }
    ];
    var t = this;
    $(document).keydown(function(event) { t.pressKey(event) });
}
KeyboardController.prototype.setState = function(state) {
    this.state = state;
}
KeyboardController.prototype.pressKey = function(event) {
    var code = event.which;
    if (typeof(this.keys[this.state][code]) == 'undefined')
        return true;
    var key = this.keys[this.state][code];
    if (key == 'escape') {
        if (typeof(dialog) != 'undefined')
            dialog.close();
    }
    else if (key == 'enter') {
        if (typeof(dialog) != 'undefined' && $('#dialogInput').val()) {
            var key = $('#dialog').find('.titlebar').html().substr(5).toLowerCase();
            save(key);
        }
    }
    else if (key == 'h')
        help();
}

//
//
//

function Poster() {
    var t = this;
    this.poster = $('#poster');
    this.poster.css('background', 'url(/' + video.id + '/poster.264.jpg)');
    this.frame = $('#frame');
    var height = video.height * 264 / 128;
    var top = (264 - height) / 2;
    this.frame.css('top', top + 'px');
    this.frame.css('height', height + 'px');
    this.timecode = $('#timecode');
    top = top + height + Math.floor((264 - top - height) / 2) - 8;
    // top = 240;
    this.timecode.css('top', top + 'px');
    this.interface = $('#interface');
    this.interface.addClass('enabled');
    this.interface.mouseover(function() { t.mouseover() });
    this.interface.mousemove(function(event) { t.mousemove(event) });
    this.interface.mouseout(function() { t.mouseout() });
}
Poster.prototype.mouseover = function() {
    this.poster.css('background', 'rgb(32, 32, 32)');
    //this.poster.css('background', 'rgb(48, 48, 48)');
    this.frame.show();
}
Poster.prototype.mousemove = function(event) {
    var x = Math.floor(event.clientX - $('#poster').offset().left);
    var timecode = getTimecode(x * imageStep);
    this.frame.attr('src', images[x].src);
    this.timecode.html(timecode);
    this.interface.unbind('click');
    this.interface.click(function() { document.location.href = '/' + video.id + '/' + timecode });
    //$('#menuBottom').html(x + ' ' + imageStep + ' ' + timecode);
}
Poster.prototype.mouseout = function() {
    this.interface.unbind('click');
    this.timecode.html('');
    this.frame.hide();
    this.poster.css('background', 'url(/' + video.id + '/poster.264.jpg)');
}

//
//
//

function Cell(parent, name, content, width) {
    this.parent = parent;
    this.name = name;
    this.content = content;
    this.width = width;
}
Cell.prototype.load = function() {
    var element = $(parseTemplate(htmlCell, {'name': this.name}));
    element.find('.border').addClass('cell' + this.width)
    element.find('#' + this.name + 'Content').html(this.content);
    this.parent.append(element);
}
Cell.prototype.update = function() {
    this.content = compose(this.name);
    $('#' + this.name + 'Content').html(this.content);
}

//
//
//

function compose(name) {
    var content = $('<div></div>');
    if (name == 'file') {
        var value = [
            (video.width * 5) + 'x' + (video.height * 5) + ' px',
            Math.round(video.duration / 60000) + ' min',
            formatBytes(video.size)
        ];
        content.html(value.join(' &ndash; '));
    }
    else if (name == 'info') {
        var element = $('<div></div>');
        if (video.director)
            element.html('<span class="bold">Director:</span> ' + video.director);
        else
            element.html('<span class="bold">Director:</span> <span class="italic">unknown</span>');
        content.append(element);
        element = $('<div></div>');
        if (video.source)
            element.html('<span class="bold">Source:</span> ' + video.source);
        else
            element.html('<span class="bold">Source:</span> <span class="italic">unknown</span>');
        content.append(element);
        element = $('<div></div>');
        if (video.collection) {
            if (video.mail)
                element.html('<span class="bold">Collection:</span> <a href="mailto:' + video.mail + '">' + video.collection + '</a>');
            else
                element.html('<span class="bold">Collection:</span> ' + video.collection);
        }
        else
            element.html('<span class="bold">Collection:</span> <span class="italic">unknown</span>');
        content.append(element);

        element = $('<div></div>');
        if (video.languages) {
          var languages = [];
          $(video.languages).each(function() {
            var q = encodeURIComponent(this);
            languages[languages.length] = '<a href="/?f=language&amp;q=' + q + '">' + this + '</a>';
          });
          if (languages.length > 0) {
            var title = 'Language';
            if (languages.length > 1)
              title = 'Languages';
            element.html('<span class="bold">' + title +':</span> ' + languages.join(', '));
            content.append(element);
          }
        }

        element = $('<div></div>');
        if (video.categories) {
          var categories = [];
          $(video.categories).each(function() {
            var q = encodeURIComponent(this);
            categories[categories.length] = '<a href="/?f=category&amp;q=' + q + '">' + this + '</a>';
          });
          if (categories.length > 0) {
            var title = 'Category';
            if (languages.length > 1)
              title = 'Categories';
            element.html('<span class="bold">' + title + ':</span> ' + categories.join(', '));
            content.append(element);
          }
        }

        element = $('<div></div>');
        element.html('<span class="bold">Contributor:</span> ' + video.creator);
        content.append(element);
        element = $('<div></div>');
        // /*
        var date = new Date();
        date.setTime(video.created * 1000);
        element.html('<span class="bold">Created:</span> ' + date.format('%F %T'));
        content.append(element);
        // */
        element = $('<div></div>');
        var date = new Date();
        date.setTime(video.published * 1000);
        element.html('<span class="bold">Published:</span> ' + date.format('%F %T'));
        content.append(element);
        element = $('<div></div>');
        var date = new Date();
        date.setTime(video.modified * 1000);
        element.html('<span class="bold">Last Modified:</span> ' + date.format('%F %T'));
        content.append(element);
    }
    else if (name == 'text') {
        var element = $('<div></div>');
        element.attr('id', 'textCellTitle')
        element.html(video.title);
        content.append(element);
        element = $('<div></div>');
        element.attr('id', 'textCellInfo');
        if (video.date_html == 'unknown') {
            video.date_html = 'unknown date';
        }
        if (video.location)
            element.html(video.location + ', ' + video.date_html);
        else
            element.html(video.date_html);
        content.append(element);
        element = $('<div></div>');
        if (video.description_html)
            element.html(video.description_html);
        else {
            element.addClass('disabled');
            element.html('No Description')
        }
        content.append(element);
    }
    else if (name == 'edit') {
        var key = ['title', 'location', 'date', 'description', 'director', 'source', 'collection', 'mail', 'categories', 'languages'];
        var html = '<div id="elementSelectEdit" class="element264 elementSelect264 enabled">Edit...</div>'
        html += '<select id="selectEdit" class="element264 enabled transparent" style="margin-left: -264px" onChange="edit()">'
        html += '<option value="edit">Edit...</option>';
        for (var k in key) {
            var v = key[k];
            html += '<option value="' + v + '">Edit ' + v.capitalize() + '...</option>';
            /*
            var element = $('<div></div>');
            element.attr('id', 'edit' + v.capitalize());
            element.addClass('element');
            element.addClass('elementButton');
            element.html('Edit ' + v.capitalize());
            function func(v) {
                return function() { edit(v) };
            }
            element.click(func(v));
            content.append(element);
            */
        }
        html += '</select>';
        content.html(html)
    }
    return content;
}

//
//
//

function download() {
    document.location.href = '/' + video.id + '/download';
}

function help() {
    // fixme: dialog formats button float:right, so buttons have to be defined in reverse order. stupid.
    cache.get('/static/templates/help.info.html', function(html) {
        dialog = new Dialog('Help', html, [
            ['Close', function() { dialog.close() }],
            ['FAQ: PGL', function() { document.location.href = '/faq#PGL' }],
            ['FAQ: Ogg Theora', function() { document.location.href = '/faq#OggTheora' }],
            ['FAQ: BitTorrent', function() { document.location.href = '/faq#BitTorrent' }],
        ], 552, 276);
        dialog.load();
    });
}

function edit() {
    var key = $('#selectEdit').val();
    if (key == 'edit') return;
    $('#selectEdit').val('edit');
    var val = video[key];
    if (key == 'categories' || key == 'languages') {
        val = val.join(', ');
    }
    if (key == 'description') {
        var element = $('<textarea></textarea>');
        var height = 278;
    } else if (key == 'categories' || key == 'languages') {
        var element = $('<input />');
        var height = 124;        
    } else {
        var element = $('<input />');
        var height = 100;
    }
    element.attr('id', 'dialogInput');
    element.val(val);
    dialog = new Dialog('Edit ' + key.capitalize(), element, [
        ['Save', function() { save(key) }],
        ['Undo', function() { undo(key) }],
        ['Cancel', function() { dialog.close() }]
    ], 416, height);
    dialog.load(function() {
        if (key == 'categories') {
            $.getJSON('/category/get', function(data) {
                var html = '<div class="enabled element264 elementSelect264">Add Category...</div>'
                html += '<select id="selectItem" class="element264 transparent" style="margin-left: -264px" onChange="addItem()">'
                html += '<option value="select">Add Category...</option>'
                for (var i in data.categories) {
                    html += '<option>' + data.categories[i] + '</option>'
                }
                html += '</select>';
                $('#dialogInput').css({
                    marginTop: '8px'
                });
                $('#dialogContent').prepend(html);
            });
        }
        else if (key == 'languages') {
            $.getJSON('/language/get', function(data) {
                var html = '<div class="enabled element264 elementSelect264">Add Language...</div>'
                html += '<select id="selectItem" class="element264 transparent" style="margin-left: -264px" onChange="addItem()">'
                html += '<option value="select">Add Language...</option>'
                for (var i in data.languages) {
                    html += '<option>' + data.languages[i] + '</option>'
                }
                html += '</select>';
                $('#dialogInput').css({
                    marginTop: '8px'
                });
                $('#dialogContent').prepend(html);
            });
        }
    });
}

function undo(key) {
    if (key == 'description')
        $('#dialogInput').val(encodeTags(video[key]));
    else
        $('#dialogInput').val(encodeQuotes(video[key]));
}

function save(key) {
    var value = $('#dialogInput').val();
    dialog.close();
    if (key == 'description')
        keyboard.setState(0);
    var parameters = {};
    parameters[key] = value;
    requests.add('/' + video.id + '/edit', parameters, saveCallback);
}

function saveCallback(result) {
    // fixme: doesn't check for failure
    var key = ['title', 'location', 'date', 'description', 'director', 'source', 'collection', 'mail', 'categories', 'languages'];
    for (var k in key) {
        var v = key[k];
        video[v] = result.video[v];
        if (result.video[v + '_html'])
            video[v + '_html'] = result.video[v + '_html'];
    }
    infoCell.update();
    textCell.update();
}

function addItem(category) {
    var newVal = $('#selectItem').val();
    var oldVal = $('#dialogInput').val();
    if (oldVal) {
        var separator = ', ';
    } else {
        var separator = '';
    }
    $('#dialogInput').val(oldVal + separator + newVal);
    $('#selectItem').val('select');
}
