<?php
require_once (PATH_MODELS . "admin/AuditLogClass.php");
require_once (PATH_MODELS . "admin/OrganizationClass.php") ;
require_once (PATH_TABLES . "admin/ConstantsKeyList.php") ;
require_once (PATH_TABLES . "admin/TableKeyList.php") ;
abstract class MasterBase {
	protected $bu;
	protected $db ;
	protected $tbl = "" ;
	protected $fldid = "";
	protected $fldid2 = "";
	protected $flddesc = "" ;
	protected $fldcode = "" ;
	protected $fldorg = "ORG_ID" ;
	protected $orgId = -1;
	protected $tblType = DatabaseTableType::Master;

	function __construct() {
	}
	function __destruct() {
	}
	function addRecord($datas) {
		$id = 0 ;
		$sql = "insert into " . $this->tbl  ;
		$fld = "" ;
		$val = "" ;
		$fs = "" ;
		$params = array() ;
		if (is_array($datas) && count($datas) > 0) {
			foreach ($datas as $data) {
				$fld .= $fs . $data['field'] ;
				$val .= $fs . $this->db->formatValueParam($data['field']) ;
				$params[] = $this->db->valueParam($data['field'],$data['value']) ;
				$fs = ", " ;
			}
			$sql .= " (" . $fld . ") values (" . $val . ")";
			$id = $this->db->insertRowGetId($sql,$params) ;
		}
        if ($this->tbl != AuditLogTable::C_TABLE && $id > 0 && $this->tblType != DatabaseTableType::Transaction){
            $this->insertToAudit($datas, AuditLogActivityType::InsertRecord, $id);
        }
		return $id ;
	}
	function insertToAuditLogin($type, $id, $trigger = 0){
        $auditCls = new AuditLogClass($this->db);

        $newLogDatas = array();
		$ws 		= $_SESSION[SE_REMOTE_IP];
		$orgid 		= $_SESSION[SE_ORGID] ;
		$modifyby 	= 0 ;
        if (isset($_SESSION[SE_USERID]))
            $modifyby 	= $_SESSION[SE_USERID] ;
        else if (isset($_SESSION[SE_EMPID]))
            $modifyby 	= $_SESSION[SE_EMPID] ;

        $desc       = "";;
		$modifydate = date_create('now')->format('Y-m-d H:i:s') ;

        if ($type == AuditLogActivityType::Login){
            $desc = "Logged in with ID = " . $id . "";
			$modifyby = $id;
        } else if ($type == AuditLogActivityType::FailedLogin){
            $desc = "Failed login attempt (wrong password) with ID = " . $id . "";
			$modifyby = $id;
        } else if ($type == AuditLogActivityType::ResetPassword){
            $desc = "Reset password for ID = " . $id . ", triggered by ID = " . $trigger . "";
        } else if ($type == AuditLogActivityType::ForgetPassword){
            $desc = "Forget password triggered for ID = " . $id . "";
			$modifyby = $id;
        }

		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_DESC,$desc) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_LOG_TABLE,$this->tbl) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_WS,$ws) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_USER,$modifyby) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_ORG_ID,$orgid) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_DATE,$modifydate) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_ACT_TYPE,$type) ;

        try {
			$auditCls->addRecord($newLogDatas) ;
		} catch (Exception $e) {
			Log::write('[AuditLogProcess]' . $e->getMessage());
		}

        return 0;
	}
    function insertToAudit($datas, $type, $id = 0, $id2 = 0){
        $auditCls = new AuditLogClass($this->db);

        $newLogDatas = array();
		$ws 		= $_SESSION[SE_REMOTE_IP];
		$orgid 		= $_SESSION[SE_ORGID] ;
		$modifyby 	= 0 ;
        if (isset($_SESSION[SE_USERID]))
            $modifyby 	= $_SESSION[SE_USERID] ;
        else if (isset($_SESSION[SE_EMPID]))
            $modifyby 	= $_SESSION[SE_EMPID] ;

        $desc       = "";
		$str2 = "";
		$modifydate = date_create('now')->format('Y-m-d H:i:s') ;


        if ($type == AuditLogActivityType::InsertRecord){
            $str = "";
            foreach($datas as $data){
                if ($str != "") $str .= ", ";
                $str .= $data['field'] .  " = " . $data['value'];


                if ($str2 != "") $str2 .= "~~~";
                $str2 .= $data['field'] .  "=" . $data['value'];
            }
            $desc = "Insert new record to table " . $this->tbl . " with ID = " . $id . " and values = (" . $str . ")";
        } else if ($type == AuditLogActivityType::UpdateRecord){
            $str = "";
            foreach($datas as $data){
                if ($str != "") $str .= ", ";
                $str .= $data['field'] .  " = " . $data['value'];


                if ($str2 != "") $str2 .= "~~~";
                $str2 .= $data['field'] .  "=" . $data['value'];
            }

			$str2 = $this->fldid . "=" . $id . "~~~" . $str2;
            $desc = "Update record with ID = " . $id . " and values = (" . $str . ") in table " . $this->tbl . "";

        } else if ($type == AuditLogActivityType::DeleteRecord){
            $desc = "Delete record with ID = " . $id . "";
			$str2 = $this->fldid . "=" . $id;
        }

		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_DESC,$desc) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_LOG_TABLE,$this->tbl) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_WS,$ws) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_USER,$modifyby) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_ORG_ID,$orgid) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_DATE,$modifydate) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_ACT_TYPE, $type) ;
		$newLogDatas[] = $this->db->fieldValue(AuditLogTable::C_DATA, $str2) ;

        try {
			$auditCls->addRecord($newLogDatas) ;
		} catch (Exception $e) {
			Log::write('[AuditLogProcess]' . $e->getMessage());
		}

        return 0;
    }

	function beautifyAuditLog($logTable='', $logDatas='') {
		// log::write("beautifyAuditLog");

		$tableName = ucfirst($logTable) . "Table";
		$className = ucfirst($logTable) . "Class";
		$cls = new $className($this->db);

		$tableRef = new ReflectionClass($tableName);
		$tableDescriptionRef = new ReflectionClass($tableName . "Description");

		$listTable = $tableRef->getConstants();
		$listTableDescription = $tableDescriptionRef->getConstants();

		$logs = explode("~~~", $logDatas);

		$logStr = "";

		if(!is_null($logs) && count($logs) > 0){
			foreach ($logs as $datas) {
				$data = explode("=", $datas);
				// log::write($datas);
				$columnName = array_search($data[0], $listTable);
				// log::write($columnName);

				if ($columnName != "C_PK") {
					$columnDesc = isset($listTableDescription[$columnName]) ? $listTableDescription[$columnName] : $columnName;
					// log::write($columnDesc);

					//foreign key
					$foundForeignKey = false;
					$parentTableName = "";
					$updateDatabaseCls = new UpdateDatabaseClass($this->db);

					$parentDesc = "";
					if ($parentTableName != "") {
						$parentClassName = $parentTableName . "Class";
						// log::write($parentClassName);
						$clsParent = new $parentClassName($this->db);
						$parentDesc = $clsParent->getDescription($data[1]);
					}

					if ($logStr != "")
						$logStr .= ", ";
				}
			}
		}

		// log::write($logStr);
		return $logStr;
	}

	function getTableTop($filter="",$orderby="",$params=null,$top=0) {

		$sql = "select * from " . $this->tbl ;
		if (!empty($filter))
			$sql .= " where " . $filter ;
		if (!empty($orderby))
			$sql .= " order by " . $orderby . " DESC";

		return $this->db->getTable($sql,$params,$top) ;
	}

	function updateRecord($id,$datas) {
		$sql = "update " . $this->tbl . " set " ;
		$fs = "" ;
		$params = array() ;
		if (is_array($datas) && count($datas) > 0) {
			foreach ($datas as $data) {
				$sql .= $fs . $this->db->fieldParam($data['field']) ;
				$fs = ", " ;
				$params[] = $this->db->valueParam($data['field'],$data['value']) ;
			}
			$sql .= " where " . $this->db->fieldParam($this->fldid) ;
			$params[] = $this->db->valueParam($this->fldid,$id) ;
            $result = $this->db->updateRow($sql,$params);
			
            // if ($result == 1 && $this->tbl != AuditLogTable::C_TABLE && $this->tblType != DatabaseTableType::Transaction){
            //     $this->insertToAudit($datas, AuditLogActivityType::UpdateRecord, $id);
            // }

			return $result ;
		} else  {
			return false ;
		}
	}
	function deleteRecord($id) {
		$sql = "delete from " . $this->tbl
			. " where " . $this->db->fieldParam($this->fldid) ;

		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$id) ;

        $result = $this->db->deleteRows($sql,$params);

		// if($this->tblType != DatabaseTableType::Transaction){
		// 	$this->insertToAudit(null, AuditLogActivityType::DeleteRecord, $id);
		// }
		return $this->db->deleteRows($sql,$params) ;
	}
	function getRecord($id, $id2=0) {
		$sql = "select * from " . $this->tbl
			. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$id) ;

		if (isset($id2) && $id2!=0) {
			$sql .= " and " . $this->db->fieldParam($this->fldid2) ;
			$params[] = $this->db->valueParam($this->fldid2,$id2) ;
		}

		//get here
		$rows = $this->db->getRow($sql,$params) ;
		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0] ;
	}
	function getValueList($orgid) {
		$sql = "select " . $this->fldid . " as code, " . $this->flddesc . " as [desc] "
			. " from " . $this->tbl
			. " where " . $this->db->fieldParam($this->fldorg)
			. " order by " . $this->flddesc ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldorg,$orgid) ;
		return $this->db->getTable($sql,$params) ;
	}
	function isFound($id) {
		$filter = $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$id) ;
		if ($this->db->getRowsCount($this->tbl,$filter,$params) > 0 )
			return true ;
		else
			return false ;
	}
	function initTable($condition) {
		return $this->db->initTable($this->tbl,$condition) ;
	}
	function getTable($filter="",$orderby="",$params=null) {
		$sql = "select * from " . $this->tbl ;
		if (!empty($filter))
			$sql .= " where " . $filter ;
		if (!empty($orderby))
			$sql .= " order by " . $orderby ;
		return $this->db->getTable($sql,$params) ;
	}
	function getDescription($id) {
		$sql = "select " . $this->flddesc . " from " . $this->tbl
			. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$id) ;
		$rows = $this->db->getRow($sql,$params) ;
		if (is_null($rows) || count($rows) == 0)
			return "" ;
		else
			return $rows[0][$this->flddesc] ;
	}
	function getIdByDescription($desc) {
		// $sql = "select " . $this->fldid . " from " . $this->tbl
		// 	. ' where ' . $this->flddesc . ' = "' . strtoupper($desc) . '"' ;

		// $rows = $this->db->getRow($sql) ;

		$sql = "select " . $this->fldid . " from " . $this->tbl
			. " where " . $this->db->fieldParam($this->flddesc);

		$params = array();
		$params[] = $this->db->valueParam($this->flddesc, strtolower($desc));

		$rows = $this->db->getRow($sql,$params) ;
		// Log::write(print_r($sql, true));
		if (is_null($rows) || count($rows) == 0)
			return "" ;
		else
			return $rows[0][$this->fldid] ;
	}
	function getIdByCode($code) {

		$sql = "select " . $this->fldid . " from " . $this->tbl
			. " where " . $this->db->fieldParam($this->fldcode) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldcode,$code) ;
		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return "" ;
		else
			return $rows[0][$this->fldid] ;
	}
	function isExistByCode($code) {
		$exist = false;
		$sql = "select " . $this->fldid . " from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldcode);
		$params = array();
		$params[] = $this->db->valueParam($this->fldcode, $code);
		
		$rows = $this->db->getRow($sql, $params);

		if (is_null($rows) || count($rows) == 0) {
			$exist = false;
		} else {
			$exist = true;
		}
		return $exist;
	}
    function isUsed($id){
        return "";
    }
    function isAllowDeleteMaster(){
		$cls = new OrganizationClass($this->db) ;
		if($this->orgId == -1)
			$row = $cls->getRecord($_SESSION[SE_ORGID]) ;
		else
			$row = $cls->getRecord($this->orgId) ;
		if (is_null($row))
			return false;

		$opt = new OrganizationOptions() ;
		if(!is_null($row) && count($row) > 0)
			$opt->loadXml($row[OrganizationTable::C_OPTIONS]) ;
		$op = $opt->getOption() ;

        return $op[OrganizationOptions::C_SETTING][OrganizationOptions::C_ALLOW_DELETE_MASTER] == '1';
	}

	function getMaxFieldByLedgerId($systemId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$systemId) ;

		$rows = $this->db->getRow($sql,$params) ;
		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}

	function getMaxFieldBySalesQuotationMaintenanceId($salesQuotationId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$salesQuotationId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}

	function getMaxFieldBySalesQuotationProjectPlanId($salesQuotationId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$salesQuotationId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}
	function getMaxFieldBySalesQuotationAppendixId($salesQuotationId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$salesQuotationId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}
	function getMaxFieldByCampaignId($campaignId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$campaignId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}
	function getMaxFieldBySalesInvoiceId($salesInvoicenId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$salesInvoicenId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}
	function getMaxFieldBySalesInvoiceMaintenanceId($salesInvoiceId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$salesInvoiceId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}

	function getMaxFieldByCreditNoteMaintenanceId($creditnoteId, $field) {
		$sql = "select MAX(".$field.") from " . $this->tbl
		. " where " . $this->db->fieldParam($this->fldid) ;
		$params = array() ;
		$params[] = $this->db->valueParam($this->fldid,$creditnoteId) ;

		$rows = $this->db->getRow($sql,$params) ;

		if (is_null($rows) || count($rows) == 0)
			return array() ;
		else
			return $rows[0][0] ;
	}
	function getTableColumnDescriptionList(){
		$tableName = str_replace("Class", "Table", get_class($this));
		$tableDescriptionRef = new ReflectionClass($tableName . "Description");
		$listTableDescription = $tableDescriptionRef->getConstants();

		return $listTableDescription;
	}
	function getTableColumnNameList(){
		$tableName = str_replace("Class", "Table",get_class($this));
		$tableRef = new ReflectionClass($tableName . "");
		$listTable = $tableRef->getConstants();

		return $listTable;
	}
	function getTableName(){
		return $this->tbl;
	}
	
	function isDescDuplicate($desc, $id = 0){
		if($id != 0){
			$exist_row		= $this->getRecord($id);
			$existing_desc	= $exist_row[$this->flddesc];
			
			if($existing_desc == $desc){
				return false;
			}else{
				// $sql 	= "select * from " . $this->tbl . " WHERE " . $this->flddesc . " = '" . $desc . "' AND " .$this->fldid . " <> " . $id;
				$sql = "select * from " . $this->tbl
					. " WHERE " . $this->db->fieldParam($this->flddesc) 
					. " AND " . $this->fldid . " <> " . $id;

				$params = array() ;
				$params[] = $this->db->valueParam($this->flddesc,$desc) ;

				$rows 	= $this->db->getTable($sql,$params) ;
				if (!is_null($rows) && count($rows) > 0)
					return true;
				else
					return false;
			}
		}else{
			// $sql = "select * from " . $this->tbl . " WHERE " . $this->flddesc . " = '" . $desc . "' AND " .$this->fldid . " <> " . $id;
			$sql = "select * from " . $this->tbl
					. " WHERE " . $this->db->fieldParam($this->flddesc) 
					. " AND " . $this->fldid . " <> " . $id;

			$params = array() ;
			$params[] = $this->db->valueParam($this->flddesc,$desc) ;

			$rows = $this->db->getTable($sql,$params) ;
			if (!is_null($rows) && count($rows) > 0)
				return true;
			else
				return false;
		}
	}

}