<?php


/**
 * Model class
 *
 * this class contain the methods that do crud operations
 *
 *
 * LICENSE: Open source
 *
 * @category   general
 * @package    core system
 * @subpackage parent
 * @copyright  coderg
 * @license    http://coderg.com
 * @version    .01
 * @link       http://coderg.com
 * @since      2018
 */
class Model {

    public static function getPDOParam($value) {
        switch (gettype($value)) {
            case "string":
                return PDO::PARAM_STR;
                break;
            case "integer":
                return PDO::PARAM_INT;
                break;
            case "boolean":
                return PDO::PARAM_BOOL;
                break;
            case "NULL":
                return PDO::PARAM_NULL;
                break;
            case "double":
                return PDO::PARAM_STR;
                break;
            default:
                break;
        }
    }

    /**
     * convertArrayToSqlString
     *
     * Convert array of data to the sql string format;
     * like data=array('name'=>'ahmed','salary'=>'222') then sqlString='name=:name,salary=:salary'
     *
     * @param     (none)
     * @return    (string) sqloutput string format
     *
     */
    function convertArrayToSqlString() {
        end($this->data);
        $lastKey = key($this->data);
        $string = "";
        foreach ($this->data as $key => $value):
            if ($key == $lastKey)
                $string.= $key . " =? ";
            else
                $string.= $key . " =? , ";
        endforeach;
        return $string;
    }

    /**
     * add
     *
     * add data to the database
     *
     * @param    none
     * @return   on sucess (last insert id) ,false otherwise
     *
     */
    public function add() {
        //global $dbh;
        $counter = 1;
        $sql = $this->dbh->prepare("INSERT INTO $this->tableName SET " . $this->convertArrayToSqlString());
        foreach ($this->data as $key => $value) {
            $sql->bindValue($counter, $value);
            $counter++;
        }
        if ($sql->execute()) {
            return $this->dbh->lastInsertId();
        } else {
            return false;
        }
    }

    /**
     *  retrieveAllData
     *
     *  get all data from model table based on condition or no condition at all
     * @param    $condition (string) sql condition like 'where id > ? '
     * @param    $data (array) array of placeholder data in squence like array(12);
     * @return null if no data found,false on failure ,on success return array of records
     *
     */
    public function retrieveAllData($condition = "", $data = "") {
        //global $dbh;
        $counter = 1;
        //query statement
        $query = "SELECT * FROM $this->tableName ";

        //check if there is a condition and array of placeholder data found
        if (!empty($condition) && is_array($data)) {
            //concat condition statment with the query
            $query .= $condition;
            //prepare query
            $sql = $this->dbh->prepare($query);
            //replace the data with the placehodlers using bindvalue function
            foreach ($data as $value) {
                $sql->bindValue($counter, $value, self::getPDOParam($value));
                $counter++;
            }
        } else {
            //prepare sql
            $sql = $this->dbh->prepare($query);
        }
        if (false !== $sql->execute()) {
            if ($sql->rowCount() == 0)
                return null;
            else
                return $sql->fetchAll(PDO::FETCH_ASSOC);
        } else
            return FALSE;
    }
    /**
     *  retrieveDataByQuery
     *
     *  get all data from model table based on condition or no condition at all
     * @param    $query (string) sql query like select * from .. inner join  '
     * @param    $data (array) array of placeholder data in squence like array(12);
     * @return null if no data found,false on failure ,on success return array of records
     *
     */
    
    public function retrieveDataByQuery($query,$data = "") {
        //global $dbh;
        $counter = 1;
        //check if is array of placeholder data found
        if (is_array($data)) {
            //prepare query
            $sql = $this->dbh->prepare($query);
            //replace the data with the placehodlers using bindvalue function
            foreach ($data as $value) {
                $sql->bindValue($counter, $value,self::getPDOParam($value));
                $counter++;
            }
        } else {
            $sql = $this->dbh->prepare($query);;
        }
        if (false !== $sql->execute()) {
            if ($sql->rowCount() == 0)
                return null;
            else
                return $sql->fetchAll(PDO::FETCH_ASSOC);
        } else
            return FALSE;
    }

    /**
     *  retriveDataById
     *
     * get one record from the database based on id
     * @param    $columnName (string)
     * @param    $id (unknown-type)
     * @return   null if no data found,false on failure ,on success return array of record
     *
     */
    public function retriveDataById($columnName, $id) {
        //global $dbh;
        $sql = $this->dbh->prepare("SELECT * FROM $this->tableName WHERE $columnName=?");
        $sql->bindValue(1, $id);
        if (false !== $sql->execute()) {
            if ($sql->rowCount() == 0)
                return NULL;
            else
                return $sql->fetch(PDO::FETCH_ASSOC);
        } else
            return FALSE;
    }

    /**
     *  deleteById
     *
     * delete one record from the database based on id
     * @param    $columnName (string)
     * @param    $id (unknown-type)
     * @return   false on failure ,true on success
     *
     */
    public function deleteById($columnName, $id) {
        //global $dbh;

        $sql = $this->dbh->prepare("DELETE FROM $this->tableName WHERE $columnName =?");
        $sql->bindValue(1, $id);
        if (false !== $sql->execute())
            return true;
        else
            return false;
    }

    /**
     *  deleteByCondition
     *
     *  delete all data from model table based on condition
     *
     * @param    $condition (string) sql condition like 'where id > ? '
     * @param    $data (array) array of placeholder data in squence like array(12);
     * @return   false on failure ,true on success
     *
     */
    public function deleteByCondition($condition, $data) {
        //global $dbh;
        $counter = 1;
        $sql = $this->dbh->prepare("DELETE FROM $this->tableName $condition ");
        foreach ($data as $value) {
            $sql->bindValue($counter, $value);
            $counter++;
        }
        if (false !== $sql->execute())
            return true;
        else
            return false;
    }

    /**
     *  updateData
     *
     * update data from database
     *
     * @param    $columnName (string)
     * @param    $id (unknown_type)
     * @return   false on failure ,true on success
     *
     */
    public function updateData($columnName, $id) {
       // global $dbh;
        $counter = 1;
        $sql = $this->dbh->prepare("UPDATE $this->tableName SET " . $this->convertArrayToSqlString() . " WHERE $columnName =?");
        foreach ($this->data as $key => $value) {
            $sql->bindValue($counter, $value);
            $counter++;
        }
        
        $sql->bindValue($counter, $id);
        $counter++;
        
        if ($sql->execute())
            return true;
        else
            return false;
    }

    /**
     * CheckExists
     *
     * check if the data exists on the database or not
     * @param    $condition (string)
     * @param    $data (array)
     * @return   false on failure ,true on success
     *
     */
    public function CheckExists($condition, $data) {
        $counter = 1;
        $sql = $this->dbh->prepare("SELECT * FROM $this->tableName $condition ");
        foreach ($data as $value) {
            $sql->bindValue($counter, $value);
            $counter++;
        }
        if (false !== $sql->execute()) {
            if ($sql->rowCount() > 0)
                return TRUE;
            else
                return FALSE;
        } else
            return FALSE;
    }

    /**
     *  get_data_number
     *
     *  GET Num Of DATA From Table (how many record on my table)  Based On Condition
     * @param     ($condition) condition to get data based on that condition
     * @return  (number) Num Of DATA From Table (how many record on my table) Based On Condition
     */
    public function get_data_number($condition,$orQuery="") {
        //global $dbh;
        if(!empty($orQuery))
        {
            $query = $this->dbh->prepare($orQuery);
        }else{
            $query = $this->dbh->prepare("SELECT * FROM $this->tableName $condition");
        }

        $query->execute();
        return $query->rowCount();
    }

    public function getTableName() {
        return $this->tableName;
    }

    public function updateByCondition($condition, $data) {
        //global $dbh;
        $counter = 1;
        $sql = $this->dbh->prepare("UPDATE $this->tableName SET " . $this->convertArrayToSqlString() . "  $condition");

        foreach ($this->data as $value) {
            $sql->bindValue($counter, $value);
            $counter++;
        }

        foreach ($data as $key => $value) {
            $sql->bindValue($counter, $value);
            $counter++;
        }

        if (false !== $sql->execute())
            return true;
        else
            return false;
    }


}
