<?php
 use TCMS\TException;
 class Db {
 private static $isNeedIncludeDriveDb = true;
 private static $conn = null;
 private static $driver = 0;
 public static function table($tableName) {
 if (empty($tableName)) {
 throw new TException('Tên table không được trống', 501);
 }
 if (self::$isNeedIncludeDriveDb) {
 self::$isNeedIncludeDriveDb = false;
 Config::$dbConfig = include(CONFIG_PATH . 'db.php');
 $dbConfig = Config::$dbConfig;
 switch ($dbConfig['driver']) {
 case 'mysql': include_once('MySqlDb.php');
 self::$driver = 0;
 break;
 case 'postgres': include_once('PgSqlDb.php');
 self::$driver = 1;
 break;
 case 'mongodb': include_once('MongoDb.php');
 self::$driver = 2;
 break;
 default: throw new TException('Database driver ' . $dbConfig['driver'] . ' chưa được hỗ trợ trong phiên bản hiện tại', 501);
 break;
 }
 }
 switch (self::$driver) {
 case 0: self::connectToMySqlDb();
 return new MySqlDb(self::$conn, $tableName);
 case 1: self::connectToPostgresDb();
 return new PgSqlDb(self::$conn, $tableName);
 case 2: self::connectToMongoDb();
 return new MongoDb(self::$conn, $tableName);
 }
 }
 private static function connectToMySqlDb() {
 if (self::$conn == null) {
 $dbConfig = Config::$dbConfig;
 try {
 if ($dbConfig["port"] == 80) self::$conn = new PDO('mysql:host=' . $dbConfig["host"] . ';dbname=' . $dbConfig['db_name'] . ';charset=' . $dbConfig['charset'], $dbConfig['user'], $dbConfig['pass']);
 else self::$conn = new PDO('mysql:host=' . $dbConfig["host"] . ';port=' . $dbConfig['port'] . ';dbname=' . $dbConfig['db_name'] . ';charset=' . $dbConfig['charset'], $dbConfig['user'], $dbConfig['pass']);
 self::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 }
 catch (PDOException $exc) {
 self::$conn = null;
 throw new TException($exc->getMessage(), 500);
 }
 }
 }
 private static function connectToPostgresDb() {
 if (self::$conn == null) {
 $dbConfig = Config::$dbConfig;
 try {
 self::$conn = new PDO('pgsql:host=' . $dbConfig["host"] . ';port=' . $dbConfig['port'] . ';dbname=' . $dbConfig['db_name'], $dbConfig['user'], $dbConfig['pass']);
 self::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 }
 catch (PDOException $exc) {
 self::$conn = null;
 throw new TException($exc->getMessage(), 500);
 }
 }
 }
 private static function connectToMongoDb() {
 if (self::$conn == null) {
 $dbConfig = Config::$dbConfig;
 try {
 require_once APP_PATH . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
 if (empty($dbConfig["user"])) {
 $client = new \MongoDB\Client('mongodb://' . $dbConfig["host"] . ':' . $dbConfig['port'] . '/');
 self::$conn = $client->selectDatabase($dbConfig['db_name']);
 }
 else {
 $acc = [ 'username' => $dbConfig["user"], 'password' => empty($dbConfig["pass"]) ? '' : $dbConfig["pass"] ];
 $client = new \MongoDB\Client('mongodb://' . $acc['username'] . ':' . $acc['password'] . '@' . $dbConfig["host"] . ':' . $dbConfig['port'] . '/' . (isset($dbConfig['auth_source']) ? ('?authSource=' . $dbConfig['auth_source']) : ''));
 self::$conn = $client->selectDatabase($dbConfig['db_name']);
 }
 }
 catch (PDOException $exc) {
 self::$conn = null;
 throw new TException($exc->getMessage(), 500);
 }
 }
 }
 public static function closeConnection() {
 if (self::$conn != null) {
 self::$conn = null;
 }
 }
 public static function raw($text) {
 return new DbRaw($text);
 }
 }
 class DbRaw {
 private $value = '';
 public function __construct($value) {
 $this->value = $value;
 }
 public function __toString() {
 return $this->value;
 }
 }
 