<?php
class User extends MY_Model
{
	const DB_TABLE = 'users';
    const DB_TABLE_PK = 'user_id';

	public $roles = array();
	public $actions = array();

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

		$this->shopper_group_id = 1;
		$this->active 			= 1;
	}

	public function load($id)
	{
		$success = parent::load($id);

		$this->roles = $this->fetchUserRoleIds();
		$this->actions = $this->fetchAllUserActions();

		return $success;
	}

	public function LoadByUsername($username)
	{
	  	if(!$username)
		{
			return false;
		}

	  	$query = $this->db->query("SELECT * FROM users WHERE username=?", array($username));

	  	if($query->num_rows() > 0)
	  	{
	  		foreach($query->result() as $row)
	  		{
	  			//load the first item
		  		$success       = $this->populate($row);
		  		$this->roles   = $this->fetchUserRoleIds();
		  		$this->actions = $this->fetchAllUserActions();

		  		return $success;
	  		}
	  	}
	  	else
	  	{
	  		return false;
	  	}
	}

	public function LoadByEmail($email)
	{
		if(!$email)
		{
			return false;
		}

	  	$query = $this->db->query("SELECT * FROM users WHERE email=?", array($email));

	  	if($query->num_rows() > 0)
	  	{
	  		foreach($query->result() as $row)
	  		{
	  			//load the first item
		  		$success       = $this->populate($row);
		  		$this->roles   = $this->fetchUserRoleIds();
		  		$this->actions = $this->fetchAllUserActions();

		  		return $success;
	  		}
	  	}
	  	else
	  	{
	  		return false;
	  	}
	}

    public function authenticate($username, $password, $admin=true)
    {
    	$this->load->helper("password");

    	if(trim($username) == "")
    	{
    		return false;
    	}

	    $result = $this->db->query("SELECT *, CONCAT(fname, ' ', lname) AS fullname FROM users WHERE active='1' AND username=?", array($username));

	    if($result->num_rows() > 0)
	    {
	    	$row = $result->row();
	    	$saved_password = $row->password;

			if(password_verify($password, $saved_password))
			{
			    $u = new User();
				$u->load($row->user_id);

				if($admin && $u->has(ACTION_ADMIN_LOGIN))
				{
					return $u;
				}
				else if(!$admin && $u->has(ACTION_LOGIN))
			    {
			    	return $u;
			    }
			    else
			    {
			    	return false;
			    }
			}
			else
			{
			    return false;
			}
	    }
	    else
	    {
	    	return false;
	    }

	    return false;
    }

    /**
	 * Retrieve all Role ID's assigned to this user
	 */
	private function fetchUserRoleIds()
	{
		$key = "acl_roles:" . $this->user_id;

		if(($roles = $this->cache->get($key)) === false)
		{
			$roles = array();
			$query = "SELECT `acl_role_id` FROM `acl_user_role` WHERE `user_id`=?";

			$role_ids = $this->db->query($query, array($this->user_id));

			if(is_object($role_ids) == false)
			{
				return false;
			}

			foreach($role_ids->result() as $row)
			{
				$roles[] = $row->acl_role_id;
			}

			$this->cache->save($key, $roles, 86400);
		}

		return $roles;
	}

	/**
	 * Retrieves an array of all unique action_id's that a user "has"
	 */
	private function fetchAllUserActions()
	{
		//if no roles exist, maybe we didn't load roles yet - try loading
		if(!isset($roles) || count($roles) == 0)
		{
			$roles = self::fetchUserRoleIds($this->user_id);
		}

		//if no roles exist still, bail out - this user has none
		if($roles == false || !isset($roles) || count($roles) == 0 ) return array();

		$key = "acl_actions:" . $this->user_id;

		if(($actions = $this->cache->get($key)) === false)
		{
			$query = sprintf("SELECT `acl_action_id` FROM `acl_role_action` WHERE `acl_role_id` IN (%s) GROUP BY `acl_action_id`", implode(',',$roles));
			$action_ids = $this->db->query($query);

			$actions = array();

			if(is_object($action_ids) == false)
			{
				return false;
			}

			foreach($action_ids->result() as $row)
			{
				$actions[] = $row->acl_action_id;
			}

			$this->cache->save($key, $actions, 86400);
		}

		return $actions;
	}

	/**
	 * Checks ALL provided action permissions and returns TRUE only if all actions are possible
	 */
	public function has()
	{
		$actions = array();
		foreach(func_get_args() as $arg)
		{
			if( is_array($arg) )
				$actions = array_merge($actions, $arg);
			else
				$actions[] = $arg;
		}
		$result = true;
		foreach($actions as $action_id)
			$result = $result && (array_search($action_id, $this->actions, true)!==false);
		return $result;
	}

    /**
	 * Checks ANY provided action permissions and returns TRUE if Any actions are possible
	 */
	public function has_any()
	{
		$actions = array();
		foreach(func_get_args() as $arg)
		{
			if( is_array($arg) )
				$actions = array_merge($actions, $arg);
			else
				$actions[] = $arg;
		}
		$intersect = array_intersect($actions, $this->actions);
		return (count($intersect) > 0);
	}

	public function has_role($acl_role_id)
    {
    	foreach($this->roles as $role)
    	{
    		if($role == $acl_role_id)
    		{
    			return true;
    		}
    	}

    	return false;
    }

    function search($q)
	{
		if($q == null)
		{
			return array();
		}

		$q = $this->db->escape_str($q);

		$query = $this->db->query("SELECT *
		                          FROM users
		                          WHERE
			                          fname LIKE '%$q%' OR
			                          lname LIKE '%$q%' OR
			                          username LIKE '%$q%' OR
			                          company LIKE '%$q%' OR
			                          email LIKE '%$q%'
		                          ORDER BY fname, lname, company");

		return $query->result();
	}
}
