/**
 * @author Per Øyvind
 *
 */

if(String(document.location).match(/import\.php/)) {

    //* Import Scripts
    tumbler.addPlayer = function(name, raidAtt, standbyAtt)
    {
        standbyAtt = standbyAtt || 0;
        name = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();

        // TODO: Throw error that char already exists.
        if(tumbler.raid.characters[name]) return;

        tumbler.raid.characters[name] = {name: name, standby: standbyAtt, raid: raidAtt};

        tumbler.refreshPlayers();
    }

    tumbler.refreshPlayers = function()
    {
        var ul = $('#attendanceList').clone(true).empty();
        var players = new Array();

        for(index in tumbler.raid.characters)
        {
            players.push(tumbler.raid.characters[index].name);
        }
        players.sort();

        var select = document.getElementById('itemLooter');
        select.options.length = 0;

        for(var i=0, player; player = tumbler.raid.characters[players[i]]; i++) {
            var li = document.createElement('li');
            li.innerHTML = player.name + '<span class="playerAttendance">' + Math.round(player.raid + player.standby) + '%</span>';

            if(!tumbler.characters[player.name])
            {
                tumbler.raid.characters[player.name].newMember = true;
                li.className = 'newMember';
            }

            if(player.standby > player.raid)
            {
                $(li).addClass('standby');
            }
            else if(player.standby > 0)
            {
                $(li).addClass('hybrid');
            }

            $(ul).append(li);
            select.appendChild(new Option(player.name, player.name));
        };

        $('#attendanceList').replaceWith(ul);
    }

    tumbler.removePlayer = function()
    {
        delete(tumbler.raid.characters[selectedPlayer.firstChild.nodeValue]);
        $(selectedPlayer).remove();

        $('#editPlayer').hide();
        // TODO: Fix items related to that char
    }

    // Fetches data for the player and displays the editing box
    tumbler.showPlayer = function(e)
    {
        var target = e.target || e.srcElement;
        if(target.tagName != 'UL')
        {
            var node = (target.tagName == 'LI') ? target : target.parentNode;
            selectedPlayer = node;

            var player = tumbler.raid.characters[node.firstChild.nodeValue];
            $('#raidAttInput').val(player.raid);
            $('#standbyAttInput').val(player.standby);
            $('#savePlayerChange').html(player.newMember ? 'Add' : 'Ok');

            var position = $(target).position();
            $('#editPlayer').css({display: 'block', left: position.left, top: position.top});
        }
    }

    tumbler.editPlayer = function(e)
    {
        var raid = Math.min(parseInt(document.getElementById('raidAttInput').value), 100);
        var standby = Math.min(parseInt(document.getElementById('standbyAttInput').value), 100);
        if(raid+standby > 100)
        {
            if(raid >= standby) raid = 100 - standby;
            else standby = 100 - raid;
        }

        var player = tumbler.raid.characters[selectedPlayer.firstChild.nodeValue];
        var targetList;
        if(raid == 0 && standby == 0)
        {
            removePlayer();
            return;
        }
        else if(player.raid > 0 && raid == 0)
        {
            targetList = document.getElementById('standbyList');
        }
        else if(player.raid == 0 && raid > 0)
        {
            targetList = document.getElementById('attendantList');
        }

        // Add player to db if he's new
        if(player.newMember)
        {
            var nodeCopy = selectedPlayer;
            $.post('json/post.php', {type: "create-character", name: player.name},
            function(json) {
                if(json.success)
                {
                    nodeCopy.className = '';
                    tumbler.raid.characters[nodeCopy.firstChild.nodeValue].newMember = false;
                } else {
                    alert('WTF? Something went wrong.');
                }
            }, 'json');
        }

        // Move the player to the other list if necessary
        if(targetList)
        {
            var name = selectedPlayer.firstChild.nodeValue;
            var lis = targetList.getElementsByTagName('li');
            if(lis.length == 0)
            {
                targetList.appendChild(selectedPlayer);
            }
            else
            {
                for(var i=0; i < lis.length; i++)
                {
                    if(name < lis[i].firstChild.nodeValue)
                    {
                        targetList.insertBefore(selectedPlayer, lis[i]);
                        break;
                    }
                    targetList.appendChild(selectedPlayer);
                }
            }
        }

        player.standby = standby;
        player.raid = raid;
        $('span', selectedPlayer).html(raid+standby + '%');

        $('#editPlayer').hide();
    }

    tumbler.addBoss = function(name, time)
    {
        var bossTime = time ? padZero(time.getHours()) + ':' + padZero(time.getMinutes()) : '';

        var node = document.createElement('div');
        node.className = 'boss';
        node.id = 'boss' + tumbler.raid.bosses.length;
        node.innerHTML = [
        '<select class="bossSelect"></select>',
	    'Time: <input maxlength="5" size="4" value="' + bossTime + '"></input>',
        '<input type="checkbox" class="wipenight" /><input type="text" class="wipeValue" />',
        '<button type="button" class="removeBoss">Remove</button>',
	    '<div class="bossLoot">',
	    '   <ul class="lootList"></ul>',
	    '   <input class="Add" type="text"></input>',
	    '   <button class="addLoot">Add</button>',
	    '</div>'].join('\n');

        var select = node.getElementsByTagName('select')[0];
        var option = new Option('Select boss...', 0, true, true);
        option.disabled = true;
        select.appendChild(option);

        var bossid = null;
        var number;
        for(var i = 0, zone; zone = tumbler.data.zones[i]; i++)
        {
            var group = document.createElement('optgroup');
            group.label = zone.name;
            for(var p=0, boss; boss = tumbler.data.bosses[zone.bosses[p]]; p++)
            {
                group.appendChild(new Option(boss, zone.bosses[p]));
                if(boss == name)
                {
                    number = select.options.length - 1 + group.childNodes.length;
                    bossid = zone.bosses[p];
                }
            }
            select.appendChild(group);
        }
        select.selectedIndex = number || 0;

        $('button.removeBoss', node).click(tumbler.removeBoss);

        $('.wipenight', node).change(function() {
            $(this).next().toggle();
        })

        // Add loot button hook, get name from input and pass to import function.
        $('.addLoot', node).click(function(){
            var input = $(this).prev();
            tumbler.addLoot(input.val(), parseInt(input.parent().parent().get(0).id.match(/[0-9]+/)));
            input.val('');
        });

        tumbler.raid.bosses.push({
            id: tumbler.raid.bosses.length,
            bossid: bossid,
            time: time ? (time.getTime() / 1000) : null,
            loot: []
        });
        $('#addBoss').before(node);

        return tumbler.raid.bosses.length - 1;
    }

    tumbler.removeBoss = function(e)
    {
        var target = e.target || e.srcElement;
        var node = target.parentNode;
        var bossid = parseInt(node.id.match(/[0-9]+/));

        delete(tumbler.raid.bosses[bossid])

        $('li', node).each(function() {
            var id = parseInt(this.id.match(/[0-9]+/));
            delete(tumbler.raid.loot[id]);
        });

        // Just in case
        $('#editLoot').hide();
        $('body').append(tumbler.tooltip).append($('#editLoot'));

        $(node).remove();
    }

    tumbler.addLoot = function(name, bossId, player)
    {
        name = trimWspace(name);
        if(name == '') return;

        player = player ? player : null;
        var ul;
        tumbler.raid.loot[tumbler.itemCount] = {id: tumbler.itemCount, player: player};
        if(typeof(bossId) != 'number')
        {
            ul = $('#trashlootList').get(0);
        }
        else
        {
            tumbler.raid.loot[tumbler.itemCount].bossid = bossId;
            tumbler.raid.bosses[bossId].loot.push(tumbler.itemCount);
            ul = $('#boss' + bossId + ' ul.lootList').get(0);
        }
        tumbler.itemCount++;

        var sanitizedName = name.replace(/[-,\' ]/gi, '');
        var li = document.createElement('li');

        player = player ? player : '';
        li.className = 'invalid item' + sanitizedName;
        li.id = 'loot' + (tumbler.itemCount - 1);
        li.innerHTML = '<span class="item q0">' + name + '</span><span class="looter">' + player + '</span>';
        $('.item', li).click(tumbler.showLoot);
        //TODO: Delegate on UL instead

        ul.appendChild(li);

        tumbler.fetchData('item', [name], tumbler.itemCount-1, function(id) { 
            var item = tumbler.cache.item[id];
            if(item) {
                $('.item', li).html(item.name).get(0).className = "item q" + item.colour;
                tumbler.raid.loot[id].itemid = item.id;
            }
        });
    }

    tumbler.showLoot = function(e)
    {
        var node = e.target || e.srcElement;
        while(!node.id.match(/loot\d/))
        {
            node = node.parentNode;
        }
        var item = tumbler.raid.loot[ parseInt(node.id.match(/[0-9]+/)) ];

        if(tumbler.editedLoot == item.id && $('#editLoot').css('display') == 'block') return;

        //$('#editLoot').insertBefore(node.firstChild);
        var position = $(node).position();
        $('#editLoot').show().css({display: 'block', left: position.left, top: position.top + 20});;

        if(item.player)
        {
            var select = document.getElementById('itemLooter');
            for(var i=1; i < select.options.length; i++)
            {
                if(item.player == select.options[i].value)
                {
                    select.selectedIndex = i;
                    break;
                }
            }
        }
        else
        {
            document.getElementById('itemLooter').selectedIndex = 0;
        }

        document.getElementById('itemOffspec').checked = item.offspec || false;
        document.getElementById('itemForced').checked = item.forced || false;

        if(item.itemid)
        {
                $('#itemHand').hide();
            switch(tumbler.cache.item[item.id].slot)
            {
                case 23:
                    item.weapon = 1;
                    break;
                case 22:
                    item.weapon = 1;
                    break;
                case 21:
                    item.weapon = 2;
                    break;
                case 17:
                    item.weapon = 3;
                    break;
                case 14:
                    item.weapon = 1;
                    break;
                case 13:
                    $('#itemHand').show();
                    $('#itemHand select').get(0).selectedIndex = Math.abs(3 - item.weapon) || 0;
                    break;
            }

            if(tumbler.cache.item[item.id].slot != 13)
            {
                $('#itemHand').hide();
            }
        }

        // Identifier of current/last edited item
        tumbler.editedLoot = item.id;
    }

    tumbler.editLoot = function()
    {
        var item = tumbler.raid.loot[tumbler.editedLoot];
        var oldPlayer = item.player;

        item.offspec = document.getElementById('itemOffspec').checked;
        item.forced = document.getElementById('itemForced').checked;
        item.player = document.getElementById('itemLooter').value;
        if($('#itemHand').is(':visible'))
        {
            item.weapon = $('#itemHand select').val();
        }

        if(item.player != 0 && oldPlayer != item.player)
        {
            $('#loot' + item.id + ' span.looter').text(item.player);
        }

        if(item.player != 0 && item.weapon != 0)
        {
            $('#loot' + tumbler.editedLoot).removeClass('invalid');
        }
        $('#editLoot').hide();
    }

    tumbler.removeLoot = function()
    {
        $('#editLoot').hide();
        $('#content').append(tumbler.tooltip).append($('#editLoot'));
        delete(tumbler.raid.loot[tumbler.editedLoot]);

        var node = document.getElementById('loot' + tumbler.editedLoot);
        node.parentNode.removeChild(node);
    }

    tumbler.updateRaidtimes = function()
    {
        // TODO: Remove players that end up with 0 attendance
        if(!tumbler.parse || !$('#raidStart').val().match(/[\d]{2}:[\d]{2}/) || !$('#raidEnd').val().match(/[\d]{2}:[\d]{2}/))
        {
            return;
        }

        $('#editPlayer').hide();

        var start = new Date($('#raidDate').val());
        start.setHours(parseInt($('#raidStart').val().slice(0, 2)));
        start.setMinutes(parseInt($('#raidStart').val().slice(3)));

        var end = new Date(start.getTime());
        end.setHours(parseInt($('#raidEnd').val().slice(0, 2)));
        end.setMinutes(parseInt($('#raidEnd').val().slice(3)));
        end.setSeconds(59, 999);

        end = end < start ? (end.getTime() + 86400000) / 1000 : end.getTime() / 1000;
        start = start.getTime() / 1000;

        var players = new Array();
        var rosterCount = 0;
        for(var i=0, roster; roster = tumbler.parse.rosters[i]; i++)
        {
            if(roster.time >= start && roster.time <= end)
            {
                rosterCount++;

                for(var p=0, player; player = roster.raid[p]; p++)
                {
                    if(!players[player]) players[player] = {raid: 0, standby: 0};
                    players[player].raid++;
                }
                for(var p=0, player; player = roster.standby[p]; p++)
                {
                    if(!players[player]) players[player] = {raid: 0, standby: 0};
                    players[player].standby++;
                }
            }
        }

        for(var i=0; i < players.length; i++)
        {
            if(players[i])
            {
                var name = tumbler.parse.players[i-1];
                var raid = players[i].raid * 100 / rosterCount;
                raid = raid % 5 > 0 ? raid + (5 - raid % 5) : raid;
                var standby = players[i].standby * 100 / rosterCount;
                standby = Math.min(100 - raid, (standby % 5 > 0) ? standby + (5 - standby % 5) : standby);
                if(tumbler.raid.characters[name])
                {
                    tumbler.raid.characters[name].raid = raid;
                    tumbler.raid.characters[name].standby = standby;
                }
            }
        }

        tumbler.refreshPlayers();
    }

    tumbler.submit = function()
    {
        //Validate input
        if($('.newChar').length > 0 ||
           $('.invalid').length > 0 ||
           !$('#raidDate').val().match(/\d{4}\/\d{2}\/\d{2}/) ||
           !$('#raidStart').val().match(/\d{2}:\d{2}/) ||
           !$('#raidEnd').val().match(/\d{2}:\d{2}/))
        {
            return alert('NEIN! Please check that all items/chars have been validated, and that times are correct.');
        }

        var start = new Date(Date.parse($('#raidDate').val()));
        start.setHours(parseInt($('#raidStart').val().substring(0,2)));
        start.setMinutes(parseInt($('#raidStart').val().slice(3)));
        var end = new Date(start.getTime());
        end.setHours(parseInt($('#raidEnd').val().substring(0,2)));
        end.setMinutes(parseInt($('#raidEnd').val().substring(3)));
        if(end.getTime() < start.getTime())
        {
            end.setDate(end.getDate() + 1);
        }

        tumbler.raid.start = start.getTime() / 1000;
        tumbler.raid.end = end.getTime() / 1000;
        if(trimWspace($('#raidNote').val()).length > 0)
        {
            tumbler.raid.note = trimWspace($('#raidNote').val());
        }

        $('#bossContainer .boss').each(function() {
            var time = new Date(start.getTime());
            time.setHours(parseInt($('input', this).val().slice(0,2)));
            time.setMinutes(parseInt($('input' ,this).val().slice(3)));
            if(time.getTime() < start.getTime())
            {
                time = time.getTime() + 86400000;
            }
            var id = parseInt($('select', this).val());

            var boss = tumbler.raid.bosses[parseInt(this.id.match(/[0-9]+/))];
            boss.bossid = id;
            boss.time = time/1000;

            boss.practice = $('.wipenight')[0].checked ? $('.wipeValue', this).val() : 0;

            for(var i=0, item; i < boss.loot.length; i++)
            {
                if(tumbler.raid.loot[boss.loot[i]])
                {
                    tumbler.raid.loot[boss.loot[i]].time = boss.time;
                }
            }
        });

        $.post('json/input.php', {raid: $.toJSON(tumbler.raid)}, function(data) {
            alert(data);
        });
    }

    tumbler.load = function(request, callback, param)
    {
        $.ajax({
            success: function(res){callback(res.data, param)},
            error: function(res){alert('fail :' + res.responseText + ' - ' + request)},
            dataType: 'json',
            url: 'json/get.php?request=' + request
        });
    }
}

tumbler.fetchData = function(request, params, id, callback)
{
    $.getJSON(
        'json/get.php'
        ,{request: request, params: params.join(',')}
        ,function(json) {
            tumbler.cache[request][id] = json.success ? json[request][0] : null;
            callback(id);
        }
    )
}

// remove multiple, leading or trailing spaces
// http://www.qodo.co.uk/blog/javascript-trim-leading-and-trailing-spaces/
function trimWspace(s)
{
    s = s.replace(/(^\s*)|(\s*$)/gi,"");
    s = s.replace(/[ ]{2,}/gi," ");
    s = s.replace(/\n /,"\n");
    return s;
}

// Object dumper, for debugging stuff
// Scott Van Vliet - http://weblogs.asp.net/skillet/archive/2006/03/23/440940.aspx
function dumpObj(obj, name, indent, depth) {
          var MAX_DUMP_DEPTH = 10;
      if (depth > MAX_DUMP_DEPTH) {
             return indent + name + ": <Maximum Depth Reached>\n";
      }

      if (typeof obj == "object") {
             var child = null;
             var output = indent + name + "\n";
             indent += "\t";
             for (var item in obj)
             {
                   try {
                          child = obj[item];
                   } catch (e) {
                          child = "<Unable to Evaluate>";
                   }
                   if (typeof child == "object") {
                          output += dumpObj(child, item, indent, depth + 1);
                   } else {
                          output += indent + item + ": " + child + "\n";
                   }
             }
             return output;
      } else {
             return obj;
      }
}

function padZero(paddee)
{
    if(paddee < 10) paddee = String('0' + paddee);
       return paddee;
}


// http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
if (!Array.prototype.map)
{
  Array.prototype.map = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

    return res;
  };
}
// http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter
if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}
// http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/forEach
if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}

function sprintf(format)
{
    for(var i=1; arguments.length > i; i++)
    {
        format = format.replace('%s', arguments[i]);
    }

    return format;
}
_s = sprintf;
