<?php

/**
 * Open a connection with the database server using mysqli extension.
 *
 * @copyright Trusto Tech 2015-2016
 * @author  Taha Sayyad <info@trustotech.com>
 * @package System\Database\Adapters
 */
class MySQLiAdapter extends DBConnectionParameters implements DBAdapterInterface {

    /**
     * @var obj Holds MySQLi connection object
     */
    private $_DBConnection;
    private $_file_name = '';
    private $_file_image_name = '';

    /**
     *
     * @var type 
     */
    private static $_error = array();

    public function __construct() {
        parent::_setParameters();
        try {
            self::connect();
        } catch (PDOException $e) {
            echo $e->getMessage();
            exit();
        }
    }

    public function query($query, $params = null) {
        return $this->prepare_Stmt($query, $params);
    }

    public function rowsno($result) {
        if (!empty($result) && $result instanceof PDOStatement)
            return $result->rowCount();
        return 0;
    }

    public function setNames() {
        $this->_DBConnection->exec("set names utf8");
        $this->_DBConnection->exec("set CHARACTER SET utf8");
    }

    public function fetch($result) {
        if (empty($result))
            return false;
        return $result->fetch(PDO::FETCH_ASSOC);
    }

    public function fetch_row($result) {
        return $result->fetch(PDO::FETCH_NUM);
    }

    public function id() {
        return $this->_DBConnection->lastInsertId();
    }

    public function assoc($result, $fetch_type = null) {
        $fetch_type = (empty($fetch_type) ? PDO::FETCH_ASSOC : PDO::FETCH_BOTH);
        if (!empty($result) && $result instanceof PDOStatement) {
            $row = $result->fetch($fetch_type);
            return (empty($row) ? null : $row); //if it return false we return null since in some cases they check if(count($row))
        }
        return null;
    }

    //    public function affectedRows() {
    //        return mysqli_affected_rows($this->_DBConnection);
    //    }

    public function commit() {
        return $this->_DBConnection->commit();
    }

    public function rollback() {
        return $this->_DBConnection->rollBack();
    }

    public function free($result) {
        $result->closeCursor();
        return $this;
    }

    public function thread() {
        return 0;
        //        return mysqli_thread_id($this->_DBConnection);
    }

    public function kill($thread_id) {
        //        if (!isset($thread_id)) {
        //            throw new MySQLiException('Error: you must specify the thread id you want to kill. Use method thread() to get the thread id you want to kill.');
        //            return;
        //        }
        //        return mysqli_kill($this->_DBConnection, $thread_id);
    }

    public function close() {
        //        if ($this->_DBConnection)
        //            mysqli_close($this->_DBConnection);
    }

    public function getConnectionObject() {
        return $this->_DBConnection;
    }

    private function connect() {
        $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
        $conn_str = "mysql:host=" . parent::_getDBHostname() . ";dbname=" . parent::_getDBName() . ";charset=utf8";
        try {
            $this->_DBConnection = new PDO($conn_str, parent::_getDBUsername(), parent::_getDBPassword(), $options);
            $this->_DBConnection->exec("set names utf8");
            $this->_DBConnection->exec("set CHARACTER SET utf8");
            //if this is set to true means to always emulate prepare statement even if sql driver support prepare statement
            //if set false then it will use sql driver native prepare statement and will fallback to emulate prepare statement
            //if driver not native support it.. so ATTR_EMULATE_PREPARES is true then prepare parameter replacement will occur
            //in the PHP PDO library while if it is false then will replace parameter in the native sql driver [if there is].
            //if it is true may get syntax errors at prepare-time rather than at execute-time
            //            $this->_DBConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        } catch (PDOException $e) {
            throw new PDOException('#' . $e->getMessage() . ': Error connecting to database.');
        }
        return true;
    }

    /**
     * # baydoun | 2016-11-16
     * @return type
     */
    public static function error() {
        return self::$_error;
    }

    public static function clear_error() {
        self::$_error = array();
    }

    public static function set_error($msg) {
        self::$_error = array($msg);
    }

    public function multi_query($query) {
        if (mysqli_multi_query($this->_DBConnection, $query)) {
            do {
                // Store first result set
                if ($result = mysqli_store_result($this->_DBConnection)) {
                    // Fetch one and one row
                    //while ($row = mysqli_fetch_row($result)) {
                    //    printf("%s\n", $row[0]);
                    //}
                    // Free result set
                    mysqli_free_result($result);
                }
            } while (mysqli_more_results($this->_DBConnection) && mysqli_next_result($this->_DBConnection));
        }
    }

    //    public function preparedStmt($query, array $params) {
    //        $stmt = mysqli_prepare($this->_DBConnection, $query);
    ////        smc_debug($stmt);
    //        $varsNumb = '';
    //        foreach ($params as $key => $value) {
    //            $varsNumb .= 's';
    //        }
    //        call_user_func_array('mysqli_stmt_bind_param', array_merge(array($stmt, $varsNumb), $params));
    //        call_user_func_array('mysqli_stmt_bind_result', array_merge(array($stmt), array(&$username, &$pass, &$district, &$city, &$sabir)));
    //
    //        mysqli_stmt_execute($stmt);
    //        $data = array();
    //        while ($row = mysqli_stmt_fetch($stmt))
    //            $data[] = array($username, $pass, $district, $city, $sabir);
    //        return $data;
    //    }

    public function prepare_Stmt($query, $params = null) {
        $stmt = null;
        try {
            $stmt = $this->_DBConnection->prepare($query);
            if (is_array($params) && count($params)) {
                $i = 0;
                foreach ($params as $indx => $parm)  //if numeric must start with 1
                    $stmt->bindValue((is_numeric($indx) ? ++$i : $indx), $parm, PDO::PARAM_STR);
            }
            $stmt->execute($params);
//            if (isset(smc_session()['default_setting']['is_production']) && smc_session()['default_setting']['is_production'] != 1) {
//                $db_info_path = SYSTEM_PATH . '/uploads/db_info/';
//                $info_log = "\r\n" . str_replace(array("\r\n", "\n", "\r"), " ", $query);  //remove line break
//                $info_log .= "\r\n" . print_r($params, true);
//                $info_log .= "\r\n\r\n===============================================================================\r\n";
//                file_put_contents($db_info_path . date('Y-m-d') . '.txt', $info_log, FILE_APPEND);
//            }
        } catch (PDOException $e) {
            if (empty($stmt))
                $err_arr = $this->_DBConnection->errorInfo();
            else
                $err_arr = $stmt->errorInfo();
            if (isset(smc_session()['default_setting']['is_production']) && smc_session()['default_setting']['is_production'] != 1)
                echo "<pre style='background:#ccc;border:1px solid black;padding:5px;'>" . print_r($err_arr, true) . "</pre>";
            //save error in a log file
            $db_err_path = SYSTEM_PATH . '/uploads/db_error/';
            if (!file_exists($db_err_path))
                mkdir($db_err_path);
            $err_log = "\r\n\r\n===============================================================================\r\n";
            $url = (empty($_SERVER['REQUEST_URI']) ? (empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING']) : $_SERVER['REQUEST_URI']);
            $err_log .= "User: " . smc_session()['user_logged_id'] . "  |  Time: " . date('H:i:s') . "  |  URL: {$url}\r\n";
            $err_log .= "\r\n" . print_r($err_arr, true);
            $err_log .= "\r\n" . str_replace(array("\r\n", "\n", "\r"), " ", $query);  //remove line break
            $err_log .= "\r\n" . print_r($params, true);
            file_put_contents($db_err_path . date('Y-m-d') . '.txt', $err_log, FILE_APPEND);
            //fill error arr.
            $err_msg = "";
            if ($err_arr[1] == 1452 || $err_arr[1] == 1451)
                $err_msg = CommonLanguage::getMessage('child_row');
            elseif ($err_arr[1] == 1062)
                $err_msg = CommonLanguage::getMessage('duplicate_entry');
            elseif ($err_arr[1] != 0)
                $err_msg = CommonLanguage::getMessage('Failed_Submit');
            if (!empty($err_msg))
                self::$_error[] = $err_msg . ' === ' . $err_arr[1] . " :: " . $err_arr[2];
        }
        return $stmt;
    }

    public function is_logged_query($query, array $params) {
        $query = str_replace('?', 'Ӂ', $query);
        foreach ($params as $key => $value) {
            //$type = $varsNumb[$key];    //$type (one of 'i', 'b', 's', 'd')
            //here later we can check if type integer we csat it to integer not string..
            $value = is_null($value) ? 'NULL' : "'" . smc_escape($value) . "'";
            $query = preg_replace("/Ӂ/", $value, $query, 1);
        }
        $query = trim($query);
        $query .= (mb_substr($query, -1) == ';' ? '' : ';') . "\n";
        return $query;
    }

    public function is_logged_data($query, array $params) {
        $query = str_replace('?', 'Ӂ', $query);
        foreach ($params as $key => $value) {
            //$type = $varsNumb[$key];    //$type (one of 'i', 'b', 's', 'd')
            //here later we can check if type integer we csat it to integer not string..
            $value = is_null($value) ? 'NULL' : "'" . smc_escape($value) . "'";
            $query = preg_replace("/Ӂ/", $value, $query, 1);
        }
        $query = trim($query);
        $query .= (mb_substr($query, -1) == ';' ? '' : ';') . "\n";
        //                    die($query);
        $file_format = "Y-m-d-H-i";
        $time = date($file_format);
        $prev_minute_time = date($file_format, strtotime('-1 minutes'));
        if ($this->_file_name == '') {
            $min = substr($time, -2);
            if ($min % 2 != 0)
                $time = $prev_minute_time;
            $this->_file_name = dirBase . "uploads/logs/log#" . $time . "#.txt";
        }

        file_put_contents($this->_file_name, $query, FILE_APPEND);
    }

    public function is_logged_file($query) {
        //                    die($query);
        $file_format = "Y-m-d-H-i";
        $time = date($file_format);
        $prev_minute_time = date($file_format, strtotime('-1 minutes'));
        if ($this->_file_name == '') {
            $min = substr($time, -2);
            if ($min % 2 != 0)
                $time = $prev_minute_time;
            $this->_file_name = dirBase . "uploads/logs/log#" . $time . "#.txt";
        }

        file_put_contents($this->_file_name, $query, FILE_APPEND);
    }

    public function is_logged_image($image_path, $type) {
        //                    die($query);
        $image_path = trim($image_path) . "Ӂ" . $type . "\n";
        $file_format = "Y-m-d-H-i";
        $time = date($file_format);
        $prev_minute_time = date($file_format, strtotime('-1 minutes'));
        if ($this->_file_image_name == '') {
            $min = substr($time, -2);
            if ($min % 2 != 0)
                $time = $prev_minute_time;
            $this->_file_image_name = dirBase . "uploads/logs/img#" . $time . "#.txt";
        }

        file_put_contents($this->_file_image_name, $image_path, FILE_APPEND);
    }

    public function moveZipFiles($zip_file_name, $current_url) {
        $remote_file = 'uploads/tmp/' . $zip_file_name;
        /* FTP Account */
        $ftp_host = 'trusto.info'; /* host */
        $ftp_user_name = 'smart_diner_sharing@trusto.info'; /* username */
        $ftp_user_pass = 'DeliveryAppSharingFiles'; /* password */


        /* New file name and path for this file */
        $local_file = $zip_file_name;

        /* Connect using basic FTP */
        $connect_it = ftp_connect($ftp_host);

        /* Login to FTP */
        $login_result = ftp_login($connect_it, $ftp_user_name, $ftp_user_pass);
        ftp_pasv($connect_it, true) or die("Cannot switch to passive mode");

        /* Download $remote_file and save to $local_file */
        if (!ftp_put($connect_it, $remote_file, $local_file, FTP_BINARY)) {
            return false;
        }

        /* Close the connection */
        ftp_close($connect_it);
        return true;
    }

}
