/* Game Manager
 * Glorified list of sockets
 * Manages clients showing specific games
 */
 
var proto = GameManager.prototype;

function GameManager(apiConnector, dbConnector) {
    this._game_sockets = {};
    this._apiConnector = apiConnector;
    this._dbConnector = dbConnector;
    this._playerData = {};
    this._lineupData = {};
    this._startingLineups = {}; //game ids -> qtrs -> teams -> players
}

proto.startPolling = function(interval) {
    setInterval(this.poll.bind(this), interval);
}

proto.getGameIds = function() {
    return Object.keys(this._game_sockets);
}

proto.addSocket = function(new_socket, gameid) {
    if (!gameid) {
        console.error("tried to add game socket with no gameid");
        return;
    }
    if (!this._game_sockets[gameid]) {
        this._game_sockets[gameid] = [];
    }
    this._game_sockets[gameid].push(new_socket);
    
    //check if there is a last gameupdate, if so emit it immediately 
    //to prevent delay when first opening a game
    
    if (this._playerData[gameid]) {
        new_socket.emit('playerdata', this._playerData[gameid]);
    }
    if (this._lineupData[gameid]) {
        new_socket.emit('lineupdata', this._lineupData[gameid]);
    }
    if (this._startingLineups[gameid]) {
        new_socket.emit('startinglineupdata', this._startingLineups[gameid]);
    }
};

proto.removeSocket = function(socket) {
    this._game_sockets[socket.identification.gameid].splice(
        this._game_sockets[socket.identification.gameid].indexOf(socket), 1);
}

//private
proto.sendGameupdate = function(gameid, gameupdate) {
    if (this._game_sockets[gameid]) {
        this._game_sockets[gameid].forEach(function(socket) {
            socket.emit("gameupdate", gameupdate)
        })    
    }
}

//private
proto.getPlayerDataIfNecessary = function(gameid, data) {
    if (!this._playerData[gameid]) {
        console.log("no player data, retrieving now")
        this.retrievePlayerData(data, (function(err, data) {
            if (err) console.error(err);
            else {
                console.log("retrieved player data: " + data);
                this._playerData[gameid] = data;
                
                this._game_sockets[gameid].forEach(function(socket) {
                    socket.emit("playerdata", data)
                })   
            }
        }).bind(this));
    }
}

proto.sendLineupData = function(gameid, lineupdata) {
     if (this._game_sockets[gameid]) {
        this._game_sockets[gameid].forEach(function(socket) {
            socket.emit("lineupdata", lineupdata)
        })    
    }
}

proto.sendStartingLineupData = function(gameid) {
    var startingLineups = this._startingLineups[gameid];
    if (this._game_sockets[gameid]) {
        this._game_sockets[gameid].forEach(function(socket) {
            socket.emit("startinglineupdata", startingLineups)
        })
    }
}

proto.getLineupDataIfNecessary = function(gameid, data) {
    if (!this._lineupData[gameid]) {
        console.log("no lineup data, retriveing now");
        
        this.retrieveLineupData(data, (function(err, data) {
            if (err) console.error(err);
            else {
                console.log("retrieved lineup data: " , data.team);
                if (!this._lineupData[gameid]) this._lineupData[gameid] = [];
                this._lineupData[gameid].push(data);
                
                this.sendLineupData(gameid, data);
            }
        }).bind(this))
    }
}

proto.getPeriod = function(gameupdate) {
    return gameupdate['apiResults'][0]['league']['season']['eventType'][0]['events'][0]['eventStatus'].period;
}

proto.storeStartingLineupsIfNecessary = function(gameid, gameupdate) {
    var period = gameupdate['apiResults'][0]['league']['season']['eventType'][0]['events'][0]['eventStatus'].period;
    var startingLineups = this.getOnCourtPlayers(gameupdate);
    
    if (!this._startingLineups[gameid]) {
        this._startingLineups[gameid] = [];
    }
    
    if (!startingLineups) return;
    
    if (!this._startingLineups[gameid][period]) {
        this._startingLineups[gameid][period] = startingLineups;
        console.log(this._startingLineups);
        this.sendStartingLineupData(gameid);
    }
}

proto.poll = function() {
    
    var gameids = this.getGameIds();
    console.log("GameManager Polling these games: ", gameids);
    
    for (var gameid_key in gameids) {
        var gameid = gameids[gameid_key];
        
        this._apiConnector.poll(gameid, (function(err, data) {
            if (err) console.error(err);
            else {
                data = JSON.parse(data);
                this.storeStartingLineupsIfNecessary(gameid, data);
                this.sendGameupdate(gameid, data);
                this.getPlayerDataIfNecessary(gameid, data);
                this.getLineupDataIfNecessary(gameid, data);
            }
        }).bind(this));     
    }
};

proto.getOnCourtPlayers = function(gameupdate) {
    var boxscores = gameupdate['apiResults'][0]['league']['season']['eventType'][0]['events'][0]['boxscores'];
    if (!boxscores[0]) {
        console.log("no boxscore yet", boxscores);
        return;
    }
    var team1_players = []
    for (var player_key in boxscores[0].playerstats) {
        var player = boxscores[0].playerstats[player_key]
    
        if (player.onCourt == "true") {
            team1_players.push(player.player)
        }
    }
    
    var team2_players = [];
    for (var player_key in boxscores[1].playerstats) {
        var player = boxscores[1].playerstats[player_key]
    
        if (player.onCourt == "true") {
            team2_players.push(player.player)
        }
    }
    return [team1_players, team2_players];
}

proto.getKeyFromPlayer = function(player) {
  return ""+player.player.firstName + " " + player.player.lastName;
}

proto.getPlayerKeysFromGameUpdate = function(gameupdate) {
    if (!gameupdate['apiResults']) {
        console.log("game hasn't started yet");
        return;
    }
    var gameData = gameupdate['apiResults'][0]['league']['season']['eventType'][0]['events'][0];
    if (!gameData.boxscores[0]) {
        console.log("no box scores yet")
        return;
    }
    var team1 = gameData['boxscores'][0].playerstats;
    var team2 = gameData['boxscores'][1].playerstats;
    var playerKeys = [];
    for (var player in team1) {
        playerKeys.push(this.getKeyFromPlayer(team1[player]));
    }
    for (var player in team2) {
        playerKeys.push(this.getKeyFromPlayer(team2[player]));
    }
    
    return playerKeys;
}

proto.retrievePlayerData = function(gameupdate, callback) {
    var playerKeys = this.getPlayerKeysFromGameUpdate(gameupdate);
    if (!playerKeys) return;
    this._dbConnector.getPlayerData(playerKeys, callback);
}

proto.retrieveLineupData = function(gameupdate, callback) {
    this._dbConnector.getLineupDataForTeam("Golden State Warriors", callback);
    this._dbConnector.getLineupDataForTeam("Oklahoma City Thunder", callback);
    
}


module.exports = GameManager;

// a way to receive schedule updates
// manage games that are pending and games that are live
// set up clients with static data
// forward dynamic data to clients
// * including formatting pbp for backtracking vis