//global url thing, you know
var jsonlobbyURL = "http://www.deltastrike.org:5080/ds2GameApplication/jsonlobby";


// global var games
var games = Array(), openGames = false, startedGames = false;
var gamesList = null;
var mapsScenariosList = null;


// form elements for error checking
var createGameElements = {
  "#gameName" : {"errorMessage" : "Please enter a name for the game."},
  "#scenarioID" : {"errorMessage" : "Please choose a scenario."},
  "#mapID" : {"errorMessage" : "Please choose a map."}
};

function hasValue(jQueryObject){
  return !(!jQueryObject.val()||!jQueryObject.val().length||!jQueryObject.val().length>0);
}

function toggleFormElementsEnabled(elements, enabled){
  for(elementID in elements){
    if(enabled){
      $(elementID).removeAttr("disabled");
    }else{
      $(elementID).attr("disabled", "disabled");
    }
  }
}

function checkFormElements(elements){
  for(elementID in elements){
    var element = $(elementID);
    if(!hasValue(element)){
      alert(elements[elementID]["errorMessage"]);
      return false;
    }
  }
  return true;
}

function checkAll(){
  return (checkFormElements(createGameElements));
}

function createGame(){
  if(!checkAll()){
    return false;
  }
  return true;
}

function updateGamesList(){
  startedGames = openGames = false;
  $.getJSON("proxy/proxy.php?proxy_url=" + escape(jsonlobbyURL + "?listAllGames"), function(games){
    gamesList.startUpdate();
	  for(var gameName in games){
	    gamesList.addGame(games[gameName]["RoomID"], games[gameName]);
	  }
	  gamesList.endUpdate();
 	});
 	setTimeout("updateGamesList()", 5000);
}

function loadMapsScenariosList(fn){
  $.getJSON("proxy/proxy.php?proxy_url=" + escape(jsonlobbyURL + "?listMapsAndScenarios"), function(mapsScenarios){
    mapsScenariosList.addMapsScenarios(mapsScenarios);
    if(fn){
      fn();
    }
  });
}

$(function(){
  //menu animations: ON CLICK
  $("#men a").click(function(){
    $("#men a[class=active]").animate({ backgroundColor: "#CCC" }, "fast").removeClass("active");
    $(this).addClass("active");
  });
  //menu animations: HOVER
  $("#men a").hover(function(){
    if(!$(this).hasClass("active")){
  	  $(this).animate({ backgroundColor: "#369" }, "fast");
  	}
  }, function(){
    if(!$(this).hasClass("active")){
  	  $(this).animate({ backgroundColor: "#CCC" }, "fast");
  	}
  });
  $("#men li.subMenu").hover(function(){
    $(this).find("ul").show().find("a");
  }, function(){
    $(this).find("ul").hide();
  });
  //user area
  $("#userArea .bg").css('opacity', 0.5).corner("br");

  if(gamesListActive){
    $("#createGameForm").submit(createGame);
    
    mapsScenariosList = new MapsScenariosList($("#mapID"), $("#scenarioID"), $("#gameInfo"));
    loadMapsScenariosList(function(){
      gamesList = new GamesList($("#openGames"), $("#startedGames"));
      updateGamesList();
    });
  }
});

function GameView(container){
  this.container = container;

  this.element = $("<li>");
  this.join = $("<a>").attr({"href" : "#", "target" : "__deltastrike"});
  this.name = $("<span>").addClass("gameName");
  this.playerNames = $("<ul>");
  this.players = $("<div>").addClass("players");
  this.gameInfo = $("<div>").addClass("gameInfo");;
  //to be cloned:
  this.playerOnline = $("<span>").addClass("player").addClass("online").html("&nbsp;");
  this.playerOffline = $("<span>").addClass("player").addClass("offline").html("&nbsp;");
  this.playerName = $("<li>").addClass("player");
  this.joinEnabled = true;
  
  this.element.append(this.id).append(this.join.append(this.name)).append(this.players).append(this.playerNames);
  
  this.init = function(gameID, gameName, gameInfo){
    if(!gameID){
      alert("invalid gameID! " + gameID);
    }
    this.setGameID(gameID);
    this.setGameName(gameName);
    this.setMaxPlayers(gameInfo["MapMaxPlayers"]);

    this.playerNames.attr("id", "g" + gameID);
    this.players.attr("id", "p" + gameID).click(function(){
      $("#g" + $(this).attr("id").substr(1)).toggle();
    });
    
    this.gameInfo
      .append($("<span>").text("Map: "))
      .append($("<em>").text(gameInfo["MapName"]))
      .append($("<br>"))
      .append($("<span>").text("Scenario: "))
      .append($("<em>").text(gameInfo["ScenarioName"]))
      .append($("<span>").text(" (" + gameInfo["ScenarioInfo"] + ")"));
    this.element.append(this.gameInfo);

    this.join.tooltip({ fade: 100, showURL: false, bodyHandler: function(){ return $(this).parent().find("div.gameInfo").html(); }});
    this.join.attr("name", gameID);
    this.join.click(function(){
      $("#gameID").val(this.name);
      $("#joinGameForm").submit();
      return false;
    });
  }
  
  this.setGameID = function(gameID){
    this.gameID = gameID;
  }
  
  this.setGameName = function(gameName){
    this.name.text(gameName);
  }
  
  this.setMaxPlayers = function(maxPlayers){
    if(isNaN(maxPlayers)){
      alert("setMaxPlayers: not a number [" + maxPlayers + "]");
      return;
    }
    for(var i = 0; i < maxPlayers; ++i){
      this.players.append(this.playerOffline.clone(true));
    }
  }
  
  this.addPlayer = function(playerName){
    this.players.children(":last").remove();
    this.players.prepend(this.playerOnline.clone(true));
    this.playerNames.append(this.playerName.clone().attr("id", playerName).text(playerName));
  }
  
  this.removePlayer = function(playerName){
    this.players.children(":first").remove();
    this.players.append(this.playerOffline.clone(true));
    this.playerNames.find("li#" + playerName).remove();
  }
  
  this.setContainer = function(container){
    if(this.container != container){
      this.container.remove(this.element);
      this.container = container;
      this.display();
    }
  }
  
  this.remove = function(){
    this.element.remove();
  }
  
  this.display = function(){
    this.container.append(this.element);
  }
  
  this.toggleJoin = function(enabled){
    if(this.joinEnabled == enabled){
      return;
    }
    this.joinEnabled = enabled;
    
    if(!enabled){
      this.name.remove();
      this.name.insertAfter(this.join);
      this.join.remove();
    }else{
      this.join.insertAfter(this.name);
      this.join.append(this.name);
    }
  }
}

function Game(gameID, game, view){
  this.id = gameID;
  this.mapID = game["MapID"];
  this.scenarioID = game["ScenarioID"];
  this.roomID = game["RoomID"];
  this.roomName = game["RoomName"];
  this.players = (game["Players"] ? game["Players"].concat() : []);
  this.gameStarted = (game["GameStarted"] == "true");
  this.view = view;
  this.gameInfo = null;
  
  this.update = function(game){
    this.gameStarted = (game["GameStarted"] == "true");

    var players = game["Players"];
    if(!players){
    	return;
    }
    var oldPlayers = this.players.concat()
    var newPlayers = players.concat();
    this.players = players.concat();
    
    for(var j = 0; j < newPlayers.length; ++j){
      for(var i = 0; i < oldPlayers.length; ++i){
        if(newPlayers[j] == oldPlayers[i]){ //player already there
          newPlayers.splice(j--, 1);
          oldPlayers.splice(i, 1);
          break;
        }
      }
    }
    for(var i = 0; i < newPlayers.length; ++i){
      this.view.addPlayer(newPlayers[i]);
    }
    for(var i = 0; i < oldPlayers.length; ++i){
      this.view.removePlayer(oldPlayers[i]);
    }
    
    this.toggleJoin();
  }
  
  this.getGameInfo = function(){
    if(this.gameInfo){
      return this.gameInfo;
    }
    var map = mapsScenariosList.getMapByID(this.mapID);
    if(!map){
      alert("could not get map with id: " + this.mapID);
      return null;
    }
    var scenario = mapsScenariosList.getScenarioByID(this.scenarioID);
    if(!scenario){
      alert("could not get scenario with id: " + this.scenarioID);
      return null;
    }
    this.gameInfo = {"MapName": map["MapName"], "MapMaxPlayers": map["MapMaxPlayers"] , "ScenarioName": scenario["ScenarioName"], "ScenarioInfo": scenario["ScenarioInfo"]};
    return this.gameInfo;
  }
  
  this.isStarted = function(){
    return this.gameStarted;
  }
  
  this.remove = function(){
    this.view.remove();
  }
  
  this.display = function(){
    this.view.init(this.id, this.roomName, this.getGameInfo());
    for(var i = 0; i < this.players.length; ++i){
      this.view.addPlayer(this.players[i]);
    }
    view.display();
  }
  
  this.toggleJoin = function(){
    this.view.toggleJoin(this.players.length < this.getGameInfo()["MapMaxPlayers"] && !this.gameStarted);
  }
  
  this.getID = function(){
    return this.id;
  }
  
  this.getView = function(){
    return this.view;
  }

  this.toggleJoin();
}

function GamesList(openGames, startedGames){
  this.lastGames = Array();
  this.games = Array();
  this.openGames = openGames;
  this.startedGames = startedGames;
  this.openGamesCount = 0;
  this.startedGamesCount = 0;
  
  this.noneOpenGames = $("<li>").text("None");
  this.noneStartedGames = this.noneOpenGames.clone(true);
  
  this.getContainer = function(gameStarted){
    return (gameStarted ? startedGames : openGames);
  }
  
  this.startUpdate = function(){
    this.openGamesCount = this.startedGamesCount = 0;
    
    this.lastGames.splice(0, this.lastGames.length);
    for(var gameID in this.games){
      var game = this.games[gameID];
      if(game){
        this.lastGames.push(game.getID());
      }
    }
  }
  
  this.endUpdate = function(){
    for(var i = 0; i < this.lastGames.length; ++i){
      this.games[this.lastGames[i]].remove();
      delete this.games[this.lastGames[i]];
    }
    if(this.startedGamesCount <= 0){
      this.startedGames.append(this.noneStartedGames);
    }else{
      this.noneStartedGames.remove();
    }
    if(this.openGamesCount <= 0){
      this.openGames.append(this.noneOpenGames);
    }else{
      this.noneOpenGames.remove();
    }
  }
  
  this.addGame = function(gameID, game){
    for(var i = 0; i < this.lastGames.length; ++i){
      if(this.lastGames[i] == gameID){
        this.lastGames.splice(i, 1);
        break;
      }
    }
    var gameStarted = (game["GameStarted"] == "true");
    gameStarted ? ++this.startedGamesCount : ++this.openGamesCount;
    
    if(this.games[gameID]){
      if(this.games[gameID].isStarted() != gameStarted){ //set new container
        this.games[gameID].getView().setContainer(this.getContainer(gameStarted));
      }
      this.games[gameID].update(game);
    }else{
      //request new view and add to game
      var container = this.getContainer(gameStarted);
      this.games[gameID] = new Game(gameID, game, new GameView(this.getContainer(gameStarted)));
      this.games[gameID].display();
    }
  }
}

function MapsScenariosList(mapsContainer, scenariosContainer, gameInfoContainer){
  this.mapsContainer = mapsContainer;
  this.scenariosContainer = scenariosContainer;
  this.gameInfoContainer = gameInfoContainer;
  this.maps = null;
  this.scenarios = null;
  
  this.option = $("<option>");
  
  this.setMaps = function(maps){
  }
  
  this.setScenarios = function(scenarios){
  }

  this.addMapsScenarios = function(mapsScenarios){
    this.maps = mapsScenarios["maps"];
    this.scenarios = mapsScenarios["scenarios"];

    var count = 0;
    for(var mapID in this.maps){
      ++count;
      var newOption = this.option.clone(true);
      newOption.attr("value", mapID).text(this.maps[mapID]["MapName"]);
      this.mapsContainer.append(newOption);
    }
    this.mapsContainer.get(0).options.selectedIndex = -1;
    this.mapsContainer.attr("size", count);
    this.mapsContainer.click(function(){
      var mapIcon = mapsScenariosList.getMapIcon(this.options[this.options.selectedIndex].value);
      var mapName = mapsScenariosList.getMapName(this.options[this.options.selectedIndex].value);
      if(mapIcon && mapName){
        $("#gameInfo td.mapIcon img").attr({"src": "http://play.deltastrike.org/xml/" + mapIcon, "alt": mapName});
        $("#gameInfo td.mapName").text(mapName);
      }
    });

    count = 0;
    for(var scenarioID in this.scenarios){
      ++count;
      var newOption = this.option.clone(true);
      newOption.attr("value", scenarioID).text(this.scenarios[scenarioID]["ScenarioName"]);
      this.scenariosContainer.append(newOption);
    }
    this.scenariosContainer.get(0).options.selectedIndex = -1;
    this.scenariosContainer.attr("size", count);
    this.scenariosContainer.click(function(){
      var scenarioName = mapsScenariosList.getScenarioName(this.options[this.options.selectedIndex].value);
      var scenarioInfo = mapsScenariosList.getScenarioInfo(this.options[this.options.selectedIndex].value);
      if(scenarioName && scenarioInfo){
        $("#gameInfo td.scenario").html(scenarioName + "<br/><span>" + scenarioInfo + "</span>");
      }
    });
  }
  
  this.getScenarioByID = function(scenarioID){
    if(!this.scenarios || !this.scenarios[scenarioID]){
      return null;
    }
    return this.scenarios[scenarioID];
  }
  
  this.getScenarioName = function(scenarioID){
    if(!this.scenarios || !this.scenarios[scenarioID]){
      return null;
    }
    return this.scenarios[scenarioID]["ScenarioName"];
  }
  
  this.getScenarioInfo = function(scenarioID){
    if(!this.scenarios || !this.scenarios[scenarioID]){
      return null;
    }
    return this.scenarios[scenarioID]["ScenarioInfo"];
  }
 
  this.getMapByID = function(mapID){
    if(!this.maps || !this.maps[mapID]){
      return null;
    }
    return this.maps[mapID];  
  }
  
  this.getMapMaxPlayers = function(mapID){
    if(!this.maps || !this.maps[mapID]){
      return null;
    }
    return this.maps[mapID]["MapMaxPlayers"];
  }
  
  this.getMapIcon = function(mapID){
    if(!this.maps || !this.maps[mapID]){
      return null;
    }
    return this.maps[mapID]["MapIcon"];
  }
  
  this.getMapName = function(mapID){
    if(!this.maps || !this.maps[mapID]){
      return null;
    }
    return this.maps[mapID]["MapName"];
  }
}
