<?php

// Database for myChess
// ````````````````````

namespace {
	require_once 'common.php';
}

namespace DB {
	$db = new \PDO('sqlite:'.DB_PATH);	
	ValidateSchema();

	// Database functions

	function ValidateSchema() {
		global $db;
		$db->query('
			CREATE TABLE IF NOT EXISTS boards (
				id    INTEGER PRIMARY KEY,
				game  INTEGER,
				time  INTEGER,
				turn  INTEGER,
				move  TEXT,
				board TEXT
			);
		');
		$db->query('
			CREATE TABLE IF NOT EXISTS chat (
				id      INTEGER PRIMARY KEY,
				game    INTEGER,
				time    INTEGER,
				player  INTEGER,
				message TEXT
			);
		');
		$db->query('
			CREATE TABLE IF NOT EXISTS games (
				id       INTEGER PRIMARY KEY,
				name1    TEXT,
				name2    TEXT,
				email1   TEXT,
				email2   TEXT,
				doEmail1 INTEGER,
				doEmail2 INTEGER
			);
		');
		$db->query('
			CREATE TABLE IF NOT EXISTS auth (
				id      INTEGER PRIMARY KEY,
				hash    VARCHAR(40),
				game	INTEGER,
				player  INTEGER
			);
		');
	}

	function GetGame() {
		global $db, $game;
		
		// Get basic information
		$stmt = $db->prepare('SELECT * FROM games WHERE id=?');
		$stmt->execute(array($game['id']));
		$found = false;
		foreach($stmt as $row) {
			$game['name1']  = $row['name1'];
			$game['name2']  = $row['name2'];
			$game['email1'] = $row['email1'];
			$game['email2'] = $row['email2'];
			$game['doEmail1'] = $row['doEmail1'];
			$game['doEmail2'] = $row['doEmail2'];
			$found = true;
		}
		if ( ! $found) {
			$_SESSION['info'] = 'Couldn\'t retrieve game info!';
			redirect(HOME_ADDRESS);
		}
		
		// Get current board and turn
		$stmt = $db->prepare('SELECT * FROM boards WHERE game=? ORDER BY id DESC LIMIT 1');
		$stmt->execute(array($game['id']));
		$found = false;
		foreach($stmt as $row) {
			$game['board'] = $row['board'];
			$game['turn']  = $row['turn'];
			$game['move']  = $row['move']; 
			$found = true;
		}
		if ( ! $found) {
			$_SESSION['info'] = 'Couldn\'t retrieve game state!';
			redirect(HOME_ADDRESS);
		}
		
		// Get spectate url
		$stmt = $db->prepare('SELECT hash FROM auth WHERE game=? AND player=?');
		$stmt->execute(array($game['id'], PLAYER_S));
		$found = false;
		foreach($stmt as $row) {
			$game['auth_spec'] = $row['hash'];
			$found = true;
		}
		if ( ! $found) {
			$_SESSION['info'] = 'Couldn\'t retrieve game state!';
			redirect(HOME_ADDRESS);
		}
		
		// Get chat history
	}

	function GetHistory($game, $limit = 5) {
		global $db;
		
		// SQLite doesn't support FULL OUTER JOIN
		$stmt = $db->prepare('
			SELECT * FROM (
				SELECT
					player key, message val, time, 2 type
				FROM chat WHERE game = ?
				UNION ALL
				SELECT
					turn key, move val, time, 1 type
				FROM boards WHERE game = ?
			) ORDER BY time DESC LIMIT ?
		');
		$stmt->execute(array($game, $game, $limit));
		$results = $stmt->fetchAll();
		
		return $results;
	}
	
	function NewGame($name1, $name2) {
		global $db;

		// Create new game
		$stmt = $db->prepare('
			INSERT INTO games (name1, name2, email1, email2, doEmail1, doEmail2)
			VALUES( ?, ?, ?, ?, ?, ?);
		');
		$stmt->execute(array($name1, $name2, '', '', 0, 0 ));
		$game['id'] = $db->lastInsertID();
		
		// Create default board
		Move($game['id'], PLAYER_W, 'New Game', DEFAULT_BOARD);
		
		// Create authentication hash keys
		$hash_w = RandomHash();
		$hash_b = RandomHash();
		$hash_s = RandomHash();		
		$stmt = $db->prepare('INSERT INTO auth (hash, game, player) VALUES (?, ?, ?);');
		$stmt->execute(array($hash_w, $game['id'], PLAYER_W));
		$stmt->execute(array($hash_b, $game['id'], PLAYER_B));
		$stmt->execute(array($hash_s, $game['id'], PLAYER_S));
		
		return array(PLAYER_W => $hash_w, PLAYER_B => $hash_b, PLAYER_S => $hash_s);
	}

	function SetPlayerPreferences($game_id, $player_id, $email, $doEmails) {
		global $db;
		
		// Build query
		if ($player_id == PLAYER_W) {
			$stmt = $db->prepare('UPDATE games SET email1=?, doEmail1=? WHERE id=?');
		} else if ($player_id == PLAYER_B) {
			$stmt = $db->prepare('UPDATE games SET email2=?, doEmail2=? WHERE id=?');
		} else return;

		// Execute
		$stmt->execute(array($email, ($doEmails)?1:0 , $game_id));
	}
	
	function Move($game_id, $turn, $move_str, $board_str) {
		global $db;		
		$stmt = $db->prepare('
			INSERT INTO boards (game, turn, move, board, time)
			VALUES( ?, ?, ?, ?, ?);
		');
		$stmt->execute(array($game_id, $turn, $move_str, $board_str, time()));
	}

	function Chat($game_id, $player, $message) {
		global $db;
		$stmt = $db->prepare('
			INSERT INTO chat (game, player, message, time)
			VALUES (?, ?, ?, ?);
		');
		$stmt->execute(array($game_id, $player, $message, time()));
	}
	
	function CountGames() {
		global $db;
		$stmt = $db->query('SELECT MAX(id) m FROM games');
		$response = $stmt->fetchAll();
		return intval($response[0]['m']);
	}

	function RandomHash() {
		return sha1(APP_NAME.time(NULL).(rand() % 1000));
	}

	function SearchHash($hash) {
		global $db;
		$stmt = $db->prepare('SELECT * FROM auth WHERE hash = ?');
		$stmt->execute(array($hash));
		foreach ($stmt as $row) {
			if (! isset($row['game']) || ! isset($row['player'])) continue;
			return array($row['game'], $row['player']);
		}
		return array(0, PLAYER_S);
	}
	
	function RetrieveHash($game, $player) {
		global $db;
		$stmt = $db->prepare('SELECT hash FROM auth WHERE game = ? AND player = ?');
		$stmt->execute(array($game, $player));
		$results = $stmt->fetchAll();
		return $results[0]['hash'];
	}
	
}
