<?php
// namespace helpers;
// use \PDO;

/**
* Database class, extending PDO to use custom methods
*/
class Database extends PDO{

	/**
	* Construct database connection
	**/
	function __construct(){
		try{
			/* Consider UTF-8 format for better support depends on server configurations...??? */
			// parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8',DB_USER,DB_PASS);
			parent::__construct(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);
			$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			$this->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND,"SET NAMES 'utf8'");
		}catch(PDOException $e){
			error_log($e);
			// [DEVELOP] In the event of an error record the error to errorlog.html
			// Logger::newMessage($e);
			// logger::customErrorMsg();
		}
	}

	/**
	* Retrieve / select records from a database using fetchAll
	* @param string $sql query
	* @param array  $array named parameters
	* @param object $fetchMode 
	* @return multi-array returns an array of records
	**/
	public function select($sql,$array = array(), $fetchMode = PDO::FETCH_BOTH ){
		$stmt = $this->prepare($sql);
		foreach($array as $key=>$value){
			if(is_int($value)){
				$stmt->bindValue("$key",$value,PDO::PARAM_INT); 
			} else {
				$stmt->bindValue("$key",$value); 
			}
		}
		$stmt->execute();
		return $stmt->fetchAll($fetchMode);
	}

	/**
	* Retrieve / select records from a database using fetch
	* @param string $sql sql query
	* @param array  $array named parameters
	* @param object $fetchMode : FETCH_LAZY FETCH_ASSOC FETCH_BOTH FETCH_NAMED
	* @return array returns an array of records 
	* FETCH_LAZY : turn next row as an anonymous object with column names as properties
	*/
	public function selectOne($sql,$array = array(), $fetchMode = PDO::FETCH_LAZY){
		$stmt = $this->prepare($sql);
		foreach($array as $key => $value){
			if(is_int($value)){
				$stmt->bindValue("$key",$value,PDO::PARAM_INT); 
			} else {
				$stmt->bindValue("$key",$value); 
			}
		}
		$stmt->execute();
		return $stmt->fetch($fetchMode);
	}

	/**
	* Insert record
	* @param TABLE $table table name
	* @param ARRAY $data array of columns and values
	* @return INT number of affected rows, 0-for none...
	*/
	public function insert($table, $data){
		ksort($data);
		$fieldNames = implode(',', array_keys($data));
		$fieldValues = ':'.implode(', :', array_keys($data));
		$stmt = $this->prepare("INSERT INTO $table ($fieldNames) VALUES ($fieldValues)");
		foreach($data as $key => $value){
			$stmt->bindValue(":$key", $value);
		}
		$stmt->execute();
		return $stmt->rowCount();
	}

	/**
	* Update record
	* @param  string $table table name
	* @param  array $data array of columns and values
	* @param  array $where array of columns and values
	* @return number of updated rows zero for none else number of updated rows
	*/
	public function update($table, $data, $where){
		ksort($data);
		$fieldDetails = NULL;
		foreach($data as $key => $value){
			$fieldDetails .= "$key = :x$key,";
		}
		$fieldDetails = rtrim($fieldDetails, ',');
		$whereDetails = NULL;
		$i = 0;
		foreach($where as $key => $value){
			if($i == 0){
				$whereDetails .= "$key = :$key";
			} else {
				$whereDetails .= " AND $key = :$key";
			}
		$i++;}
		$whereDetails = ltrim($whereDetails, ' AND ');
		$stmt = $this->prepare("UPDATE $table SET $fieldDetails WHERE $whereDetails");
		foreach($data as $key => $value){
			$stmt->bindValue(":x$key", $value);
		}
		foreach($where as $key => $value){
			$stmt->bindValue(":$key", $value);
		}
		$stmt->execute();
		return $stmt->rowCount();
	}

	/**
	* Update record, this one is extremely dangerous... but better for PDO workarounds...
	* @param  string direct sql string without 'UPDATE' prefix
	* @return int number of affected rows
	*/
	public function updateDirect($sql){
		$stmt = $this->prepare("UPDATE ".$sql);
		$stmt->execute();
		return $stmt->rowCount();
	}

	/**
	* Delete method
	* @param string $table table name
	* @param array $data array of columns and values
	* @param array $where array of columns and values
	* @param integer $limit limit number of records
	*/
	public function delete($table, $where, $limit = 1){
		ksort($where);
		$whereDetails = NULL;
		$i = 0;
		foreach($where as $key => $value){
			if($i == 0){
				$whereDetails .= "$key = :$key";
			} else {
				$whereDetails .= " AND $key = :$key";
			}
			$i++;
		}
		$whereDetails = ltrim($whereDetails, ' AND ');
		/* if limit is a number use a limit on the query */
		if(is_numeric($limit)){
			$uselimit = "LIMIT $limit";
		}
		$stmt = $this->prepare("DELETE FROM $table WHERE $whereDetails $uselimit");
		foreach($where as $key => $value){
			$stmt->bindValue(":$key", $value);
		}
		$stmt->execute();
		return $stmt->rowCount();
	}

}