<?php
	namespace Juju\PDO;
	require_once(realpath(dirname(__DIR__).'/pdo.class.php'));
	use Juju\PDO;

	class Transaction {
		private $pdo;
		private $_pdo;
		private $savepoint = 0;
		private $dirty = false;
		public function __construct(PDO $pdo){
			$this->pdo = $pdo;
			if(!$pdo->beginTransaction()){
				throw $this->getError();
			}
		}
		public function __destruct(){
			if($this->dirty){
				throw new \Exception("Transaction not committed");
			}
			$this->pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, true);
			$this->savepoint = 0;
		}
		public function __get(string $name){
			switch($name){
				case 'savepoint':case 'dirty':
					return $this->$name;
				break;
				default:
					throw new \Exception("Invalid property {$name}");
			}
		}
		public function commit(bool $final = false){
			if($this->dirty){
				$this->savepoint++;
				$this->exec("savepoint trans_{$this->savepoint}");
				$this->dirty = false;
			}
		}
		public function rollback(bool $final = false){
			if($this->savepoint > 0){
				if($this->dirty){
					$this->exec("rollback to trans_{$this->savepoint}");
				}
				$this->savepoint--;
			}
			$this->dirty = false;
		}
		public function transaction(callable $fn){
			$this->commit();
			if($fn($this) === false){
				$this->rollback();
			}else{
				$this->commit();
			}
		}
		public function table(string $name){
			return new Table($this, $name);
		}
		public function prepare(...$args){
			$this->dirty = true;
			return $this->pdo->prepare(...$args);
		}
		public function exec(...$args){
			$this->dirty = true;
			return $this->pdo->exec(...$args);
		}
		public function query(...$args){
			$this->dirty = true;
			return $this->pdo->query(...$args);
		}
		public function quote(...$args){
			return $this->pdo->quote(...$args);
		}
		public function lastInsertId(...$args){
			return $this->pdo->lastInsertId(...$args);
		}
		public function getError(){
			return $this->pdo->getError();
		}
		public function stringFilter(...$args){
			return $this->pdo->stringFilter(...$args);
		}
		public function stringSet(...$args){
			return $this->pdo->stringSet(...$args);
		}
		public function stringColumn(...$args){
			return $this->pdo->stringColumn(...$args);
		}
		public function stringIndex(...$args){
			return $this->pdo->stringIndex(...$args);
		}
		public function stringForeignKey(...$args){
			return $this->pdo->stringForeignKey(...$args);
		}
	}
?>