<?php

class PBReusableModel_User extends CI_Model {

	const USERS = 'users';
	const USERS_TOKENS = 'users_auth_tokens';
	const USERS_EMAILS = 'users_changed_emails';
	const DEVICE_TOKENS = 'user_device_tokens';
	const PARTNERS = 'sq_partners';

    function __construct() {
        parent::__construct();
		$this->load->database();
		$this->load->helper('date');
		$this->load->library('encryption');
		$this->load->helper('url');
		$this->load->model('PBReusableModel_Mail','mail');
		$this->load->model('PBReusableModel_Global','globals');
    }

	public function getUserByEmail($email) {
		$this->load->database();
		$this->db->select('user_id');
		$this->db->from(self::USERS);
		$this->db->where('email',$email);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		return $user;
	}

	public function checkIfPartnerExists($user_id) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::PARTNERS);
		$this->db->where('user_id',$user_id);
		$query = $this->db->get();
		return $query->result();
	}

	public function registerThePartner() {
		$data = $this->input->post();
		$id = $this->get_unused_id();

		$register_data = array(
			'user_id' => $id,
			'username' => 'User'.$id,
			'firstname' => $data['firstname'],
			'lastname' => $data['lastname'],
			'email' => $data['email'],
			'passwd' => $this->authentication->hash_passwd($data['password']),
			'auth_level' => 6,
			'created_at' => date('Y-m-d H:i:s'),
			'modified_at' => date('Y-m-d H:i:s'),
			'opt_in' => true,
			'guest' => 0,
			'gender' => 3
		);

		$manager_data = array(
			'user_id' => $id,
			'brand_id' => $data['brand_id']
		);

		if($this->checkIfEmailExists($data['email'])) {
			$id = $this->getUserByEmail($data['email']);
			$id = $id['user_id'];
			// echo "user id existed and was ".$id;
			$this->db->where('user_id',$id);

			$update_data = array(
				'username' => 'User'.$id,
				'firstname' => $data['firstname'],
				'lastname' => $data['lastname'],
				'auth_level' => 6,
				'modified_at' => date('Y-m-d H:i:s'),
			);

			$updated_manager_data = array(
				'user_id' => $id,
				'brand_id' => $data['brand_id']
			);

			if ($this->db->update(self::USERS, $update_data)) {
				if($this->checkIfPartnerExists($id)){
					$this->db->where('user_id',$id);
					$this->db->update(self::PARTNERS, $updated_manager_data);
					return 3;
				} else {
					$this->db->insert(self::PARTNERS, $updated_manager_data);
					return 1;
				}
				return 3;
			} else {
				return 0;
			}
		} else {
			if ($this->db->insert(self::USERS, $register_data)) {
				if($this->checkIfPartnerExists($id)){
					$this->db->where('user_id',$manager_data['user_id']);
					$this->db->update(self::PARTNERS, $manager_data);
					return 3;
				} else {
					$this->db->insert(self::PARTNERS, $manager_data);
					return 1;
				}
				return 1;
			} else {
				return 0;
			}
		}
	}

	function removeTokenForUser($data) {
		$this->load->database();
		$this->db->delete(self::DEVICE_TOKENS, array('device_token' => $data['device_token']));
		return 1;
	}

	function registerTokenForUser($data) {
		$token_data = array();
		$token_data['user_id'] = $data['user_id'];
		$token_data['device_token'] = $data['device_token'];
		$token_data['device_type'] = $data['device_type'];
		$this->db->insert(self::DEVICE_TOKENS, $token_data);
	}

	function checkIfDeviceTokenForUserExists($data) {
        $this->load->database();
        $this->db->select('*');
        $this->db->where('user_id', $data['user_id']);
        $this->db->where('device_token', $data['device_token']);
		$this->db->from(self::DEVICE_TOKENS);
		$this->db->limit(1);
        $query = $this->db->get();
		if (!$query->row()) {
			$this->registerTokenForUser($data);
		}
	}

	function getPushTokensForUser($user_id) {
		$this->load->database();
		$this->db->select('device_token');
		$this->db->where('user_id', $user_id);
		$this->db->from(self::DEVICE_TOKENS);
		$query = $this->db->get();
		return $query->result();
	}
	// Administration

	public function adminupdateUser($data) {
		$valid_data = array();
		$valid_data['modified_at'] = date('Y-m-d H:i:s');
		$valid_data['firstname'] = $data['firstname'];
		$valid_data['lastname'] = $data['lastname'];
		$valid_data['email'] = $data['email'];
		$valid_data['auth_level'] = $data['auth_level'];
		$valid_data['gender'] = $data['gender'];
		$this->load->database();
		$this->db->where('user_id',$data['user_id']);
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if($this->db->trans_status() === FALSE) {
		    return "0";
		} else {
			if ($this->db->affected_rows() > 0) {
				return "1";
			} else {
				return "2";
			}
		}
	}

	public function admin_registerTheUser() {
		$data = $this->input->post();

		$register_data = array(
			'user_id' => $this->get_unused_id(),
			'firstname' => $data['firstname'],
			'lastname' => $data['lastname'],
			'email' => $data['email'],
			'passwd' => $this->authentication->hash_passwd($data['password']),
			'auth_level' => $data['auth_level'],
			'created_at' => date('Y-m-d H:i:s'),
			'modified_at' => date('Y-m-d H:i:s'),
			'opt_in' => true,
			'gender' => $data['gender'],
		);
		$this->load->database();
		if ($this->db->insert(self::USERS, $register_data)) {
			return true;
		} else {
			return false;
		}
	}
	// Administration

	public function getFullUserObjectByID($id) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS);
		$this->db->where('user_id',$id);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		return $user;
	}

	// Datatable
	function users_count() {
		$this->load->database();
        $this->db->select('*');
        $this->db->from(self::USERS);
        $query = $this->db->get();
        return $query->num_rows();
    }

	function datatables_allusers($limit,$start,$col,$dir) {
		$this->load->database();
        $this->db->select('*');
        $this->db->from(self::USERS);
		$this->db->limit($limit,$start);
		$this->db->order_by($col,$dir);
        $query = $this->db->get();
        if($query->num_rows()>0) {
            return $query->result();
        } else {
            return null;
        }
    }

	function datatables_users_search($limit,$start,$search,$col,$dir) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS);
		$this->db->like('user_id',$search);
		$this->db->or_like('firstname',$search);
		$this->db->or_like('lastname',$search);
		$this->db->or_like('email',$search);
		$this->db->or_like('auth_level',$search);
		$this->db->limit($limit,$start);
		$this->db->order_by($col,$dir);
		$query = $this->db->get();
        if($query->num_rows()>0) {
            return $query->result();
        } else {
            return null;
        }
    }

	function datatables_users_search_count($search) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS);
		$this->db->like('user_id',$search);
		$this->db->or_like('firstname',$search);
		$this->db->or_like('lastname',$search);
		$this->db->or_like('email',$search);
		$this->db->or_like('auth_level',$search);
		$query = $this->db->get();
        return $query->num_rows();
    }
	// Datatable

	function getUsers() {
        $this->load->database();
        $this->db->select('*');
        $this->db->from(self::USERS);
        $query = $this->db->get();
        return $query->result();
	}

	public function isTokenValid($token) {
        $this->load->database();
        $this->db->select('*');
        $this->db->from(self::USERS_TOKENS);
		$this->db->where('user_auth_token',$token);
		$this->db->where('active',1);
        $query = $this->db->get();
        return $query->result();
	}

	public function getUserObject($user_string) {
		$selected_columns = [
			'email',
			'firstname',
			'lastname',
			'auth_level',
			'user_id',
			'banned',
			'avatar',
			// 'guest',
		];
		$this->load->database();
		$this->db->select($selected_columns);
		$this->db->from(self::USERS);
		$this->db->where('LOWER(email) =',strtolower($user_string));
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		$user['avatar'] = base_url()."images/uploads/".$user['avatar'];
		return $user;
	}

	function generateUserActivationCode() {
		$characters = 'ABCEFHJKMNPRTUVWXY493712568';
		$string = '';
		for ($i = 0; $i < 6; $i++) {
		    $string .= $characters[rand(0, strlen($characters) - 1)];
		}
		return $string;
	}

	public function get_unused_id() {
        $this->load->database();
        // Create a random user id between 1200 and 4294967295
        $random_unique_int = 2147483648 + mt_rand( -2147482448, 2147483647 );
        // Make sure the random user_id isn't already in use
		$query = $this->db->get_where('users', array('user_id' => $random_unique_int), 1, 0);
        if( $query->num_rows() > 0) {
            $query->free_result();
            // If the random user_id is already in use, try again
            return $this->get_unused_id();
        }
        return $random_unique_int;
    }

	public function registerTheUser() {
		$data = $this->input->post();
		if ($data['opt_in'] == 'true') {
			$data['opt_in'] = 1;
		} else {
			$data['opt_in'] = 0;
		}
		$new_id = $this->get_unused_id();
		$register_data = array(
			'user_id' => $new_id,
			'firstname' => $data['firstname'],
			'lastname' => $data['lastname'],
			'email' => $data['email'],
			'passwd' => $this->authentication->hash_passwd($data['password']),
			'activation_code' => $this->users->generateUserActivationCode(),
			'auth_level' => 2,
			'created_at' => date('Y-m-d H:i:s'),
			'modified_at' => date('Y-m-d H:i:s'),
			'opt_in' => $data['opt_in'],
			'gender' => 3,
			'username' => 'User'.$new_id
		);
		$this->load->database();
		if ($this->db->insert(self::USERS, $register_data)) {
			$mail = array();
			$mail['email'] = $register_data['email'];
			$mail['activation_code'] = $register_data['activation_code'];
			$this->mail->sendActivationCodeEmail($mail);
			return $this->getUserObject($data['email']);
		} else {
			return false;
		}
	}

	public function convertTheGuestUserToFullAccount() {
		$user = $this->getUserByHeaders();
		$user_id = $user['user_id'];
        if ($this->globals->checkHeaders($user_id)) {
			$data = $this->input->post();
			$this->load->database();
			$this->db->select('*');
			$this->db->from(self::USERS);
			$this->db->where("user_id",$user_id);
			$code = $this->users->generateUserActivationCode();
			$register_data = array(
				'firstname' => $data['firstname'],
				'lastname' => $data['lastname'],
				'email' => $data['email'],
				'passwd' => $this->authentication->hash_passwd($data['passwd']),
				'activation_code' => $code,
				'auth_level' => 2,
				'created_at' => date('Y-m-d H:i:s'),
				'modified_at' => date('Y-m-d H:i:s'),
				'opt_in' => $data['opt_in'],
				'gender' => $data['gender'],
				'username' => 'User'.$user_id
			);
			$this->db->update(self::USERS,$register_data);
			if ($this->db->affected_rows() > 0) {
				$mail = array();
				$mail['email'] = $data['email'];
				$mail['activation_code'] = $code;
				$this->mail->sendActivationCodeEmail($mail);
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	public function registerTheGuestUser() {
		$data = $this->input->post();
		$data['opt_in'] = 0;
		$new_user_id = $this->get_unused_id();
		$register_data = array(
			'user_id' => $new_user_id,
			'firstname' => "Guest".$new_user_id,
			'lastname' => "",
			'email' => "",
			'passwd' => "",
			'activation_code' => "",
			'auth_level' => 1,
			'created_at' => date('Y-m-d H:i:s'),
			'modified_at' => date('Y-m-d H:i:s'),
			'opt_in' => $data['opt_in'],
			'gender' => 0,
			'username' => 'Guest'.$new_user_id
		);
		$this->load->database();
		if ($this->db->insert(self::USERS, $register_data)) {
			$headers = $this->input->request_headers();
			$token = $this->appsecurity->isAppTokenValid($headers['Api-Token']);
			// var_dump($token);
			if ($token) {
				$token_data = array();
				$token_data['user_id'] = $new_user_id;
				$token_data['partner_id'] = $token[0]->id;
				$token_data['user_agent'] = $headers['User-Agent'];;
				$token_data['host'] = $headers['Host'];;
				$new_auth_token = $this->appsecurity->generateUserToken($token_data);
				$guest = array();
				$guest['user_api_token'] = $new_auth_token;
				$guest['firstname'] = "Guest".$new_user_id;
				return $guest;
			} else {
				return false;
			}

		} else {
			return false;
		}
	}

	public function checkIfEmailExists($email) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS);
		$this->db->where('email',$email);
		$query = $this->db->get();
		return $query->result();
	}

	public function isActivationCodeValid($data) {
        $this->load->database();
        $this->db->select('*');
        $this->db->from(self::USERS);
		$this->db->where('activation_code',$data['activation_code']);
		$this->db->where('email',$data['email']);
        $query = $this->db->get();
        return $query->result();
	}

	public function activateTheUser($data) {
		$valid_data = array();
		$valid_data['auth_level'] = 3;
		$valid_data['modified_at'] = date('Y-m-d H:i:s');
		$valid_data['activation_code'] = '';
		// $valid_data['guest'] = '0';
		$this->load->database();
		$this->db->where('activation_code',$data['activation_code']);
		$this->db->where('email',$data['email']);
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			return true;
		} else {
			return false;
		}
	}

	public function recoverTheUser($email) {
		$valid_data = array();
		$valid_data['passwd_recovery_code'] = $this->users->generateUserActivationCode();
		$valid_data['passwd_recovery_date'] = date('Y-m-d H:i:s');
		$this->load->database();
		$this->db->where('email',$email);
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			$mail = array();
			$mail['email'] = $email;
			$mail['recovery_code'] = $valid_data['passwd_recovery_code'];
			$this->mail->sendForgottenDetailsEmail($mail);
			return true;
		} else {
			return false;
		}
	}

	public function isRecoveryCodeValid($data) {
        $this->load->database();
        $this->db->select('*');
        $this->db->from(self::USERS);
		$this->db->where('passwd_recovery_code',$data['recovery_code']);
		$this->db->where('email',$data['email']);
        $query = $this->db->get();
        return $query->result();
	}

	public function getUserByID($id) {
		$this->load->database();
		$this->db->select('email');
		$this->db->from(self::USERS);
		$this->db->where('user_id',$id);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		return $user;
	}

	public function getUserByToken($token) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS_TOKENS);
		$this->db->where('user_auth_token',$token);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		$email = $this->getUserByID($user['user_id']);
		return $email;
	}

	public function getUserByHeaders() {

		$headers = $this->input->request_headers();
		$user_token = "";
		if (isset($headers['User-Api-Token'])) {
			$user_token = $headers['User-Api-Token'];
		}

		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS_TOKENS);
		$this->db->where('user_auth_token',$user_token);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		// $email = $this->getUserByID($user['user_id']);
		return $user;
	}

	public function getFullUserByID($id) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS);
		$this->db->where('user_id',$id);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		return $user;
	}

	public function getFullUserByToken($token) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS_TOKENS);
		$this->db->where('user_auth_token',$token);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		$email = $this->getFullUserByID($user['user_id']);
		return $email;
	}

	public function resetTheUsersPassword() {
		$valid_data = array();
		$valid_data['passwd_modified_at'] = date('Y-m-d H:i:s');
		$valid_data['passwd_recovery_code'] = '';
		$valid_data['passwd'] = $this->authentication->hash_passwd($this->input->post('password'));
		$this->load->database();
		$this->db->where('email',$this->input->post('email'));
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			$this->mail->sendResetPasswordEmail($this->input->post('email'));
			return true;
		} else {
			return false;
		}
	}

	public function changeTheUsersPassword($email) {
		$valid_data = array();
		$valid_data['passwd_modified_at'] = date('Y-m-d H:i:s');
		$valid_data['passwd'] = $this->authentication->hash_passwd($this->input->post('new_password'));
		$this->load->database();
		$this->db->where('email',$email);
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			return true;
		} else {
			return false;
		}
	}

	public function updateUsersDetails() {
		$valid_data = array();
		$valid_data['modified_at'] = date('Y-m-d H:i:s');
		$valid_data['firstname'] = $this->input->post('firstname');
		$valid_data['lastname'] = $this->input->post('lastname');
		$valid_data['email'] = $this->input->post('email');
		$valid_data['gender'] = $this->input->post('gender');
		$this->load->database();
		$this->db->where('email',$this->input->post('email'));
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			return true;
		} else {
			return false;
		}
	}

	public function updateUsersDetailsWithEmail($current_email) {
		$valid_data = array();
		$valid_data['modified_at'] = date('Y-m-d H:i:s');
		$valid_data['firstname'] = $this->input->post('firstname');
		$valid_data['lastname'] = $this->input->post('lastname');
		$valid_data['activation_code'] = $this->users->generateUserActivationCode();
		$valid_data['auth_level'] = 2;
		$valid_data['gender'] = $this->input->post('gender');
		$valid_data['email'] = $this->input->post('email');
		$this->load->database();
		$this->db->where('email',$current_email);
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			$user = $this->getUserObject($this->input->post('email'));
			$user['changed_email'] = $this->input->post('email');
			$mail = array();
			$mail['email'] = $this->input->post('email');
			$mail['activation_code'] = $valid_data['activation_code'];
			$this->mail->sendChangeEmailEmail($mail);
			// $this->requestEmailChangeForUser($user);
			return true;
		} else {
			return false;
		}
	}

	public function checkIfAnEmailRequestIsAlreadyActiveForUser($user_id) {
		$this->load->database();
		$this->db->select('*');
		$this->db->from(self::USERS_EMAILS);
		$this->db->where('user_id',$user_id);
		$this->db->limit(1);
		$query = $this->db->get();
		$user = $query->row_array();
		if ($user) {
			return true;
		} else {
			return false;
		}
	}

	public function updateTheUserAvatar($data) {
		$valid_data = array();
		$valid_data['modified_at'] = date('Y-m-d H:i:s');
		$valid_data['avatar'] = $data['avatar'];
		$valid_data['user_id'] = $data['user_id'];
		$this->load->database();
		$this->db->where('user_id',$data['user_id']);
		$this->db->update(self::USERS, $valid_data);
		$this->db->trans_complete();
		if ($this->db->trans_status() === TRUE) {
			return true;
		} else {
			return false;
		}

	}

}
