<?php
declare (strict_types = 1);
namespace ProxyPay\Core;

use ProxyPay\Traits\Log;

class Db extends \mysqli
{

	use Log;

	private $query;

	public function pQuery($query, array $params = [])
	{

		$params = array_map(function($item) {
			if(is_null($item)) {
					return $this->q('');
			}
			if (!is_array($item)) {
				return $this->q($item);
			}
			$item = array_map(function($elm){
				return $this->q($elm);
			}, $item);
			return implode(',', $item);
		}, $params);

		$keys = array_keys($params);

		$keys = array_map(function($item) {
			return ":{$item}:";
		}, $keys);

		$query = str_replace($keys, array_values($params), $query);
		return $this->query($query);
	}

	public function query($query, $resultmode = null)
	{
		$this->query = $query;
		if (stripos($query, "update") !== false || stripos($query, "delete") !== false) {
			if (stripos($query, "where") === false && stripos($query, "INSERT INTO") === false) {
				throw new \Exception($query, 1);
			}
		}
		try{
			$res = parent::query($query);
		} catch(\Exception $e) {
			$backtrace = debug_backtrace();
			$this->log("$this->query
			{$this->error}
			{$backtrace[0]['file']}:{$backtrace[0]['line']}
			" . var_export($_REQUEST, true) . "
			----------------
			");
			throw $e;
		}
		return $res;
	}

	public function prepare($query)
	{
		$this->query = $query;
		if (stripos($query, "update") !== false || stripos($query, "delete") !== false) {
			if (stripos($query, "where") === false && stripos($query, "INSERT INTO") === false) {
				throw new \Exception($query, 1);
			}
		}
		//$res = parent::prepare($query);
		$stmt = new Statement($this, $query);
		if ($this->error) {
			$backtrace = debug_backtrace();
			$this->log("$this->query
{$this->error}
{$backtrace[0]['file']}:{$backtrace[0]['line']}
" . var_export($_REQUEST, true) . "
----------------
");
		}
		return $stmt;
	}

	public function q($str, $quote = '"')
	{
		if (is_array($str)) {
			throw new \Exception(var_export($str, true));
		}
		return $quote . parent::real_escape_string(strval($str)) . $quote;
	}

	public function insertObject($obj, $table, $update = false)
	{
		$this->insertArray((array) $obj, $table, $update);
	}

	public function insertArray(array $array, string $table, $update = false)
	{
		$refarg = array(str_repeat('s', count($array)));
		$args   = implode(',', array_fill(0, count($array), '?'));
		$keys   = array_keys($array);
		array_walk($keys, function (&$item, $key, $db) {$item = $db->q($item, '`');}, $this);
		$columns = implode(',', $keys);
		$table   = $this->q($table, "`");
		$query   = "INSERT INTO $table ($columns) VALUES ($args)";
		if ($update) {
			$query .= " ON DUPLICATE KEY UPDATE ";
			array_walk($keys, function (&$item, $key) {$item = "$item=VALUES($item)";});
			$query .= implode(',', $keys);
		}
		$stmt = $this->prepare($query);

		foreach ($array as $key => $value) {
			$refarg[] = &$array[$key];
		}

		call_user_func_array(array($stmt, "bind_param"), $refarg);
		$res = $stmt->execute();
		if($this->error) {
			$this->log("$table
" . var_export($array, true) . "
----------------
");
		}
		$stmt->close();
		return $res;
	}

	public function getLastQuery()
	{
		return $this->query;
	}

}
