<?php

ini_set('display_errors', 'Off');
ini_set('error_reporting', E_ALL);

/**
 * @property NotificationComponent $Notification
 */
class UsersController extends AppController {

    var $uses = array('Expense', 'GroupExpense', 'Participant', 'DemoExpense', 'AccessInfo', 'User','Wallet','PushToken');
    public $components = array(
        'RequestHandler',
        'MobileDetect',
        'Notification'
    );
    private $app_version = "1"; // 1= old expense date, 2= new expense date
    private $validation_status = "-1";

    private $group_status = ['Active' => 1,'Archived' => 2];

    public function initialize() {

        $this->app_version = "1";  // 1=  old app; 2=new app; date related

        $this->setDefaultTimeStamp();
    }
    public function beforeFilter()
    {
        parent::beforeFilter(); // TODO: Change the autogenerated stub
    }

    public function beforeRender() {
        parent::beforeRender();

        $this->layout = 'visitor';
        if ($this->Session->check("homecontroller_layout")) {
            //$this->layout = '';
            $this->Session->delete("homecontroller_layout");
        }
    }

    public function getProfile() {
        
    }

    public function updateProfile() {
        
    }

    // signup API
    public function signup() {
        $status = "-1";
        $status_desc = "FAILED";
        $error = "";
        $secretKey = "";
        $data = array();
        $invalidGroups = array();
        $userObj = NULL;
        $googleOrAppleSignUp = false;

        $object = $this->request->input('json_decode');

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

        //check maintenance mood
        if (MAINTENANCE_MOOD) {
            $status = "35";
            $status_desc = "Service is in maintenance mood. Please try again later.";
            $error = $status;
        } else if (empty($data)) {
            $status = "31";
            $status_desc = "Invalid JSON input sent";
        } else {
            if ($status == "-1") {
                if (!$this->isValidToken($data["access_token"], $data["device_id"], $data["random_number"])) {
                    $status = "57"; // token is not valid
                    $status_desc = "TOKEN's ARE  NOT VALID";
                }
            }

            if ($status == "-1") {
                list($status, $status_desc, $userObj) = $this->validateRegisterForm($data);
            }
        }


        if (empty($status)) {
            // register the user into database
            $data["ip"] = $this->getClientIp();
            $data["device_info"] = $this->getUserAgent();
            $data["create_date"] = $this->getSystemCurrentTimeStamp();
            $data["update_date"] = $this->getSystemCurrentTimeStamp();

            $device_id = session_id();
            $random_number = rand(10000000, 99999999);
            $verificationToken = $this->getResetPasswordToken($device_id, $random_number, $data['profile_id']);

            $existUser = $this->User->isUserExist($data["profile_id"]);

            if (isset($existUser[0]) && empty($existUser[0])) {

                if (!isset($data['password'])) {
                    $googleOrAppleSignUp = true;
                } else {
                    
                    // temporary check for quick fix; currently web doesn't encode the password
                    if($this->is_base64_encoded($data['password'])) {
                        $data['password'] = base64_decode($data['password'], false);
                    }
                    //$data['password'] = base64_decode($data['password'], false);
                }

                $data['password'] = md5($data['password']);

                if ($this->User->insertUser($data)) {

                    //set Verification Token
                    $this->User->setVerificationTokenByProfileId($data['profile_id'], $verificationToken);

                    //insert into user_groups
                    if (isset($data["groups"])) {
                        $groups = $data["groups"];
                        $user_id = $this->User->id;

                        $groupData = array();

                        foreach ($groups as $key => $value) {
                            if (isset($value["unique_url"]) && isset($value["participant_id"])) {
                                $groupData[$key]["user_id"] = $user_id;
                                $groupData[$key]["unique_url"] = $value["unique_url"];
                                $groupData[$key]["participant_id"] = $value["participant_id"];
                            } else {
                                $invalidGroups[$key] = $value;
                            }
                        }

                        if (!empty($groupData)) {
                            $this->loadModel('UserGroup');
                            $this->UserGroup->saveMany($groupData);
                        }
                    }

                    $userObj = $this->User->getUserByProfileId($data["profile_id"]);
                    $verificationUrl = HTTP_SITE_URL . '/users/verify?vt=' . $verificationToken . '&p=' . $userObj['User']['profile_id'];

                    if(IS_EMAIL_SEND_DURING_USER_REGISTRATION && $googleOrAppleSignUp == false) {

                        $params = array();
                        $params["first_name"] = $userObj['User']['first_name'];
                        $params["profile_id"] = $userObj['User']['profile_id'];
                        $params["email_to"] = $userObj['User']['profile_id'];
                        $params["email_from"] = SUPPORT_EMAIL;
                        $params["subject"] = 'ExpenseCount verification link';
                        $params["link"] = $verificationUrl;
                        $params["template"] = 'user_verification';
                        $params["verification_token"] = $verificationToken;
                        $this->sendEmail($params);
                    }

                    if(IS_USER_WALLET_ACTIVE) {

                        $inputData = array();
                        $inputData["user_id"] = $userObj['User']['id'];
                        $inputData["currency_id"] = 1; // 1 = USD
                        $inputData["balance"] = 0;
                        $inputData["withdrawable_balance"] = 0;
                        $inputData["non_withdrawable_balance"] = 0;
                        $inputData["status"] = 1; // 0 = Inactive, 1= Active
                        $inputData["created_date"] = $this->getSystemCurrentTimeStamp();
                        $inputData["updated_date"] = $this->getSystemCurrentTimeStamp();
                        $this->Wallet->add($inputData);
                    }

                    $status = "+000";
                    $status_desc = "SUCCESS";
                } else {
                    $status = "22";
                    $status_desc = "User Data Saving Failed!";
                }
            } else {
                if ($existUser[1]['User']['is_verified'] == 0) {
                    $status = "-995";
                    $status_desc = "Email is exist but not verified!<p style='color: blue;'>Resend the verification link? <a href='".HTTP_SITE_URL ."/users/resendemail/?p=".trim($existUser[1]['User']["profile_id"])."'>Click here.</></p>";
                } else {
                    $status = "-996";
                    $status_desc = "Email is exist! Try with another email.";
                }
            }
        } else if ($status == 60) {

            $status = "+000";
            $status_desc = "SUCCESS";
        }

        unset($userObj['User']['password']);
        
        if($googleOrAppleSignUp == true) {
            $input["user"] = $userObj["User"];
        }

        $input["status"] = $status;
        $input["status_desc"] = $status_desc;

        if (!empty($error) || $status != "+000") {
            unset($data['password']);
            $input["input"] = $data;

            $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);
        }

        $input["invalid_groups"] = $invalidGroups;

        $this->set(array(
            'response' => $input,
            '_serialize' => array('response')
        ));
    }


    // signin API
    public function signin() {
        $status = "-1";
        $status_desc = "FAILED";
        $error = "";
        $secretKey = "";
        $data = array();
        $userObj = NULL;
        $object = $this->request->input('json_decode');
        $googleSignin = false;

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

        if (!isset($data['password'])) {
            $data['password'] = 'googleSignIn';
            $googleSignin = true;
        } else {

            // temporary check for quick fix; currently web doesn't encode the password
            if($this->is_base64_encoded($data['password'])) {
                $data['password'] = base64_decode($data['password'], false);
            }
            $data['password'] = md5($data['password']);
        }

        if (isset($data['email'])) {
            $data['profile_id'] = $data['email'];
        }

        //check maintenance mood
        if (MAINTENANCE_MOOD) {
            $status = "35";
            $status_desc = "Service is in maintenance mood. Please try again later.";
            $error = $status;
        } else if (empty($data)) {
            $status = "31";
            $status_desc = "Invalid JSON input sent";
        } else {
            
            if ($status == "-1") {
                if (!$this->isValidToken($data["access_token"], $data["device_id"], $data["random_number"])) {
                    $status = "57"; // token is not valid
                    $status_desc = "TOKEN IS  NOT VALID. Please  provide access_token, device_id and  random_number ";
                }
            }
            if ($status == "-1") {
                list($status, $status_desc, $userObj) = $this->validateRegisterForm($data);
            }
        }

        if (empty($status)) {
            $userObj = $this->User->getUserByProfileId($data["profile_id"]);

            if (!isset($userObj['User'])) {
                $status = "-999";
                $status_desc = "No User Found";
            } else if ($googleSignin == false && $userObj['User']['password'] != $data["password"]) {
                $status = "-998";
                $status_desc = "Email or password is incorrect!";
            } else if ($googleSignin == false && $userObj['User']['is_verified'] != 1) {
                $status = "-997";
                $status_desc = "Email not verified";
            } else {
                list($status, $status_desc, $userGroupData) = $this->getUserGroup($userObj['User']['id']);
                $archivedGroupData = $this->getArchivedUserGroup($userObj['User']['id']);

                if (IS_FIREBASE_ACTIVATED) {
                    $firebaseUserGroup = $this->userGroupFromFirebase($data['profile_id']);
                    $userGroupData = $this->combineUserGroupWithFirebase($userGroupData, $firebaseUserGroup);
                }

                if (!empty($userGroupData)) {
                    $input["groups"] = $userGroupData;
                    $input["archived_groups"] = $archivedGroupData;
                }

                $status = "+000";
                $status_desc = "Login in successful.";

                unset($userObj['User']['password']);
                $input["user"] = $userObj['User'];
            }
        }
       
        $input["status"] = $status;
        $input["status_desc"] = $status_desc;

        if (!empty($error) || $status != "+000") {
            $input["input"] = $data;

            $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);
        }

        $this->set(array(
            'response' => $input,
            '_serialize' => array('response')
        ));
    }

     // resend varificaton link email 
     public function resendemail() {
        
        if (isset($this->request->query['p'])) {
            $data['profile_id'] = $this->request->query['p'];
            $existUser = $this->User->isUserExist($this->request->query['p']);

            if (isset($existUser[0]) && !empty($existUser[0])) {

                // generate a new token
                $device_id = session_id();
                $random_number = rand(100000, 999999);
                $verificationToken = $this->getResetPasswordToken($device_id, $random_number, $data['profile_id']);

                //set the new verification token
                $this->User->setVerificationTokenByProfileId($data['profile_id'], $verificationToken);

                $userObj = $this->User->getUserByProfileId($data["profile_id"]);
                $verificationUrl = HTTP_SITE_URL . '/users/verify?vt=' . $verificationToken . '&p=' . $userObj['User']['profile_id'];

                $params = array();
                $params["first_name"] = $userObj['User']['first_name'];
                $params["profile_id"] = $userObj['User']['profile_id'];
                $params["email_to"] = $userObj['User']['profile_id'];
                $params["email_from"] = SUPPORT_EMAIL;
                $params["subject"] = 'ExpenseCount verification link';
                $params["link"] = $verificationUrl;
                $params["template"] = 'user_verification';
                $params["verification_token"] = $verificationToken;
                $this->sendEmail($params);
                $status_desc = "Verification email send successfully! Please check your inbox.";
            } else {
                $status_desc = "User not found!";
            }
        }

        $this->set('status_desc', $status_desc); 
    }

    // forgotpassword API
    public function forgotpassword() {
        $status = "-1";
        $status_desc = "FAILED";
        $error = "";
        $secretKey = "";
        $data = array();
        $userObj = NULL;

        $object = $this->request->input('json_decode');

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

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

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

            if ($status == -1) {
                list($status, $status_desc, $userObj) = $this->validateForgotpassForm($data);
            }
        }

        if (empty($status)) {
            $user = $this->User->isUserExist($data["profile_id"]);
            if (isset($user[0]) && !empty($user[0])) {
                $device_id = session_id();
                $random_number = rand(100000, 999999);
                $resetPassToken = $this->getResetPasswordToken($device_id, $random_number, $data["profile_id"]);
                $resetPassTokenExpireDateTime = date('Y-m-d h:i:s', strtotime(USER_RESET_PASSWORD_EXPIRE_WITHIN_TIME, strtotime($this->getSystemCurrentTimeStamp())));

                if ($this->User->setPassTokenByProfileId($data["profile_id"], $resetPassToken, $resetPassTokenExpireDateTime)) {
                    
                    $userObj = $this->User->getUserByProfileId($data["profile_id"]);
                    if ($userObj['User']['is_verified'] == 0 && !empty($userObj['User']['password'])) {
                        $status = "-997";
                        $status_desc = "Email not verified;"; // Or probably signedUp with Gmail/AppleID
                    } else {
                        $resetPassUrl = HTTP_SITE_URL . '/users/resetpass/' . $resetPassToken;

                        if(IS_EMAIL_SEND_DURING_RESET_PASSWORD) {
                            $params = array();
                            $params["first_name"] = $userObj['User']['first_name'];
                            $params["profile_id"] = $userObj['User']['profile_id'];
                            $params["email_to"] = $userObj['User']['profile_id'];
                            $params["email_from"] = SUPPORT_EMAIL;
                            $params["subject"] = 'ExpenseCount Reset Password';
                            $params["link"] = $resetPassUrl;
                            $params["template"] = 'reset_password';
                            $params["token_str"] = $resetPassToken;
                            $this->sendEmail($params);
                        }
                        $status = "+000";
                        $status_desc = "SUCCESS.";
                    }
                } else {
                    $status = "-998";
                    $status_desc = "Password doesn't reset!";
                }
            } else {
                $status = "-996";
                $status_desc = "User Not found!";
            }
        }

        unset($userObj['User']['password']);
        $input["user"] = $userObj["User"];

        $input["status"] = $status;
        $input["status_desc"] = $status_desc;


        if (!empty($error) || $status != "+000") {
            unset($input["user"]);
            $input["input"] = $data;

            $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);
        }


        $this->set(array(
            'response' => $input,
            '_serialize' => array('response')
        ));
    }

    // resendVerifyEmail API
    public function resendverifyemail() {
        $status = "";
        $status_desc = "FAILED";
        $error = "";
        $secretKey = "";
        $data = array();
        $invalidGroups = array();
        $userObj = NULL;

        $object = $this->request->input('json_decode');

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

        //check maintenance mood
        if (MAINTENANCE_MOOD) {
            $status = "35";
            $status_desc = "Service is in maintenance mood. Please try again later.";
            $error = $status;
        } else if (empty($data)) {
            $status = "31";
            $status_desc = "Invalid JSON input sent";
        }  else {
            if (!$this->isValidToken($data["access_token"], $data["device_id"], $data["random_number"])) {
                $status = "57"; // token is not valid
                $status_desc = "TOKEN IS  NOT VALID. Please  provide access_token, device_id and  random_number ";
            }

            if (empty($status)) {
                list($status, $status_desc) = $this->validateResendEmailVerifyForm($data);
            }
        }

        if (empty($status)) {
            
            $existUser = $this->User->isUserExist($data["profile_id"]);

            if (isset($existUser[0]) && !empty($existUser[0])) {

                // generate a new token
                $device_id = session_id();
                $random_number = rand(100000, 999999);
                $verificationToken = $this->getResetPasswordToken($device_id, $random_number, $data['profile_id']);

                //set the new verification token
                $this->User->setVerificationTokenByProfileId($data['profile_id'], $verificationToken);

                $userObj = $this->User->getUserByProfileId($data["profile_id"]);
                $verificationUrl = HTTP_SITE_URL . '/users/verify?vt=' . $verificationToken . '&p=' . $userObj['User']['profile_id'];

                $params = array();
                $params["first_name"] = $userObj['User']['first_name'];
                $params["profile_id"] = $userObj['User']['profile_id'];
                $params["email_to"] = $userObj['User']['profile_id'];
                $params["email_from"] = SUPPORT_EMAIL;
                $params["subject"] = 'ExpenseCount verification link';
                $params["link"] = $verificationUrl;
                $params["template"] = 'user_verification';
                $params["verification_token"] = $verificationToken;
                $this->sendEmail($params);

                $status = "+000";
                $status_desc = "SUCCESS";
            } else {
                $status = "-996";
                $status_desc = "User not found!";
            }
        }

        $input["status"] = $status;
        $input["status_desc"] = $status_desc;

        if (!empty($error) || $status != "+000") {
            $input["input"] = $data;

            $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);
        }

        $this->set(array(
            'response' => $input,
            '_serialize' => array('response')
        ));
    }

    private function validateUserField($data)
    {
        //check validity
        $error = "";
        $error_desc = "";

        if (empty($error)) {
            if ( !array_key_exists('user_id', $data)
            ) {
                $error = "6";
                $error_desc = "user_id is required";
            }
        }
        return array($error, $error_desc);
    }
    
    private function validateGroupAddField($data)
    {
        //check validity
        $error = "";
        $error_desc = "";

        if (empty($error)) {
            if ( !array_key_exists('user_id', $data)
            || !array_key_exists('unique_url', $data)
            ) {
                $error = "6";
                $error_desc = "user_id and unique_url are required";
            }
        }
        return array($error, $error_desc);
    }

    private function validateGroupDeleteField($data)
    {
        //check validity
        $error = "";
        $error_desc = "";

        if (empty($error)) {
            if ( !array_key_exists('user_id', $data)
            || !array_key_exists('unique_url', $data)
            ) {
                $error = "6";
                $error_desc = "user_id and unique_url  are required";
            }
        }
        return array($error, $error_desc);
    }

    private function getUserGroup($user_id){

        $userGroupData = array();
        $this->loadModel('UserGroup');
        $this->loadModel('Expense');
        $conditions = array('UserGroup.user_id' => $user_id,'UserGroup.status' => 1);
        $fields = array('UserGroup.unique_url','UserGroup.participant_id','Expense.id', 'Expense.title','Expense.create_date');
        $userGroups = $this->UserGroup->listWithExpense($fields, $conditions);

        $status = "+000";
        $status_desc = "SUCCESS.";

        return array($status, $status_desc, $userGroups);
    }
    private function getArchivedUserGroup($user_id){

        $userGroupData = array();
        $this->loadModel('UserGroup');
        $this->loadModel('Expense');
        $conditions = array('UserGroup.user_id' => $user_id,'UserGroup.status' => 2);
        $fields = array('UserGroup.unique_url','UserGroup.participant_id','Expense.id', 'Expense.title','Expense.create_date');
        return $this->UserGroup->listWithExpense($fields, $conditions);
    }

    // user groups API
    public function groups()
    {
        list($data, $status, $status_desc, $error) = $this->processValidation('GET');

        if (empty($status)) {
            list($status, $status_desc) = $this->validateUserField($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        $input = array();
        if (empty($status)) {
            list($status, $status_desc, $userGroupData) = $this->getUserGroup($data['user_id']);

            if(IS_FIREBASE_ACTIVATED){
                if(!isset($data['expense_type'])) {
                    $data['expense_type'] = '';
                }
                $firebaseUserGroup = $this->userGroupFromFirebase($userObj['profile_id'], $data['expense_type']);
                $userGroupData = $this->combineUserGroupWithFirebase($userGroupData,$firebaseUserGroup);
            }

            if(!empty($userGroupData)){
                $input["data"] = $userGroupData;
            }else{
                $input["data"] = [];
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    // user groups add API; for array of groups
    public function groupsAdd() {
        $data = array();
        $invalidGroups = array();

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

        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }
        if (empty($data["user_id"])) {
            $status = "-994";
            $status_desc = "user_id is required!";
        }

        $expense_type = '';
        if (empty($status)) {
        
            $user = $this->User->getUserByUserId($data["user_id"]);

            if (!empty($user)) {
                //insert into user_groups
                if (isset($data["groups"])) {
                    $groups = $data["groups"];
                    $userDd = $user["User"];
                    $user_id = $userDd["id"];

                    $groupData = array();

                    foreach ($groups as $key => $value) {

                        if (isset($value["unique_url"])) {
                            $this->loadModel('UserGroup');
                            $usergroup = $this->UserGroup->isExistUserGroup($user_id, $value["unique_url"]);

                            if (!$usergroup[0]) { // add only if not exist in database
                                $groupData[$key]["user_id"] = $user_id;
                                $groupData[$key]["unique_url"] = $value["unique_url"];
                                if (isset($value["participant_id"])) {
                                    $groupData[$key]["participant_id"] = $value["participant_id"];
                                }
                            }

                            if (empty($expense_type)) {
                                $expense_type = substr($value["unique_url"], 0 , 1);
                            }
                        } else {
                            $invalidGroups[$key] = $value;
                        }
                    }

                    if (!empty($groupData)) {
                        $this->loadModel('UserGroup');
                        $this->UserGroup->saveMany($groupData);
                    }
                    $status = "+000";
                    $status_desc = "SUCCESS";

                    // increment the version in firebase
                    $expense_name = 'GroupExpense';
                    if ($expense_type == 2) {
                        $expense_name = "MessExpense";
                    } elseif ($expense_type == 3) {
                        $expense_name = "FamilyExpense";
                    }
                    $this->userGroupUpdateOnFirebase($user_id, $expense_name);


                } else {
                    $status = "-995";
                    $status_desc = "Groups data is not provided";
                }
            } else {
                $status = "-996";
                $status_desc = "User not exists";
            }
        }

        if (!empty($error) || $status != "+000") {
            $input["input"] = $data;

            $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);
        }

        $input["invalid_groups"] = $invalidGroups;
        $this->processResponse($input, $data, $status, $status_desc);
    }


    // user group add API
    public function groupadd()
    {
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        
        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }

        if (empty($status)) {
            list($status, $status_desc) = $this->validateGroupAddField($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        // Commenting this code; bcz if group is archieved than adding a group might failed!
        // if (empty($status)) {
        //     $this->loadModel('Expense');
        //     $isExpExist = $this->Expense->find('first', array(
        //         'conditions' => array('Expense.unique_url' => $data['unique_url'])
        //     ));
        //     if(empty($isExpExist)){
        //         $status = "-992"; 
        //         $status_desc = "unique_url is not Exist in Expense table.";
        //     }
        // }

        $input = array();
        if (empty($status)) {
            $this->loadModel('UserGroup');
            $usergroup = $this->UserGroup->isExistUserGroup($data['user_id'],$data['unique_url']);

            if (!$usergroup[0]) {
                $param = array();
                $param['user_id'] = $data['user_id'];
                $param['unique_url'] = $data['unique_url'];
                $param['participant_id'] = $data['participant_id'];
                $newUserGroup = $this->UserGroup->add($param);

                if (!empty($newUserGroup[1])) {
                    $input["data"] = $newUserGroup[1];
                }
                $status = "+000";
                $status_desc = "SUCCESS.";

                // increment the version in firebase
                $expense_name = 'GroupExpense';
                $expense_type = substr($data["unique_url"], 0 , 1);
                if ($expense_type == 2) {
                    $expense_name = "MessExpense";
                } elseif ($expense_type == 3) {
                    $expense_name = "FamilyExpense";
                }
                $this->userGroupUpdateOnFirebase($data['user_id'], $expense_name);
            } else {
                $status = "-992";
                $status_desc = "User Group is Exist.";
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    // user group update API
    public function groupRestore()
    {
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }

        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();

        }
        if (empty($status)) {
            list($status, $status_desc) = $this->validateGroupAddField($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        $input = array();
        if (empty($status)) {
            $this->loadModel('UserGroup');
            $usergroup = $this->UserGroup->isExistUserGroup($data['user_id'],$data['unique_url']);

            if ($usergroup[0]) {
                if(!empty($data['participant_id'])) {
                    $updateFields['participant_id'] = '"' . $data['participant_id'] . '"';
                }
                if(!empty($data['status'])) {
                    $updateFields['status'] =  $data['status'] ;
                }
                $updateConditions = array(
                    'user_id' => $data['user_id'],
                    'unique_url' => $data['unique_url']
                );
                if($this->UserGroup->updateUG($updateFields,$updateConditions)){
                    $status = "+000";
                    $status_desc = "User Group has been updated successfully";
                }
            } else {
                $status = "-991";
                $status_desc = "User Group is not Exist.";
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    // user group delete API
    public function groupdelete()
    {
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        
        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
            
            if (empty($status)) {
                list($status, $status_desc) = $this->validateGroupDeleteField($data);
            }
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        $input = array();
        if (empty($status)) {
            $this->loadModel('UserGroup');
            $usergroup = $this->UserGroup->isExistUserGroup($data['user_id'],$data['unique_url']);

            if ($usergroup[0]) {
                $deleteConditions = array(
                    'user_id' => $data['user_id'],
                    'unique_url' => $data['unique_url']
                );
                if($this->UserGroup->deleteUG($deleteConditions)){
                    $status = "+000";
                    $status_desc = "User Group has been deleted successfully";
                }

                // increment the version in firebase
                $expense_name = 'GroupExpense';
                $expense_type = substr($data["unique_url"], 0 , 1);
                if ($expense_type == 2) {
                    $expense_name = "MessExpense";
                } elseif ($expense_type == 3) {
                    $expense_name = "FamilyExpense";
                }
                $this->userGroupUpdateOnFirebase($data['user_id'], $expense_name);
            } else {
                $status = "-991";
                $status_desc = "User Group is not Exist.";
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }


    protected function combineUserGroupWithFirebase($userGroupData,$firebaseUserGroup)
    {
        $userGroupUniqueUrlArray = array();
        $fugArr = array();
        if(!empty($userGroupData)){
            foreach($userGroupData as $key => $val){
                $userGroupUniqueUrlArray[] = $val['unique_url'];
            }
        }
        if(!empty($firebaseUserGroup)){
            foreach($firebaseUserGroup as $expTypeKey => $expType){
                foreach($expType as $k1 => $item){
                    if(!in_array($item,$userGroupUniqueUrlArray)){
                        $tmp['unique_url'] = $item;
                        $tmp['participant_id'] = '';
                        $fugArr[] = $tmp;
                    }
                }
            }
        }
        $userGroupData = array_merge($userGroupData,$fugArr);
        return $userGroupData;
    }



    public function prelogin() {
        $this->layout = "auth";
    }

    public function prereset() {
        $this->layout = "auth";
    }

    public function verify() {
        
        if (isset($this->request->query['p'])) {
            $profile_id = trim($this->request->query['p']);
            $verificationToken = trim($this->request->query['vt']);
            $user = $this->User->isUserExistByVerificationToken($profile_id, $verificationToken);
            
            if (isset($user[0]) && !empty($user[0])) {
                $this->autoRender = false;
                $this->User->resetVerificationTokenByProfileId($profile_id);
                $this->Session->write('verification', true);
                $this->redirect('/users/login');
            }
        }
    }

    function register() {
        $postData = array();
        $message = '';
        $this->Session->write('system.message', $message);

        if (isset($this->request->data['singupbtn']) && isset($this->request->data['captcha'])) {

            if(isset($_COOKIE['ecc']) && $_COOKIE['ecc'] == $this->request->data['captcha']){

                $apiResponse = array();
                $this->request->data['profile_type'] = 1; // 1 for email, 2 for Gmail Signin
                $data = $this->preparingRegistrationInput($this->request->data);
               
                $apiResponse = $this->callAPI(HTTP_SITE_URL . "/users/signup.json", 'POST', json_encode($data));
                $apiResponseArr = json_decode($apiResponse, true);
                $profile_id = $data['profile_id'];
            
                if (isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) {
                    if (IS_FIREBASE_ACTIVATED) {
                        $data['email'] = $data['profile_id'];
                        unset($data['profile_id']);
                        $postData = $this->registerInFirebase($data);
                    }
                }

                if ((isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) || !empty($postData)) {
    //                $verificationURL = HTTP_SITE_URL . '/users/verify?p='. $apiResponseArr['response']['user']['User']['profile_id'] . '&vt=' .$apiResponseArr['response']['user']['User']['verification_token'];
                    $this->redirect('/users/prelogin');
                } else {
                    $message = '<div class="alert alert-danger alert-dismissible" role="alert">' . $apiResponseArr['response']['status_desc'] . '</div>';
                    $this->Session->write('system.message', $message);
                }
            } else {
               $message = '<div class="alert alert-danger alert-dismissible" role="alert">' . 'Captcha doesn\'t not match' . '</div>';
                $this->Session->write('system.message', $message);
            }
        }
    }



    private function preparingRegistrationInput($requestData) {
        $name = explode(' ', $requestData['name']);
        $data['first_name'] = (isset($name[0])) ? $name[0] : '';
        $data["nick_name"] = (isset($name[0])) ? $name[0] : '';
        unset($name[0]);
        $data['last_name'] = implode(' ', $name);
        $data['profile_id'] = $requestData['email'];
        //$data['password'] = md5($requestData['password']);
        $data['password'] = $requestData['password'];

        $data['action'] = 'register';
        $data['profile_type'] = $requestData['profile_type']; //1=email, 2 = facebook_id, 3= phone_number
        $data["device_id"] = session_id();
        $data["random_number"] = rand(1000, 9999);
        $data["access_token"] = $this->getUserToken($data["device_id"], $data["random_number"]);
        $data["preferences"] = "1|0|1";
        $data["is_verified"] = "0";

        return $data;
    }

    private function preparingLoginInput($requestData) {
        $data['profile_id'] = $requestData['email'];
        if(isset($requestData['password'])) {
            $data['password'] = $requestData['password'];
        } 
        $data['action'] = 'login';
        $data['profile_type'] = 1; //1=email, 2 = facebook_id, 3= phone_number
        $data["device_id"] = session_id();
        $data["random_number"] = rand(1000, 9999);
        $data["access_token"] = $this->getUserToken($data["device_id"], $data["random_number"]);

        return $data;
    }



    private function userGroupFromFirebase($email,$expense_type = '') {
        /*
         * expensecount-312c7/root/{env}/users/{userId}/{url}/rs/{status}
         * env: prod, dev
         * userId: firebase user id
         * ulr: groups unique url
         * status: 0 = deleted, 1 = active
         * you don't need to returns the deleted items
         */

        switch ($expense_type){
            case 1:
                $expenseType = 'ge';
                break;
            case 2:
                $expenseType = 'me';
                break;
            case 3:
                $expenseType = 'fe';
                break;
            default:
                $expenseType = '';
        }

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

        $user = $this->firebase->getAuth()->getUserByEmail($email);

        $newPost = $database->getReference(FIREBASE_DB_PATH);
        $current_row = $newPost->getChild('users/'.$user->uid);
        $current_ver = $current_row->getValue();

        $newGroup = array();
        if ($expenseType != '')  {
            if( !empty($current_ver[$expenseType]) ) {
                foreach($current_ver[$expenseType] as $k => $item){
                    if( isset($item['rs']) && ($item['rs']==1) ) {
                        $newGroup[$expenseType][] = $k;
                    }
                }
            }
        } else {
            foreach($current_ver as $expTypeKey => $expType){
                foreach($expType as $k1 => $item){
                    if( isset($item['rs']) && ($item['rs']==1) ) {
                        $newGroup[$expTypeKey][] = $k1;
                    }
                }
            }
        }

        return $newGroup;
    }

    private function registerInFirebase($requestData) {
        $this->initializeFirebase();
        return $this->firebase->getAuth()->createUserWithEmailAndPassword($requestData['email'], $requestData['password']);
    }

    public function loginInFirebase($data) {
        $this->initializeFirebase();
        return $this->firebase->getAuth()->verifyPassword($data['email'], $data['password']);
    }

    public function login() {
        $this->layout = "auth";
        $message = '';
        $userData = array();
        $this->Session->write('system.message', '');

        if (isset($this->request->data['singinbtn']) || (!isset($this->request->data['password']) && isset($this->request->data['email']))) {
            
            $data = $this->preparingLoginInput($this->request->data);
            if(!isset($this->request->data['password'])) {
                $this->autoRender = false;
            }

            $apiResponse = $this->callAPI(HTTP_SITE_URL . "/users/signin.json", 'POST', json_encode($data));
            $apiResponseArr = json_decode($apiResponse, true);

            if (isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) {
                $this->Cookie->delete('Expenses'); // clear the cookie before setting a new one if it already exists
                if(isset($this->request->data['remme']) && ($this->request->data['remme'] == 'on') ) {
                    $cookie_name = "ecc_auto_login";
                    $cookie_value = $this->request->data['email'];
                    setcookie($cookie_name, $cookie_value, strtotime(REMEMBER_ME_EXPIRE_WITHIN_TIME), "/");
                }

                $this->Session->write('userData', $apiResponseArr['response']['user']);
                $message = '<div class="alert alert-success alert-dismissible" role="alert">' . $apiResponseArr['response']['status_desc'] . '</div>';
                $this->Session->write('system.message', $message);
                $this->Session->write('system.is_now_login', true);
                if(isset($this->request->data['password'])) {
                    $this->redirect('/pages/myExpenses');
                } else {
                    return true;
                }
            } else {
                if (IS_FIREBASE_ACTIVATED) {
                    $data['email'] = $data['profile_id'];
                    unset($data['profile_id']);
                    $userData = $this->loginInFirebase($data);
                    $userData->id = $userData->uid;
                }
                if (!empty($userData)) {
                    if(isset($this->request->data['remme']) && ($this->request->data['remme'] == 'on') ) {
                        $cookie_name = "ecc_auto_login";
                        $cookie_value = $this->request->data['email'];
                        setcookie($cookie_name, $cookie_value, strtotime(REMEMBER_ME_EXPIRE_WITHIN_TIME), "/");
                    }

                    $this->Session->write('userData', $this->objectToArray($userData));
                    $message = '<div class="alert alert-success alert-dismissible" role="alert">' . 'Login is Successful' . '</div>';
                    $this->Session->write('system.message', $message);
                    $this->Session->write('system.is_now_login', true);
                    $this->redirect('/pages/myExpenses');
                } else {
                    $message = '<div class="alert alert-danger alert-dismissible" role="alert">' . __("LBL_INCORRECT_EMAIL") . '</div>';
                    $this->Session->write('system.message', $message);
                    if(!isset($this->request->data['password'])) {
                        return $message;
                    }
                }
            }
        } else {
            if(isset($_COOKIE['ecc_auto_login'])){
                $profile_id = $_COOKIE['ecc_auto_login'];
                $userObj = $this->User->isUserExist($profile_id);
                if($userObj[0]){
                    $this->Session->write('userData', $userObj[1]['User']);
                    $this->redirect('/pages/myExpenses');
                }
            }
            
            $this->set('verification',$this->Session->read('verification'));
            
            $this->Session->write('verification',false);
        }
    }

    public function logout() {
        $message = '';
        $this->autoRender = true;
        $this->Session->write('system.message', '');
        $session_user_id = ($this->Session->read('userData.id')) ? $this->Session->read('userData.id') : 0;
        if ($session_user_id != '') {
            $this->Cookie->delete('Expenses');
            setcookie("ecc_auto_login", "", (time() - 3600), "/");
            $this->Session->delete('userData');
            $message = '<div class="alert alert-success alert-dismissible" role="alert">' . __("LBL_LOGOUT_MESSAGE") . '</div>';
            $this->Session->write('system.message', $message);
            $this->Session->write('system.is_now_login', false);
            $this->redirect('/users/login');
        }
    }

    private function preparingForgotpassInput($requestData) {
        $data['profile_id'] = trim($requestData['email']);
        $data['action'] = 'forgotpass';
        $data['profile_type'] = 1; //0=email, 1=gmail, 2=facebook, 3=phone
        $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 forgotpass() {
        $this->layout = "auth";
        $message = '';
        $this->Session->write('system.message', $message);
        if (isset($this->request->data['forgotpassbtn'])) {

            $apiResponse = array();

            $data = $this->preparingForgotpassInput($this->request->data);

            $apiResponse = $this->callAPI(HTTP_SITE_URL . "/users/forgotpassword.json", 'POST', json_encode($data));
            $apiResponseArr = json_decode($apiResponse, true);

            if (isset($apiResponseArr['response']['status']) && ($apiResponseArr['response']['status'] == '+000')) {

//                $resetPassURL = HTTP_SITE_URL . '/users/resetpass/' . $apiResponseArr['response']['user']['User']['resetPassToken'];

                $this->redirect('/users/prereset');
            } else {
                $message = '<div class="alert alert-danger alert-dismissible" role="alert">' . $apiResponseArr['response']['status_desc'] . '</div>';
                $this->Session->write('system.message', $message);
            }
        }
    }

    public function resetpass($resetPassToken) {
        $this->layout = "auth";
        $user = $this->User->isUserExistByResetPassToken($resetPassToken);
        $this->set(compact('resetPassToken'));
        $this->Session->write('system.message', '');

        if (isset($user[0]) && !empty($user[0])) {
            if (isset($this->request->data['resetpassbtn'])) {
                $password = trim($this->request->data['password']);
                $confirm_password = trim($this->request->data['confirm_password']);

                if ($password == $confirm_password) {
                    $profile_id = $user[1]['User']['profile_id'];
                    $resetpass_token_expire_date = $user[1]['User']['resetpass_token_expire_date'];
//                    $this->getSystemCurrentTimeStamp();

                    if ($this->getSystemCurrentTimeStamp() < $resetpass_token_expire_date) {

                        if ($this->User->setPasswordByProfileId($profile_id, md5($password))) {
                            $this->User->resetPassTokenByProfileId($profile_id);

                            $message = '<div class="alert alert-success alert-dismissible" role="alert">' . 'Password has changed' . '</div>';
                            $this->Session->write('system.message', $message);
                            $this->redirect('/users/login');
                        }
                    }
                } else {
                    $message = '<div class="alert alert-danger alert-dismissible" role="alert">' . 'Your Password doesn\'t match' . '</div>';
                    $this->Session->write('system.message', $message);
                    $this->redirect($this->referer());
                }
            }
        } else {
            $message = '<div class="alert alert-danger alert-dismissible" role="alert">' . 'Your Token is wrong' . '</div>';
            $this->Session->write('system.message', $message);
            $this->redirect($this->referer());
        }
    }

    public function assignGroup() {
        
    }

    public function unAssignGroup() {
        
    }

    public function subscribe() {
        
    }

    // action  should be "login" , "register", "social_media"
    private function validateRegisterForm($data) {

        //check validity
        $error = "";
        $error_desc = "";
        $action = "";

        $userObj = NULL;

        if (empty($data)) {
            $error = "005";
            $error_desc = "input data array is empty";
        }

        //Check action field
        if (empty($error) && isset($data["action"])) {
            $action = $data["action"];
        } else {
            $error = "061";
            $error_desc = "action field is required as parameter";
        }

        if ($action == "login") {
            if (empty($error)) {

                if (!array_key_exists('profile_type', $data)
                    || !array_key_exists('profile_id', $data)
                    || !array_key_exists('password', $data)
                    || !array_key_exists('access_token', $data)
                    || !array_key_exists('device_id', $data)
                    || !array_key_exists('random_number', $data)
                ) {
                    $error = "6";
                    $error_desc = "missing some data!";
                }
            }
        } else if ($action == "register") {
            if (empty($error)) {

                if (!array_key_exists('profile_type', $data)
                    || !array_key_exists('profile_id', $data)
                    || !array_key_exists('access_token', $data)
                    || !array_key_exists('device_id', $data)
                    || !array_key_exists('random_number', $data)
                ) {

                    $error = "6";
                    $error_desc = "profile_type, profile_id, access_token, device_id, random_number and preferences are required";
                }

                if (isset($data["password"]) && !array_key_exists('password', $data)) {
                    $error = "6";
                    $error_desc = "password is required";
                }
            }

        } else if ($action == "social_media") {
            if (empty($error)) {
                if (!array_key_exists('profile_id', $data)
                    || !array_key_exists('access_token', $data)
                    || !array_key_exists('device_id', $data)
                    || !array_key_exists('random_number', $data)
                    || !array_key_exists('preferences', $data)
                ) {

                    $error = "6";
                    $error_desc = "profile_type,profile_id,access_token,device_id,random_number and preferences are required";
                }
            }

            if (empty($error)) {

                list($is_user_exist, $userObj) = $this->User->isUserExist($data["profile_id"]);

                if ($is_user_exist) {
                    $error = "60";
                    $error_desc = "User Already Exist";
                } else {

                    //Insert User  Record

                    $form["first_name"] = "";
                    $form["last_name"] = "";
                    $form["profile_type"] = trim($data["profile_type"]);
                    ;
                    $form["profile_id"] = trim($data["profile_id"]);

                    $form["preferences"] = trim($data["preferences"]);

                    $form["is_verified"] = 1;
                    $form["nick_name"] = "";

                    $crash["ip"] = $this->getClientIp();
                    $crash["device_info"] = $this->getUserAgent();

                    $form["create_date"] = $this->getSystemCurrentTimeStamp();
                    $form["update_date"] = $this->getSystemCurrentTimeStamp();
                }
            }
        }


        if (empty($error)) {

            if (($action != "login") && ($action != "register") &&
                    (mb_strlen(trim($data["first_name"]), 'UTF-8') < 1 || mb_strlen(trim($data["first_name"]), 'UTF-8') > 30 ||
                    mb_strlen(trim($data["last_name"]), 'UTF-8') < 1 || mb_strlen(trim($data["last_name"]), 'UTF-8') > 30 )) {
                $error = "7";
            } else if (mb_strlen(trim($data["profile_type"]), 'UTF-8') != 1) {
                $error = "7";
            } else if (isset($data["password"]) && mb_strlen(trim($data["password"]), 'UTF-8') < 4) {
                $error = "7";
            }
        }

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

    // action  should be "forgotpass"
    private function validateForgotpassForm($data) {

        //check validity
        $error = "";
        $error_desc = "";
        $action = "";

        $userObj = NULL;

        if (empty($data)) {
            $error = "5";
        }

        //Check action field
        if (empty($error) && isset($data["action"])) {
            $action = $data["action"];
        } else {
            $error = "61";
            $error_desc = "action field is required as parameter";
        }

        if ($action == "forgotpass") {
            
        }

        if (empty($error)) {

            if (mb_strlen(trim($data["profile_type"]), 'UTF-8') != 1) {
                $error = "7";
                $error_desc = "profile type is not valid";
            }
        }


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


    private function validateResendEmailVerifyForm($data) {
        $error = "";
        $error_desc = "";
    
        if (!isset($data['profile_id'])) {
            $error = "8";
            $error_desc = "profile_id is not valid!";
        }

        if (!filter_var($data['profile_id'], FILTER_VALIDATE_EMAIL)) {
            $error = "9";
            $error_desc = "profile_id is not valid!";
        }

        if (mb_strlen(trim($data["profile_type"]), 'UTF-8') != 1) {
            $error = "7";
            $error_desc = "profile type is not valid!";
        }

        return array($error, $error_desc);
    }

    private function decryptPassword($encryptedPass) {

        $password = "";

        return $password;
    }

    private function sendEmail($data) {

//        $data = array();
//        $data["email_from"] = $params['email_from'];
//        $data["email_to"] = $params['email_to'];
//        $data["template"] = $params['template'];
//        $data["subject"] = $params['subject'];
//        $data["profile_id"] = $params['profile_id'];
//        $data["link"] = $params['link'];

        $default = array(
            'host' => Configure::read('expensecount.email.smtp.host'),
            'port' => 587,
            'auth' => 'plain',
            'username' => Configure::read('expensecount.email.smtp.username'),
            'password' => Configure::read('expensecount.email.smtp.password'),
            'tsl' => false,
            'transport' => 'Smtp',
            'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
            'returnPath' => Configure::read('expensecount.email.smtp.from'),
            'layout' => false,
            'emailFormat' => 'html',
            //'template' => 'only_text',
            'charset' => 'utf-8',
            'headerCharset' => 'utf-8',
        );

        App::uses('CakeEmail', 'Network/Email');

        //echo $Email->
        $Email = new CakeEmail($default);
        $Email->to(array($data["email_to"]));
        $Email->emailFormat('html');
        $Email->template($data["template"], null)->viewVars(array('data' => $data));
        $Email->subject($data["subject"]);
        $Email->replyTo($data["email_from"]);
        $Email->replyTo($data["email_from"]);
        $Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount.com"));
       // $Email->smtpOptions = $default;
        $Email->delivery = 'Smtp';
        $Email->send();
    }

    public function googlesignin()
    {
        $this->autoRender = false;
        $result = 'fail';
        if($this->request->is('ajax')){

            $this->request->data['profile_type'] = 2; // 1 for email, 2 for Gmail Signin
            $this->request->data['password'] = $this->request->data['profileId'];
            $data = $this->preparingRegistrationInput($this->request->data);
            $data["ip"] = $this->getClientIp();
            $data["device_info"] = $this->getUserAgent();
            $data["create_date"] = $this->getSystemCurrentTimeStamp();
            $data["update_date"] = $this->getSystemCurrentTimeStamp();

            $existUser = $this->User->isUserExistByProfile($data["profile_id"], $data["profile_type"]);

            if (isset($existUser[0]) && empty($existUser[0])) {

                if ($this->User->insertUser($data)) {
                    $result = 'success';
                    $this->User->setVerificationTokenByProfileId($data['profile_id'], $this->request->data['id_token']);
                    $data['verification_token'] = $this->request->data['id_token'];
                    $this->Session->write('userData', $data);
                }
            } elseif(($existUser[0] == true) && is_array($existUser[1])) {
                $this->Session->write('userData', $existUser[1]);
                $result = 'success';
            }
        }
        echo json_encode($result);
    }

    function captcha33($rand){
        $this->autoRender = false;
//        session_start();
//You can customize your captcha settings here

        $captcha_code = '';
        $captcha_image_height = 50;
        $captcha_image_width = 120;
        $total_characters_on_image = 4;

//The characters that can be used in the CAPTCHA code.
//avoid all confusing characters and numbers (For example: l, 1 and i)
        $possible_captcha_letters = 'bcdfghjkmnpqrstvwxyz23456789';
        $captcha_font = 'E:\SERVER\xampp_7.0.22\htdocs\test\expensecountv2\app\webroot\arial.ttf';//'monofont.ttf';./arial.ttf

        $random_captcha_dots = 50;
        $random_captcha_lines = 25;
        $captcha_text_color = "0x142864";
        $captcha_noise_color = "0x142864";


        $count = 0;
        while ($count < $total_characters_on_image) {
            $captcha_code .= substr(
                $possible_captcha_letters,
                mt_rand(0, strlen($possible_captcha_letters)-1),
                1);
            $count++;
        }

        $captcha_font_size = $captcha_image_height * 0.65;
        $captcha_image = @imagecreate(
            $captcha_image_width,
            $captcha_image_height
        );

        /* setting the background, text and noise colours here */
        $background_color = imagecolorallocate(
            $captcha_image,
            255,
            155,
            255
        );

        $array_text_color = $this->hextorgb($captcha_text_color);
        $captcha_text_color = imagecolorallocate(
            $captcha_image,
            $array_text_color['red'],
            
            $array_text_color['green'],
            $array_text_color['blue']
        );

        $array_noise_color = $this->hextorgb($captcha_noise_color);
        $image_noise_color = imagecolorallocate(
            $captcha_image,
            $array_noise_color['red'],
            $array_noise_color['green'],
            $array_noise_color['blue']
        );

        /* Generate random dots in background of the captcha image */
        for( $count=0; $count<$random_captcha_dots; $count++ ) {
            imagefilledellipse(
                $captcha_image,
                mt_rand(0,$captcha_image_width),
                mt_rand(0,$captcha_image_height),
                2,
                3,
                $image_noise_color
            );
        }

        /* Generate random lines in background of the captcha image */
        for( $count=0; $count<$random_captcha_lines; $count++ ) {
            imageline(
                $captcha_image,
                mt_rand(0,$captcha_image_width),
                mt_rand(0,$captcha_image_height),
                mt_rand(0,$captcha_image_width),
                mt_rand(0,$captcha_image_height),
                $image_noise_color
            );
        }

        /* Create a text box and add 6 captcha letters code in it */
        $text_box = imagettfbbox(
            $captcha_font_size,
            0,
            $captcha_font,
            $captcha_code
        );
        $x = ($captcha_image_width - $text_box[4])/2;
        $y = ($captcha_image_height - $text_box[5])/2;
        imagettftext(
            $captcha_image,
            $captcha_font_size,
            0,
            $x,
            $y,
            $captcha_text_color,
            $captcha_font,
            $captcha_code
        );

        /* Show captcha image in the html page */
// defining the image type to be shown in browser widow
        header('Content-Type: image/jpeg');
        imagejpeg($captcha_image); //showing the image
        imagedestroy($captcha_image); //destroying the image instance
//        $_SESSION['captcha'] = $captcha_code;
        $this->Session->write('captcha',$captcha_code);
    }
    function hextorgb33 ($hexstring){
        $integar = hexdec($hexstring);
        return array("red" => 0xFF & ($integar >> 0x10),
            "green" => 0xFF & ($integar >> 0x8),
            "blue" => 0xFF & $integar);
    }


// user delete API
public function delete()
{
    $object = $this->request->input('json_decode');
        
    if (!empty($object)) {
        $data = $this->objectToArray($object);
    }
    
    if(!isset($data['skip_process_validation'])) {
        list($data, $status, $status_desc, $error) = $this->processValidation();
    }

    if (empty($status)) {
        list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
    }

    $input = array();
    if (empty($status)) {
        $this->loadModel('User');
        $this->loadModel('UserGroup');
        $this->loadModel('PermissionTable');
        $this->loadModel('PushToken');

        if($this->User->delete($data['user_id'])){
            $status = "+000";
            $status_desc = "Profile has been deleted successfully";

            $deleteConditions = array(
                'user_id' => $data['user_id']
            );
            $isUsergroupExist = $this->UserGroup->find('count', array(
                'conditions' => $deleteConditions
            ));
            if ($isUsergroupExist) {

               $this->UserGroup->deleteUG($deleteConditions);
            }

            $isPermissionExist = $this->PermissionTable->find('count', $deleteConditions);
            if ($isPermissionExist) {

                $this->PermissionTable->deleteByCondition($deleteConditions);
            }

            $isPushTokenExist = $this->PushToken->find('count', $deleteConditions);
            if ($isPushTokenExist) {
                $this->PushToken->deleteByCondition($deleteConditions);
            }

        }
    }
    $this->processResponse($input, $data, $status, $status_desc);
}

    //signle method for select/add/delete groups 
    public function groupsOperation()
    {

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

        $status = '';
        $status_desc = '';
        $error = null;
        $input = [];
        $doFirebaseVersionIncrement = false;

        /* ---------- PROCESS VALIDATION ---------- */
        if (!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }

        /* ---------- USER VALIDATION ---------- */
        if (empty($status)) {
            list($err, $err_desc, $user) = $this->validateUser($data['user_id']);
            if (!empty($err)) {
                $status = $err;
                $status_desc = $err_desc;
            }
        }

        if (!isset($data["expense_type"])) {
            $status = "-1";
            $status_desc = "expense_type not provided!";
        }
        $user = $this->User->getUserByUserId($data["user_id"]);
        if (empty($user) && empty($user['User'])) {
            $status = "-1";
            $status_desc = "User not found!";
        }
        $this->loadModel('UserGroup');
        //add user groups
        if (empty($status)) {

            $user = $this->User->getUserByUserId($data["user_id"]);

            if (!empty($user)) {
                //insert into user_groups
                if (isset($data["AddGroups"])) {
                    $groups = $data["AddGroups"];
                    $userDd = $user["User"];
                    $user_id = $userDd["id"];

                    $groupData = array();

                    foreach ($groups as $key => $value) {

                        if ($value) {
                            $this->loadModel('UserGroup');
                            $usergroup = $this->UserGroup->isExistUserGroup($user_id, $value);

                            if (!$usergroup[0]) { // add only if not exist in database
                                $groupData[$key]["user_id"] = $user_id;
                                $groupData[$key]["unique_url"] = $value;
                            }
                        }
                    }

                    if (!empty($groupData)) {
                        $this->loadModel('UserGroup');
                        $this->UserGroup->saveMany($groupData);
                        $doFirebaseVersionIncrement = true;
                    }
                }
            }
        }

        //delete user groups
        if (empty($status)) {
            if (!empty($data["DeleteGroups"])) {
                foreach ($data["DeleteGroups"] as $key => $value) {
                    $deleteConditions = array(
                        'user_id' => $user['User']['id'],
                        'unique_url' => $value
                    );
                    $this->UserGroup->deleteUG($deleteConditions);
                    $doFirebaseVersionIncrement = true;
                }
            }
        }

        //archive user groups
        if (empty($status)) {
            if (!empty($data["ArchiveGroups"])) {
                foreach ($data["ArchiveGroups"] as $key => $value) {
                    $updateFields['status'] = $this->group_status['Archived'];
                    $updateConditions = array(
                        'user_id' => $user['User']['id'],
                        'unique_url' => $value
                    );
                    if ($this->UserGroup->updateUG($updateFields, $updateConditions)) {
                        $doFirebaseVersionIncrement = true;
                    }
                }
            }
        }

        //select groups
        if (empty($status)) {
            $this->loadModel('UserGroup');
            $this->loadModel('Expense');
            $conditions = array('UserGroup.user_id' => $user['User']['id'],
                'UserGroup.status' => $this->group_status['Active'],
                'Expense.expense_type'=>$data['expense_type']
                );
            $fields = array('UserGroup.unique_url','UserGroup.participant_id','Expense.id', 'Expense.title','Expense.create_date');
            $status = "+000";
            $status_desc = "SUCCESS";
            $input["groups"] = $this->UserGroup->groupListWithExpense($fields, $conditions);
            $conditions = array('UserGroup.user_id' => $user['User']['id'],
                'UserGroup.status' => $this->group_status['Archived'],
                'Expense.expense_type'=>$data['expense_type']
            );
            $input["archivedGroups"] = $this->UserGroup->listWithExpense($fields, $conditions);


            // increment the version in firebase
            if($doFirebaseVersionIncrement) {
                $expense_name = '';
                $expense_type = $data["expense_type"];
                if($expense_type == 1) {
                    $expense_name = "GroupExpense";
                } elseif ($expense_type == 2) {
                    $expense_name = "MessExpense";
                } elseif ($expense_type == 3) {
                    $expense_name = "FamilyExpense";
                }
                $this->userGroupUpdateOnFirebase($user_id, $expense_name);
            }
            $this->set(array(
                'response' => $input,
                '_serialize' => array('response')
            ));
        }

        $this->processResponseForGroups($input, $data, $status, $status_desc);
    }

    public function processResponseForGroups($responseData, $requestData, $status, $status_desc, $error = null)
    {
        $response = [
            'status' => $status,
            'status_desc' => $status_desc
        ];

        // Always attach response payload (groups)
        if (!empty($responseData)) {
            $response = array_merge($response, $responseData);
        }

        // Failure → attach request input
        if ($status !== "+000") {
            $response['input'] = $requestData;
            $response['error'] = $error;
            $this->apiLogAppCrashData($requestData, $status, $status_desc);
        }

        $this->set([
            'response' => $response,
            '_serialize' => ['response']
        ]);
    }



    // get categories API
    public function getCategories()
    {
        list($data, $status, $status_desc, $error) = $this->processValidation('GET');

        if (empty($status)) {
            list($status, $status_desc) = $this->validateUserField($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        if (empty($status)) {
            if(!$this->isPaid($data['user_id'])){
                $status = '-992';
                $status_desc = 'This feature is only for paid user!';
            }
        }

        $input = array();
        if (empty($status)) {
            list($status, $status_desc, $CategoryData) = $this->getUserCategories($data['unique_url']);

            if(!empty($CategoryData)){
                    foreach ($CategoryData as $CatData){
                        $returnData[] = $CatData['Category'];
                    }
                $input["categories"] = $returnData;
            }else{
                $input["categories"] = [];
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    private function getUserCategories($unique_url){

        $CategoryData = array();
        $this->loadModel('Category');
        $conditions = array('Category.unique_url' => $unique_url);
        $fields = array('Category.id','Category.name','Category.icon_id','Category.version');
        $CategoryData = $this->Category->find('all', array(
            'fields' => $fields,
            'conditions' => $conditions
        ));

        $status = "+000";
        $status_desc = "SUCCESS.";

        return array($status, $status_desc, $CategoryData);
    }

    private function validateCategoryAddField($data)
    {
        //check validity
        $error = "";
        $error_desc = "";

        if (empty($error)) {
            if ( !array_key_exists('name', $data['Categories'])
            || !array_key_exists('icon_id', $data['Categories'])
            //|| !array_key_exists('participant_id', $data)
            ) {
                $error = "6";
                $error_desc = "name and icon_id are required";
            }
        }
        return array($error, $error_desc);
    }

    public function addCategories()
    {
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        
        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }

        if (empty($status)) {
            list($status, $status_desc) = $this->validateCategoryAddField($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        if (empty($status)) {
            if(!$this->isPaid($data['user_id'])){
                $status = '-992';
                $status_desc = 'This feature is only for paid user!';
            }
        }

        if(!preg_match('/^[a-z0-9 .\_]+$/i', $data['Categories']['name'])){
            $status = '-6';
            $status_desc = 'Allow only letters(Unicode), digits, dot (.), space, underscore(_).';
        }

        $input = array();
        if (empty($status)) {
            $this->loadModel('Category');
            $isExist = $this->Category->findByNameAndUniqueUrl($data['Categories']['name'],$data['unique_url']);

            if (!$isExist) {
                $param = array();
                $param['name'] = $data['Categories']['name'];
                $param['unique_url'] = $data['unique_url'];
                $param['icon_id'] = $data['Categories']['icon_id'];
                $param['version'] = 1;
                $category = $this->Category->save($param);

                if (!empty($category)) {
                    list($status, $status_desc, $CategoryData) = $this->getUserCategories($data['unique_url']);
                    if (!empty($CategoryData)) {
                        foreach ($CategoryData as $CatData) {
                            $returnData[] = $CatData['Category'];
                        }
                        $input["categories"] = $returnData;
                    } else {
                        $input["categories"] = [];
                    }
                }
                // $status = "+000";
                // $status_desc = "SUCCESS.";
            } else {
                $status = "-992";
                $status_desc = "Category is Exist.";
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    public function updateCategories()
    {
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        
        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }

        if (empty($status)) {
            list($status, $status_desc) = $this->validateCategoryAddField($data);
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        if (empty($status)) {
            if(!$this->isPaid($data['user_id'])){
                $status = '-992';
                $status_desc = 'This feature is only for paid user!';
            }
        }

        if(!preg_match('/^[a-z0-9 .\_]+$/i', $data['Categories']['name'])){
            $status = '-6';
            $status_desc = 'Allow only letters(Unicode), digits, dot (.), space, underscore(_).';
        }

        $input = array();
        if (empty($status)) {
            $this->loadModel('Category');
            $isExist = $this->Category->findByIdAndUniqueUrl($data['Categories']['id'],$data['unique_url']);
            
            if($data['Categories']['version'] < $isExist['Category']['version']){
                $status = '-992';
                $status_desc = 'conflicts';
            }

            if ($data['Categories']['name'] != $isExist['Category']['name']) {
                $isUnique = $this->Category->findByNameAndUniqueUrl($data['Categories']['name'], $data['unique_url']);
                if ($isUnique) {
                    $status = '-992';
                    $status_desc = 'Already exist!';
                }
            }
            
            if ($isExist && empty($status) && !$isUnique) {
                $param = array();
                $param['name'] = $data['Categories']['name'];
                $param['id'] = $data['Categories']['id'];
                $param['unique_url'] = $data['unique_url'];
                $param['icon_id'] = $data['Categories']['icon_id'];
                $param['version'] = $data['Categories']['version']+1;
                $category = $this->Category->save($param);

                if (!empty($category)) {
                    list($status, $status_desc, $CategoryData) = $this->getUserCategories($data['unique_url']);
                    if (!empty($CategoryData)) {
                        foreach ($CategoryData as $CatData) {
                            $returnData[] = $CatData['Category'];
                        }
                        $input["categories"] = $returnData;
                    } else {
                        $input["categories"] = [];
                    }
                }
                // $status = "+000";
                // $status_desc = "SUCCESS.";
            } else {

                if(empty($status)){
                    $status = "-992";
                $status_desc = "Category is not Exist.";
                }
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }


    // user Category delete API
    public function deleteCategories()
    {
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        
        if(!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }

        if (empty($status)) {
            list($status, $status_desc, $userObj) = $this->validateUser($data['user_id']);
        }

        if (empty($status)) {
            if(!$this->isPaid($data['user_id'])){
                $status = '-992';
                $status_desc = 'This feature is only for paid user!';
            }
        }

        $input = array();
        if (empty($status)) {
            $this->loadModel('Category');
            $isExist = $this->Category->findById($data['category_id']);

            if ($isExist) {
                if($this->Category->delete($data['category_id'])){
                    $status = "+000";
                    $status_desc = "SUCCESS";
                }
            } else {
                $status = "-991";
                $status_desc = "Category is not Exist.";
            }
        }

        $this->processResponse($input, $data, $status, $status_desc);
    }

    private function is_base64_encoded($str) {
        $decoded_str = base64_decode($str);
        $Str1 = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $decoded_str);
        if ($Str1!=$decoded_str || $Str1 == '') {
           return false;
        }
        return true;
     }

    public function register_push_token()
    {

        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        if (!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }
        if (!empty($data) && empty($status)) {
            list($status, $status_desc, $error) = $this->pushTokenRequestValidate($data);
        }

        $response = array();

        if (empty($status)) {
            $this->loadModel('User');
            $user = $this->User->getUserByUserId($data['user_id']);

            if(!empty($user['User'])) {
                $status = "+000";
                $status_desc = 'Token not found.';
                $this->loadModel('PushToken');
                $activeToken = $this->PushToken->checkActiveToken($data['user_id'],$data['device_id'],$data['platform']);
                if (!empty($activeToken['PushToken'])){
                    $status_desc = 'Fetch Token successfully!';
                }

                if(!empty($data['push_token']) && array_key_exists('status', $object)) {
                    try {
                        if (!empty($activeToken['PushToken'])) {
                            // Token exists – update it
                            if ($data['status'] == 0) {
                                $this->PushToken->delete($activeToken['PushToken']['id']);
                                $status_desc = "Push Token Deleted Successfully";
                            } else {
                                $this->PushToken->save(array(
                                    'id' => $activeToken['PushToken']['id'],
                                    'user_id' => $activeToken['PushToken']['user_id'],
                                    'device_id' => $activeToken['PushToken']['device_id'],
                                    'push_token' => $data['push_token'],
                                    'is_active' => $data['status']
                                ));
                                $status_desc = "Push Token Updated Successfully";
                            }

                        } else if (empty($activeToken['PushToken']) && $data['status'] == 1) {
                            // Token does not exist – insert new
                            $this->PushToken->save(array(
                                'user_id' => $data['user_id'],
                                'device_id' => $data['device_id'],
                                'platform' => $data['platform'],
                                'push_token' => $data['push_token'],
                                'is_active' => 1
                            ));
                            $status_desc = "Push Token Registered Successfully";
                        }
                        $status = "+000";
                        $activeToken = $this->PushToken->checkActiveToken($data['user_id'],$data['device_id'],$data['platform']);
                    } catch (Exception $e) {
                        $status_desc = $e->getMessage();
                        $status = "-99";
                    }
                }
            }else{
                $status = '12';
                $status_desc = 'User not found!';
            }


        }

        if ($status != "+000") {
            $this->processResponse($input, $data, $status, $status_desc);
        } else {

            $response["status"] = $status;
            $response["status_desc"] = $status_desc;
            $response["api_version"] = 3;
            $response["data"] = null;
            if (!empty($activeToken['PushToken'])) {
                $response["data"] = $activeToken['PushToken'];
            }

            $this->set(array(
                'response' => $response,
                '_serialize' => array('response')
            ));
        }
    }

    public function pushTokenRequestValidate($object)
    {

        //check validity
        $error = "";
        $error_desc = "";
        $expObj = array();
        $statues = array(0,1);
        if (empty($object['user_id']) && !is_numeric($object['user_id'])) {
            $error = $this->validation_status;
            $error_desc = "user_id must be provided and numeric!";
            $expObj['user_id'] = $error_desc;
        }
        if (empty($object['device_id'])) {
            $error = $this->validation_status;
            $error_desc = "device_id must be provided!";
            $expObj['device_id'] = $error_desc;
        }
        if (!isset($object['platform'])) {
            $error = $this->validation_status;
            $error_desc = "platform must be provided!";
            $expObj['platform'] = $error_desc;
        }
        if (array_key_exists('push_token', $object) && trim($object['push_token']) === '') {
            $error = $this->validation_status;
            $error_desc = "push_token must be provided!";
            $expObj['push_token'] = $error_desc;
        }
        if (array_key_exists('status', $object) && !in_array($object['status'], $statues)) {
            $error = $this->validation_status;
            $error_desc = "status must be 0 or 1!";;
            $expObj['status'] = $error_desc;
        }

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

    public function sendNotification(){
        $object = $this->request->input('json_decode');
        if (!empty($object)) {
            $data = $this->objectToArray($object);
        }
        if (!isset($data['skip_process_validation'])) {
            list($data, $status, $status_desc, $error) = $this->processValidation();
        }
        if (!empty($data) && empty($status)) {
            list($status, $status_desc, $error) = $this->notificationRequestValidate($data);
        }
        $tokens = array();
        $this->loadModel('PushToken');
        if(!empty($data['user_id'])){
            $filter = array('status' => 1,'user_id' => $data['user_id']);
            $db_token = $this->PushToken->getToken($filter);

            if(!empty($db_token)) {
                foreach ($db_token as $token) {
                    $tokens[] = ['user_id'=>$token['PushToken']['user_id'],
                       'device_id'=>$token['PushToken']['device_id'],
                        'token'=> $token['PushToken']['push_token']];
                }
            }
            if(!empty($tokens)) {
                $request_data = $data['data'];
                $response = $this->Notification->sendPushNotification($tokens,$request_data);

            }else{
                $response["status"] = "-99";
                $response["status_desc"] = "Push Token Not Found!";
                $response["input"] = $data;
            }

        }else{
            $response["status"] = $status;
            $response["status_desc"] = $status_desc;
            $response["input"] = $data;
        }

        $this->set(array(
            'response' => $response,
            '_serialize' => array('response')
        ));

    }

    public function notificationRequestValidate($object)
    {

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

        if (empty($object['title'])) {
            $error = $this->validation_status;
            $error_desc = "title must be provided!";
            $expObj['title'] = $error_desc;
        }
        if (empty($object['body'])) {
            $error = $this->validation_status;
            $error_desc = "message must be provided!";
            $expObj['body'] = $error_desc;
        }
        if (array_key_exists('user_id', $object) && empty($object['user_id'])) {
            $error = $this->validation_status;
            $error_desc = "user_id must be provided!";
            $expObj['user_id'] = $error_desc;
        }

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



}




