<?php
/**
 * Application level Controller
 *
 * This file is application-wide controller file. You can put all
 * application-wide controller-related methods here.
 *
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @package       app.Controller
 * @since         CakePHP(tm) v 0.2.9
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */

App::uses('Controller', 'Controller');


/**
 * Application Controller
 *
 * Add your application-wide methods in the class below, your controllers
 * will inherit them.
 *
 * @package		app.Controller
 * @link		http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
 */
class AppController extends Controller {
    public $firebase;
	
	public $components = array('Session','Cookie');
	//platform= 1/2/3; 1=iOS,2=Android,3=Windows
    public $operation_type = array('ADD'=>1,'EDIT'=>2,'DELETE'=>3);
	
	public function beforeFilter() {
		//This line will be implemented where I will change language.
		//$this->Session->write('Config.language', 'fra');
		$this->firebase = '';
	
			 
		if ($this->Session->check('Config.language')) {
			//echo "cuurent_session";exit;
			$lang = $this->Session->read('Config.language');
			if($lang != Configure::read('Config.language')){
				Configure::write('Config.language', $this->Session->read('Config.language'));
			}
		}  else if($this->Cookie->check('Config.expcount.language')){
			//echo "cuurent_cookie";exit;
			$language = $this->Cookie->read('Config.expcount.language');
			$this->Session->write("Config.language",$language);
			Configure::write('Config.language',$language);
		}
		
		$this->set("current_lang",Configure::read('Config.language'));
		
	}
	
	public function getClientIp(){		
	 
	    $ipaddress = '';
	    if (isset($_SERVER['HTTP_CLIENT_IP']))
	        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
	    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
	        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
	    else if(isset($_SERVER['HTTP_X_FORWARDED']))
	        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
	    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
	        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
	    else if(isset($_SERVER['HTTP_FORWARDED']))
	        $ipaddress = $_SERVER['HTTP_FORWARDED'];
	    else if(isset($_SERVER['REMOTE_ADDR']))
	        $ipaddress = $_SERVER['REMOTE_ADDR'];
	    else
	        $ipaddress = 'UNKNOWN';
	    return $ipaddress;
 
	}
	
	public function getUserAgent(){
		
		
		$maxlength = 80;
		$userAgent = (isset($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : '';
		if(strlen($userAgent) < 80){
			$maxlength = strlen($userAgent);
		}
	 
		return substr($userAgent, 0, $maxlength);;
	
	}
	
	
	public function objectToArray($d) {
		if (is_object($d))
			$d = get_object_vars($d);
		return is_array($d) ? array_map(__METHOD__, $d) : $d;
	}

    public function getSystemCurrentIntTime(){
        date_default_timezone_set("UTC");
        return time();
    }
	public function getSystemCurrentTimeStamp(){
	    date_default_timezone_set("UTC");
		return date("Y-m-d H:i:s");
	}
	
	public function setDefaultTimeStamp(){
		date_default_timezone_set("UTC");
	}
	
	public function getIntToStrDate($intDate){		
		return date("d-M-Y",$intDate);
		
	}
	
	public function isValidNewExpenseDate($newExpenseDate){
		$result = true;
		$newExpenseDateArray = explode('-', $newExpenseDate);
		if(count($newExpenseDateArray) != 3){
			$result = false;
		} else {
			$month = strtolower($newExpenseDateArray[1]);
			$monthArray = array("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
			if(!in_array($month,$monthArray)){
				$result = false;
			} 
		}
		
		return $result;
	}
	
	
	
	
	public function getStrToIntDate($strDate){
	
		list($day, $month, $year) = explode('-', $strDate);
		$month = strtolower($month);
		
		if($month == "jan"){
			$month = "01";
		} else if($month == "feb"){
			$month = "02";
		} else if($month == "mar"){
			$month = "03";
		} else if($month == "apr"){
			$month = "04";
		} else if($month == "may"){
			$month = "05";
		} else if($month == "jun"){
			$month = "06";
		} else if($month == "jul"){
			$month = "07";
		} else if($month == "aug"){
			$month = "08";
		} else if($month == "sep"){
			$month = "09";
		} else if($month == "oct"){
			$month = "10";
		} else if($month == "nov"){
			$month = "11";
		} else if($month == "dec"){
			$month = "12";
		} 
		
		return  (string)mktime(0, 0, 0, $month, $day, $year);
	}

	public function getExpenseCreationDate($intDate){
		$intDateArray = explode("-",$intDate);
		if(count($intDateArray)>1){
			return  $intDate;
		} else {
			return  date("Y-m-d H:i:s", $intDate); 
		}
		 
	}
	
	public function getExpenseCreationStrToIntDate($strDate){
		$strDateArray = explode(" ",$strDate);
		list($year, $month, $day) = explode('-', $strDateArray[0]);
		list($hour, $min, $sec) = explode(':', $strDateArray[1]);
		return  mktime($hour, $min, $sec, $month, $day, $year);
	}
	
	public function isValidExpenseUniqueURL($unique_url, $firstValue){
		if( substr($unique_url, 0, 1) == $firstValue)
			return true;
		else
			return false;		
	}

	public function isValidToken($access_token, $device_id, $random_number){
		$unique_number = $device_id.$random_number; // device id + six digit random number
		$salt      = 'Nop@ss%!*-+@s=_17';
		$generated_token    = hash('sha256', $unique_number . $salt);
		 
		if($access_token == $generated_token){
			return true;
		} else {
			return false;
		}
	}

	public function getUserToken($device_id, $random_number){
		$unique_number = $device_id.$random_number; // device id + six digit random number
		$salt      = 'Nop@ss%!*-+@s=_17';
		return hash('sha256', $unique_number . $salt);
	}

	public function getResetPasswordToken($device_id, $random_number, $email){
		$unique_number = $device_id.$random_number.$email; // device id + six digit random number + email
		$salt      = 'Nomatter%!*-+@s=_17';
		return hash('sha256', $unique_number . $salt);
	}
	
	public function isItemAlreadyAdded($dbExpenseList,$currentItemUniqueId){
	
		$result = false;
		if(!empty($dbExpenseList) && !empty($currentItemUniqueId)){
			foreach($dbExpenseList as $key=>$value){
				if(!empty($value["syn_add_unique_id"]) &&  $value["syn_add_unique_id"] == $currentItemUniqueId){
					$result = true;
					break;
						
				}
			}
		}
	
		return $result;
	}
	
	public function getSource($detect){
	
		$source = 2;
			
		if ($detect->isAndroid()) {
			$source = 4;
		} else if($detect->isIphone()){
			$source = 5;
		} else if($detect->isWindows()){
			$source = 6;
		}
		
		return $source;
	
	}

	public function getCaptchaResponse($captcha)
    {
	    
      //  echo RECAPTCH_SECRET_KEY;exit;
        $secretKey  = RECAPTCH_SECRET_KEY;
        $verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secretKey.'&response='.$captcha);
        $responseData = json_decode($verifyResponse);
        return $responseData;
    }

    public function setDefaultWhat($expenseList){
        
        $result = array();
        if(!empty($expenseList)) {
            foreach($expenseList as $key=>$value ) {
                
                if(isset($value["what"]))
                    $value["what"] = trim($value["what"]);
                    if(isset($value["what"]) && empty($value["what"])) {
                        $value["what"] = "N/A";
                    }
                    $result[$key] = $value;
            }
        }
        
        return $result;
        
    }

	public function updateFirebase($unique_url)
    {
        require_once "../../lib/firebase/vendor/autoload.php";
//        $startime = time();
        $expense_type = substr($unique_url, 0 , 1);
        $expense_name = '';
        if($expense_type == 1) {
            $expense_name = "GroupExpense";
        } elseif ($expense_type == 2) {
            $expense_name = "MessExpense";
        } elseif ($expense_type == 3) {
            $expense_name = "FamilyExpense";
        }

        $db_dir = $expense_name.'/'.$unique_url;
        $serviceAccount = \Kreait\Firebase\ServiceAccount::fromJsonFile('../../go_ser_pri.json');
        $firebase = (new \Kreait\Firebase\Factory())
            ->withServiceAccount($serviceAccount)
            ->create();
        $database = $firebase->getDatabase();
        $newPost = $database
            ->getReference(FIREBASE_DB_PATH);
        $current_row = $newPost->getChild($db_dir.'/ver'); //FamilyExpense/3Po9rHbzvdZO0n4
        $current_ver = $current_row->getValue();
        $update_ver = $current_ver + 1;
        $current_row->set($update_ver);
        //$time_diff = time() - $startime;
//        echo "time : ".$time_diff."<br>";
    }

    public function processValidation($method = 'POST')
    {
        $status = "-1";
        $status_desc = "FAILED";
        $error = "";
        $secretKey = "";
        $data = array();

        if($method == 'GET') {
            $object = $this->request->query;
        } else{
            $object = $this->request->input('json_decode');
        }

        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }

        //check maintenance mood
        if (MAINTENANCE_MOOD) {
            $status = "035";
            $status_desc = "Service is in maintenance mood. Please try again later.";
            $error = $status;
        } else if (empty($data)) {
            $status = "031";
            $status_desc = "Invalid JSON input sent";
        } else {

            if ($status == "-1") {
                if (!$this->isValidToken($data["access_token"], $data["device_id"], $data["random_number"])) {
                    $status = "057"; // token is not valid
                    $status_desc = "TOKEN IS NOT VALID. Please  provide access_token, device_id and  random_number ";
                } else {
                    $status = "";
                    $status_desc = "PASS";
                }
            }

        }

        return array($data, $status, $status_desc, $error);
    }

    public function apiLogAppCrashData($data, $status, $status_desc)
    {
        $this->loadModel('LogAppCrashes');
        $crash["unique_url"] = "";
        $crash["error_code"] = $status;
        $crash["error_desc"] = $status_desc;
        $crash["request"] = serialize($data);
        $crash["response"] = ""; //serialize($latestExpenseData);
        $crash["crash_date"] = $this->getSystemCurrentTimeStamp();
        $crash["ip"] = $this->getClientIp();
        $crash["device_info"] = $this->getUserAgent();

        $this->LogAppCrashes->insertLogAppCrashes($crash);
    }

    public function processResponse($error, $data, $status, $status_desc)
    {
        $input["status"] = $status;
        $input["status_desc"] = $status_desc;

        if (!empty($error) || $status != "+000") {
            $input["input"] = $data;
            $input['error'] = $error;
            $this->apiLogAppCrashData($data, $status, $status_desc);
        }

        $this->set(array(
            'response' => $input,
            '_serialize' => array('response')
        ));
    }
    public function isExistFirebaseUser($user_id)
    {
        $result = false;
        $firebaseUser = array();
        $this->initializeFirebase();
        $firebaseUser =  $this->firebase->getAuth()->getUser($user_id);
        if(!empty($firebaseUser)){
            $result = true;
        }
        return array($result,$firebaseUser);
    }

    public function validateUser($user_id) {

        //check validity
        $error = "";
        $error_desc = "";
        $userObj = array();

        $this->loadModel('User');
        list($result, $userObj) = $this->User->isExistUserById($user_id);

        if(IS_FIREBASE_ACTIVATED){
            if(!$result){
                list($result, $userObj) = $this->isExistFirebaseUser($user_id);
            }
        }
        if(!$result){
            $error = "-997";
            $error_desc = "User not exist!";
        }

        return array($error, $error_desc, $userObj);
    }

    public function validateUniqueUrl($url) {

        //check validity
        $error = "";
        $error_desc = "";
        $expObj = array();

        if (empty($error)) {
            $this->loadModel('Expense');
            $expInfo = $this->Expense->findByUniqueUrl($url);

            if(!$expInfo){
                $error = "-997";
                $error_desc = "Unique_url not exist!";
            }
        }
        return array($error, $error_desc,$expObj);
    }

    public function systemGeneratedUniqueId($user_id,$expense_type)
    {
        return $expense_type.'-'.$user_id.'-'.time().'-'.rand(1000,9999);
    }

    public function isValidUserProfile($profile_id, $profile_type)
    {
        $this->loadModel('User');
        return $this->User->isUserExistByProfile( $profile_id, $profile_type);
    }

    public function addUserGroupDuringExpenseCreate($user_id, $unique_url, $expense_type)
    {
        $result = array();
        $status = '';
        $status_desc = '';
        $newUserGroup = array();
        $this->loadModel('UserGroup');
        $this->loadModel('User');

        $userObj = $this->User->getUserByUserId($user_id);

        if(sizeof($userObj)) {
            $existUserGroup = $this->UserGroup->isExistUserGroup($user_id, $unique_url);

            if(empty($existUserGroup[0])) {
                $inputData['user_id'] = $user_id;
                $inputData['unique_url'] = $unique_url;
                $inputData['participant_id'] = '1_0';
                $result[] = $this->UserGroup->add($inputData);
            } else {
                $status = "12";
                $status_desc = "UserGroup is Exist";
            }

            // increment the version in firebase
            $this->userGroupUpdateOnFirebase($user_id, $expense_type);
        } else {
            $status = "13";
            $status_desc = "User is invalid";
        }
        return array($status, $status_desc, $result);
    }

    public function isForceUpgradeRequire($version_recceived, $version_expected) {

		return intval($version_recceived) < intval($version_expected);
	}


    public function initializeFirebase() {
        require_once "../../lib/firebase/vendor/autoload.php";
        $serviceAccount = \Kreait\Firebase\ServiceAccount::fromJsonFile(FIREBASE_SERVICE_ACCOUNT_CREDENTIALS);
        $this->firebase = (new \Kreait\Firebase\Factory())
            ->withServiceAccount($serviceAccount)
            ->create();
    }

    function callAPI($api_url, $request_method = "GET", $post_fields = '') {
        if (!empty($api_url)) {
            $curl = curl_init();
            curl_setopt_array($curl, array(
                CURLOPT_URL => $api_url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => "",
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => $request_method,
                CURLOPT_POSTFIELDS => $post_fields,
                CURLOPT_HTTPHEADER => array(
                    "accept: application/json",
                    "content-type: application/json"
                )
            ));

            $response = curl_exec($curl);
            $err = curl_error($curl);
            $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            curl_close($curl);

            if ($httpcode == 200) {
                return $response;
            } else {
                return "Something went wrong";
            }
        }
        return false;
    }

    function callGETAPI($api_url) {
        if (!empty($api_url)) {
            $curl = curl_init();
            curl_setopt_array($curl, array(
                CURLOPT_URL => $api_url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => "",
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'GET',
//                CURLOPT_POSTFIELDS => $post_fields,
                CURLOPT_HTTPHEADER => array(
                    "accept: application/json",
                    "content-type: application/json"
                )
            ));

            $response = curl_exec($curl);
            $err = curl_error($curl);
            $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            curl_close($curl);

            if ($httpcode == 200) {
                return $response;
            } else {
                return "Something went wrong";
            }
        }
        return false;
    }

    function deviceData(){
        $data["device_id"] = session_id();
        $data["random_number"] = rand(1000, 9999);
        $data["access_token"] = $this->getUserToken($data["device_id"], $data["random_number"]);
        return $data;
    }

    
	public function setCookie($data, $unique_url, $UpdateFlag = null){
	    //set cookie for my expenses
        $this->autoRender = false;
	    $new_cookie = ['title'=>$data['title'],'unique_url'=>$unique_url, 'create_date'=>$data['create_date']];
	    $prev_cookie[] = $new_cookie;
	    if($this->Cookie->read('Expenses') != "") {
	        $prev_cookie = $this->Cookie->read('Expenses');
            if($UpdateFlag){
                $key = array_search($unique_url, array_column($prev_cookie, 'unique_url'));
                $prev_cookie[$key]['title'] = $data['title'];
                setcookie("CakeCookie[Expenses]", json_encode($prev_cookie), time() + (86400 * 1000), "/");
            }else{
                array_push($prev_cookie, $new_cookie);
            }
	    }
        
        if(!$UpdateFlag){
            $this->Cookie->write('Expenses', $prev_cookie, false, '24000 hours');
        }
    }

    public function isPaid($uid)
    {
        $this->loadModel('User');
        $user = $this->User->findById($uid);
			
			if (!empty($user) && !empty($user['User']['user_subscription_id'])) {
				$this->loadModel('UserSubscription');
				$userSub = $this->UserSubscription->findById($user['User']['user_subscription_id']);
				$currtDate = strtotime(date('Y-m-d H:i:s'));
				$userSubDate = strtotime($userSub['UserSubscription']['valid_to']);
				if ($userSubDate >= $currtDate) {
					return true;
				}
			}
            return false;
    }

    public function userGroupUpdateOnFirebase($userId, $expenseType) {
        /*
         * expensecount-312c7/root/{env}/myProfileUser/{expenseType}/{userId}/ver
         * env: prod, dev
         * userId: myProfile user_id
         * expenseType: GroupExpense, MessExpense, FamilyExpense
         */

        require_once "../../lib/firebase/vendor/autoload.php";
        $serviceAccount = \Kreait\Firebase\ServiceAccount::fromJsonFile('../../go_ser_pri.json');
        $this->firebase = (new \Kreait\Firebase\Factory())
            ->withServiceAccount($serviceAccount)
            ->create();

        $database = $this->firebase->getDatabase();

        $newPost = $database->getReference(FIREBASE_DB_PATH);
        $current_row = $newPost->getChild('/myProfileUser/'.$expenseType.'/'.$userId.'/ver');
        $current_ver = $current_row->getValue();

        if(!isset($current_ver)) {
            $update_ver = 1;
        } else {
            $update_ver = $current_ver + 1;
        }
        
        $current_row->set($update_ver);
    }

    public function validateDeleteParticipant($ParticipantArray){
        $error = "";

        if(empty($ParticipantArray)){
            $error = "8";
        }

        if($error == ""){
            foreach($ParticipantArray as $key=>$value){

                if (!array_key_exists('expense_id', $value)||!array_key_exists('id', $value)) {
                    $error = "9";
                    break;
                }

                $idArray[$key] = $value["id"];
            }

        }
        //check id duplicacy
        if($error == ""){
            $previousLength = count($idArray);
            $idArray = array_unique($idArray);
            if($previousLength != count($idArray)){
                $error = "10";
            }
        }

        return $error;
    }

}
