<?php
/**
 * Storage using a database
 */

include_once(dirname(__FILE__).'/./config.inc.php');
include_once(dirname(__FILE__).'/./IdIncreaser.class.php');
include_once(dirname(__FILE__).'/./AbstractStorage.class.php');

class MySQLDbStorage extends AbstractStorage {

	private $dbconn = NULL;

	function __construct() {
		try {
			$this->dbconn = new PDO("mysql:host=" . DB_HOST .  ";dbname=" . DB_DATABASE, DB_USER, DB_PASS); 
		} catch (Exception $e) {
		}
	}
	function __destruct() {
	}

	function getEntryByUrl($url) {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$sqlStr = "SELECT * FROM " . DB_TABLE . " WHERE url = :searchUrl AND text = 0";
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute(array(':searchUrl' => $url));
		$res = $stmt->fetch(PDO::FETCH_ASSOC);
		$stmt->closeCursor();
		return $res;
	}

	function reserveId($userShortId, $url) {
		if ($this->dbconn == NULL) {
			return NULL;
		}

		$tmpId = $userShortId;
		
		if ($tmpId != NULL) {
			// try to allocate entry with that id
			$sqlStr = "INSERT INTO " . DB_TABLE . " (id, url, text) VALUES (:insertId, :theUrl, 1)";
			$stmt = $this->dbconn->prepare($sqlStr);
			if (!$stmt->execute(array(':insertId' => $tmpId, ':theUrl' => $url))) {
				// not successful, so set tmpId to null which generates a new id
				$tmpId = NULL;
			}
		}
		
		if ($tmpId == NULL) {
			// find new unused id
			$sqlStr = "SELECT id FROM " . DB_TABLE . " WHERE text = 0 ORDER BY date DESC LIMIT 1";
			$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
			$stmt->execute();
			$foundLastRes = $stmt->fetch(PDO::FETCH_ASSOC);
			$stmt->closeCursor();
			$foundLast = $foundLastRes['id'];
			$idIncreaser = new IdIncreaser($foundLast, "");
			$reservedId = NULL;
			$sqlStr2 = "INSERT INTO " . DB_TABLE . " (id, url) VALUES (:reserveId, :theUrl)";
			$stmt2 = $this->dbconn->prepare($sqlStr2);
			do {
				$idIncreaser->increase();
				$nextId = $idIncreaser->build();
				if ($stmt2->execute(array(':reserveId' => $nextId, ':theUrl' => $url))) {
					$reservedId = $nextId;
				}
			} while ($reservedId == NULL);
			$tmpId = $reservedId;
		}
		
		return $tmpId;
	}
	
	function getEntryById($shortId) {
		if (empty($shortId) == true) {
			return NULL;
		}
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$sqlStr = "SELECT * FROM " . DB_TABLE . " WHERE id = :searchId";
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute(array(':searchId' => $shortId));
		$foundRes = $stmt->fetch(PDO::FETCH_ASSOC);
		$stmt->closeCursor();
		return $foundRes;
	}
	
	function markVisited($shortId) {
		if (empty($shortId) == true) {
			return;
		}
		if ($this->dbconn == NULL) {
			return;
		}
		$sqlStr = "UPDATE urls SET visited = visited + 1 WHERE id = :visitedUrl";
		$stmt = $this->dbconn->prepare($sqlStr);
		$stmt->execute(array(':visitedUrl' => $shortId));
		return;
	}
	
	function getStatisticsOverview() {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$sqlStr = "SELECT count(id) AS count_ids, sum(visited) AS sum_visited FROM urls";
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute();
		$foundRes = $stmt->fetch(PDO::FETCH_ASSOC);
		$stmt->closeCursor();
		return $foundRes;
	}
	
	function getRandomLink() {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$sqlStr = "SELECT * FROM urls WHERE text = 0 ORDER by rand() LIMIT 1";
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute();
		$foundRes = $stmt->fetch(PDO::FETCH_ASSOC);
		$stmt->closeCursor();
		return $foundRes;
	}

	function getStatsCountByType() {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$sqlStr = "SELECT count(id) AS cnt, text FROM urls GROUP BY text ORDER BY text";
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute();
		$res = $stmt->fetchAll();
		$stmt->closeCursor();
		if (count($res) != 2) {
			return NULL;
		}
		return $res;
	}
	
	function getStatsAllLinksByType($t) {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$limitTo = "";
		if ($t >= 0) {
			$limitTo = "WHERE text = " . $t . " ";
		}
		$sqlStr = "SELECT * FROM urls " . $limitTo . "ORDER BY visited DESC";
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute();
		$res = $stmt->fetchAll();
		$stmt->closeCursor();
		return $res;
	}
	
	function getStatsListActiveLinks($cnt) {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$sqlStr = "SELECT * FROM urls ORDER BY date DESC LIMIT " . ($cnt+0);
		$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute();
		$res = $stmt->fetchAll();
		$stmt->closeCursor();
		return $res;
	}

	function getStatsLinkData($t) {
		if ($this->dbconn == NULL) {
			return NULL;
		}
		$limitTo = "";
		if ($t >= 0) {
			$limitTo = "WHERE text = " . $t . " ";
		}
		$sqlStr = "SELECT * FROM urls " . $limitTo . "ORDER BY visited DESC LIMIT 10000";
				$stmt = $this->dbconn->prepare($sqlStr, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
		$stmt->execute();
		$res = $stmt->fetchAll();
		$stmt->closeCursor();
		return $res;
	}
	
}
