<?php 
//namespace models;
//use helpers\session as Session;
//use helpers\cookie as Cookie;
//use \PDO; //uncomment for PDOStatement::fetchObjects

/**
* Profile Model : The Database object
* Handles the user's profile / inbox / edit / user images stuff
**/
class Mobile_Model extends Model{
	/**
	* Constructor, expects a Database connection
	*/
	public function __construct(){
		parent::__construct();
	}

	/** 
	* Returns true if such email dose not exists
	* @param STRING email to check for
	* @return BOOL false on email exists else email free
	**/
	public function get_EmailTaken($userEmail=""){
		if($userEmail == "")
			return false;
		$data = $this->_db->select("SELECT *
									FROM ".PREFIX."usr 
									WHERE user_email = :user_email"
									,array(':user_email' => $userEmail));
		if($data){
			return true;
		}else{
			return false;
		}
	}


	/**
	* mOBILE CHECK for user auth
	* @param INT user id 
	* @returns ARRAY with paths or BOOL false on none found
	*/
	public function get_UserValid($user_id,$user_uid){
		$query = $this->_db->select("SELECT *
									FROM ".PREFIX."usr 
									WHERE user_id = :user_id 
										AND user_mobile_uid = :user_uid
										AND user_active = 1"
									,array(':user_id' => $user_id,
											':user_uid' => $user_uid));
		// if there's NOT one result but only first row fetched (we only have one result)
		if($query){
			return true;
		}else{
			return false;
		}
	}

	/** 
	* Returns conversation between two users and marks message as read
	* @param INT current (the sending) second (the receiving)
	* @return ARRAY with messages or BOOL false
	**/
	public function get_Conv($userId,$userTwo,$limit=DISPLAY_MSGS){
		$this->_db->update(PREFIX."usr_con",
							array('status' => '1'),
							array('user_one' => $userTwo,
									'user_two' => $userId));
		// $query = $this->_db->select("SELECT user_one,msg,status,time
		$query = $this->_db->select("SELECT *
									FROM ".PREFIX."usr_con
									WHERE 
										(user_one = :user_id AND user_two = :user_two)
									OR
										(user_one = :user_two AND user_two = :user_id)
									ORDER BY con_id ASC LIMIT ".$limit
									,array(':user_id' => $userId,
											':user_two' => $userTwo));
		// if there's NOT one result but only first row fetched (we only have one result)
		if ($query){
			return $query;
		}else{
			return false;
		}
	}

	/** 
	* Returns conversation between two users and marks message as read
	* @param INT current (the sending) second (the receiving)
	* @return ARRAY with messages or BOOL false
	**/
	public function get_ConvNew($userId,$userTwo,$conFromId=0){
		$this->_db->update(PREFIX."usr_con",
							array('status' => '1'),
							array('user_one' => $userTwo,
									'user_two' => $userId));
		// $query = $this->_db->select("SELECT user_one,msg,status,time
		$query = $this->_db->select("SELECT *
									FROM ".PREFIX."usr_con
									WHERE 
										(user_one = :user_id AND user_two = :user_two AND con_id > :con_id)
									OR
										(user_one = :user_two AND user_two = :user_id AND con_id > :con_id)
									ORDER BY con_id ASC"
									,array(':user_id' => $userId,
											':user_two' => $userTwo,
											':con_id' => $conFromId));
		// if there's NOT one result but only first row fetched (we only have one result)
		if ($query){
			return $query;
		}else{
			return false;
		}
	}


	/** 
	* Returns any new / incoming unread messages to given user 
	* @param INT currently awaiting new message user id
	* @return ARRAY with new incoming messages and user id's or BOOL false
	**/
	public function get_ConvNewMsgCheck($userId){
		// $query = $this->_db->select("SELECT user_one,msg,status,time,COUNT(*) as count
		$query = $this->_db->select("SELECT user_one,COUNT(*) as count
									FROM ".PREFIX."usr_con
									WHERE user_two = :user_id AND status = '0'
									GROUP BY user_one 
									ORDER BY con_id ASC"
									,array(':user_id' => $userId));
		// if there's NOT one result but only first row fetched (we only have one result)
		if ($query){
			return $query;
		}else{
			return false;
		}
	}


	/**
	* Insert/add new message to conversation between users 
	* @paramt INT sending/receiving user id
	* @param STRING message content 
	* @return BOOL success/fail
	**/
	public function set_ConvMsg($sending,$receiving,$message){
		$query = $this->_db->insert(PREFIX."usr_con"
								,array('user_one' => $sending,
									'user_two' => $receiving,
									'msg' => $message,
									'time' => date('Y-m-d H:i:s', time())));
		if($query){
			return true;
		}else{
			return false;
		}
	}

	/**
	* Retrieve all messages/conversations that was to current user with others, auto limit considering 
	* @param INT current page/ optional limit/ current user id
	* @return ARRAY of conversations/messages or BOOL false if no conversations found
	**/
	public function get_UserConvs($pageId=0,$limit=DISPLAY_USERS,$userId){
		$data['usr'] = $this->_db->select("SELECT SQL_CALC_FOUND_ROWS DISTINCT 
											u.user_id,
											u.user_city,
											u.user_name,
											u.user_birth,
											u.user_interpersonal_stat,
											u.user_about,
											u.user_height,
											u.user_gender,
											u.user_modified,
											p.con_id,
											p.user_one,
											p.user_two,
											p.status,
											p.time,
											i.user_img_path
									FROM ".PREFIX."usr_i u
									JOIN (SELECT DISTINCT * 
											FROM ".PREFIX."usr_con
											WHERE ".PREFIX."usr_con.user_one = :user_id OR ".PREFIX."usr_con.user_two = :user_id
											ORDER BY ".PREFIX."usr_con.time DESC
											)AS p ON u.user_id = p.user_one OR u.user_id = p.user_two 
									LEFT OUTER JOIN ".PREFIX."usr_img i
									ON u.user_id = i.user_id
									WHERE NOT u.user_id = :user_id
									GROUP BY u.user_id
									ORDER BY p.time DESC LIMIT ".$limit * ($pageId)." , ".$limit." "
									,array(':user_id' => $userId));
		// check for any conversations...
		if(empty($data['usr'])){
			return false;
		}else{
			$data['add'] = $this->_db->select("SELECT FOUND_ROWS() AS `total_found`");
			return $data;
		}
	}


	/**
	* Handles the entire registration process for DEFAULT, creates a new user in the database if everything is fine
	* Not for people who register with service like Facebook
	* @return ARRAY/BOOL success/failure status of the registration
	*/
	public function set_RegisterNewUser($p_user_email,$p_user_password,$p_user_birth,$p_user_gender,$p_user_name){
		/* Just checking that received all variables .. */
		// The user gender is 0 but should be 2 this is old code
		// error_log(" $p_user_email $p_user_password $p_user_birth $p_user_gender $p_user_name ");
		if(empty($p_user_birth) OR empty($p_user_email) OR empty($p_user_password) OR empty($p_user_name)){
			echo 'ERROR_UNKNOWN';
			// error_log(" error unknown ");
			return false;
		}else{
			// check if email already exists
			$query = $this->_db->selectOne("SELECT user_id FROM ".PREFIX."usr WHERE user_email = :user_email",array(':user_email' => $p_user_email));
			// email exists ?! return false! may be send to user email notification....?
			if($query){
				// echo 'EMAIL_TAKEN';
			// error_log(" email taken ");
				return false;
			}
			// generate random hash for email verification (40 char string)
			$user_activation_hash = sha1(uniqid(mt_rand(), true));
			// generate simple 20 chars long Hash using SHA1 from users birth day and creation time stamp for use as "salt" in login check
			$user_creation_hash_salt = substr(hash('sha1',$p_user_birth.time()),-20);
			// generate simple 40 chars long Hash for mobile UID using SHA1 from users email and creation hash
			$user_mobile_uid = hash('sha1',$p_user_email.$user_creation_hash_salt);
			// crypt the user's password using Blowfish as some salt the pass 60 chars long
			$user_password_hash = crypt($p_user_password, BLOWFISH_HASH_COST.$user_creation_hash_salt);
			// write new user into data into database
			//error_log(' new user with '.$p_user_email);
			$query = $this->_db->insert(PREFIX."usr"
										,array('user_gender' => $p_user_gender,
											'user_password_hash' => $user_password_hash,
											'user_email' => $p_user_email,
											'user_name' => $p_user_name,
											'user_creation_hash_salt' => $user_creation_hash_salt,
											'user_mobile_uid' => $user_mobile_uid,
											'user_activation_hash' => $user_activation_hash,
											'user_birth' => $p_user_birth,
											'user_provider_type' => 'DEFAULT'));
			// check if user successfully created in DB
			if($query != 1){
				
				error_log(" error unknown  : unable to create user  ($p_user_email)");
				return false;
			}
			// get unique user_id of the user that has been created
			$query = $this->_db->selectOne("SELECT * 
											FROM ".PREFIX."usr 
											WHERE user_email = :user_email"
											,array(':user_email' => $p_user_email));
			// unable to get the newly created user...?!
			//error_log(' new id '.$query->user_id);
			if(!$query){
				error_log(" error unknown : unable to get created user ($p_user_email) ");
				return false;
			}
			error_log(" error unknown : user created success ($p_user_email) ");
			// this is finale return upon all procedures success
			return $query;
		}
		// default return, returns only true of really successful (see above)
		return false;
	}

	/** 
	* Returns all users by decreasing ID
	* @param INT current page considering with users limit per page
	* @return ARRAY of users with information or BOOL on false or none meet criteria
	**/
	public function get_Users($pageId=0,$limit=12){
		$data["users"] = $this->_db->select("SELECT SQL_CALC_FOUND_ROWS 
												u.user_id,
												u.user_gender,
												u.user_city,
												u.user_name,
												u.user_birth,
												u.user_interpersonal_stat,
												u.user_modified,
												i.user_img_path
								FROM ".PREFIX."usr_i u
								LEFT OUTER JOIN ".PREFIX."usr_img i
								ON u.user_id = i.user_id
								GROUP BY u.user_id
								ORDER BY u.user_id DESC LIMIT ".$limit * ($pageId)." , ".$limit." ");
		if($data){
			$data["total_found"] = $this->_db->select("SELECT FOUND_ROWS() AS 'total_found'");
			return $data;
		}else{
			return false;
		}
	}

	/** 
	* Returns users found by search limit, the search performed will return users by decreasing ID
	* @param INT current page considering with users limit per page
	* @params MIX as optional: gender , date(age) from/to 
	* @return ARRAY of users with information or BOOL on false or none meet criteria
	**/
	public function get_Search($pageId=0,$limit=DISPLAY_USERS,$searchParams){
		if(!empty($searchParams)){
			/** This array will allow to expand dynamic search **/
			$push_array=[];
			$push_string = " WHERE 1=1 ";
			if(array_key_exists('user_gender',$searchParams)){
				$push_array[':user_gender'] = $searchParams['user_gender'];
				$push_string .= " AND u.user_gender = :user_gender ";
			}
			if(!empty($searchParams['user_age_from'])){
				$push_array[':user_birth_from'] = $searchParams['user_age_from'];
				$push_string .=  " AND u.user_birth <= :user_birth_from ";
			}
			if(!empty($searchParams['user_age_to'])){
				$push_array[':user_birth_to'] = $searchParams['user_age_to'];
				$push_string .=  " AND u.user_birth >= :user_birth_to ";
				
			}
			if(array_key_exists('user_district',$searchParams)){
				$push_array[':user_district'] = $searchParams['user_district'];
				$push_string .= " AND u.user_district = :user_district ";
			}
			$data["users"] = $this->_db->select("SELECT SQL_CALC_FOUND_ROWS 
												u.user_id,
												u.user_gender,
												u.user_city,
												u.user_name,
												u.user_birth,
												u.user_interpersonal_stat,
												u.user_modified,
												i.user_img_path
									FROM ".PREFIX."usr_i u
									LEFT OUTER JOIN ".PREFIX."usr_img i
									ON u.user_id = i.user_id
									".$push_string."
									GROUP BY u.user_id
									ORDER BY u.user_id DESC LIMIT ".$limit * ($pageId)." , ".$limit." "
									,$push_array);
		}else{
			$data["users"] = $this->_db->select("SELECT SQL_CALC_FOUND_ROWS 
												u.user_id,
												u.user_gender,
												u.user_city,
												u.user_name,
												u.user_birth,
												u.user_interpersonal_stat,
												u.user_modified,
												i.user_img_path
									FROM ".PREFIX."usr_i u
									LEFT OUTER JOIN ".PREFIX."usr_img i
									ON u.user_id = i.user_id
									GROUP BY u.user_id
									ORDER BY u.user_id DESC LIMIT ".$limit * ($pageId)." , ".$limit." ");
		}
		if($data){
			$data["total_found"] = $this->_db->select("SELECT FOUND_ROWS() AS `total_found`");
			return $data;
		}else{
			return false;
		}
	}
	
	/**
	* Get user by email and password
	*/
	public function getUserByEmailAndPassword($p_user_email, $p_user_password) {
		// $result = mysql_query("SELECT * FROM users WHERE email = '$email'") or die(mysql_error());
		// // check for result 
		// $no_of_rows = mysql_num_rows($result);
		// if ($no_of_rows > 0) {
			// $result = mysql_fetch_array($result);
			// $salt = $result['salt'];
			// $encrypted_password = $result['encrypted_password'];
			// $hash = $this->checkhashSSHA($salt, $password);
			// // check for password equality
			// if ($encrypted_password == $hash) {
				// // user authentication details are correct
				// return $result;
			// }
		// } else {
			// // user not found
			// return false;
		// }
		
		$query = $this->_db->selectOne("SELECT user_id,
											user_gender,
											user_email,
											user_password_hash,
											user_mobile_uid,
											user_active,
											user_account_type,
											user_failed_logins,
											user_last_failed_login,
											user_creation_hash_salt
										FROM ".PREFIX."usr
										WHERE user_email = :user_email
											AND user_provider_type = :provider_type"
											,array(':user_email' => $p_user_email
											,':provider_type' => 'DEFAULT'));//,$DFSSD);
		// if there's NOT one result
			// error_log("select one");
			// error_log($query["user_password_hash"]);
			// // error_log($query);
			// error_log($query->user_email);
			// error_log($query->user_creation_hash_salt);

		if(!$query){
			// here LOGIN_FAILED to prevent potential attackers showing if the user exists
			//Session::set("feedback_negative", 'LOGIN_FAILED');
			return false;
		}
		//echo $query->user_last_failed_login;
		// check if hash of provided password matches the hash in the database
		// crypt(p_user_password, BLOWFISH_HASH_COST.user_creation_hash_salt)
		// crypt using current (BLOWFISH_HASH_COST) Blowfish + only 04 iterations the salt those the magic
		
			// error_log(" users crypt ");
			// error_log(crypt($p_user_password, BLOWFISH_HASH_COST.$query->user_creation_hash_salt));
		if(crypt($p_user_password, BLOWFISH_HASH_COST.$query["user_creation_hash_salt"]) == $query["user_password_hash"]){
			if ($query->user_active != 1)
				return false;
			else{
				$queryUser = $this->_db->selectOne("SELECT *
									FROM ".PREFIX."usr_i
									WHERE user_id = :user_id"
										,array(':user_id' => $query["user_id"]));
				if(!$queryUser)
					return false;
				else{
					// foreach ($query as $k => $v) {
						// //echo "Current value of \$a: $v.\n";
						// $result[$k] = $v;
					// }
					$result["user_uid"] = $query->user_mobile_uid;
					$result["user_email"] = $query->user_email;
					foreach ($queryUser as $k => $v) {
						//echo "Current value of \$a: $v.\n";
						$result[$k] = $v;
					}
					$result["queryString"] = "";
					//$queryUser['user_id'] = $query["user_id"];
					return $result;
				}
			}
		}
	}


	/** 
	* Returns all user information by given ID
	* @param INT current page considering with users limit per page
	* @return ARRAY of users with information or BOOL on false or none meet criteria
	**/
	public function get_UserInfo($userId=0){
		if($userId == 0)
			return false;
		$data['usr'] = $this->_db->select("SELECT *
									FROM ".PREFIX."usr_i 
									WHERE user_id = :user_id"
									,array(':user_id' => $userId));
		if($data){
			$data['add'] = $this->_db->select("SELECT FOUND_ROWS() AS `total_found`");
			return $data;
		}else{
			return false;
		}
	}

	/** 
	* Returns all user information by given ID with associative array
	* @param INT user id to fetch
	* @return ARRAY of user information or BOOL on false or none meet criteria
	**/
	public function get_UserInformation($userId=0){
		if($userId == 0)
			return false;
		$data = $this->_db->selectOneAssoc("SELECT *
									FROM ".PREFIX."usr_i 
									WHERE user_id = :user_id"
									,array(':user_id' => $userId));
		if($data){
			return $data;
		}else{
			return false;
		}
	}


	/**
	* Returns user all parameters from user_information table
	* @param INT the id of user to look for
	* @return ARRAY or false BOOL if none found
	**/
	public function get_User($userId){
		$query = $this->_db->select("SELECT *
									FROM ".PREFIX."usr_i 
									WHERE user_id = :user_id"
									,array(':user_id' => $userId));
		// if there's NOT one result but only first row fetched (we only have one result)
		if($query){
			return $query[0];
		}else{
			return false;
		}
	}

	/**
	* Updates/edit users profile information everything that passed to this method
	* @param INT the id of user to look for
	* @param ARRAY updateArray with values
	* @return BOOL on successful update ele on false
	*/
	public function set_EditProfile($userId,$updateArray){
		$query_a = $this->_db->update(PREFIX."usr_i",
									$updateArray,
									array('user_id' => $userId));
		if(sizeof($query_a) == 1){
			// Session::set("feedback_positive", USERNAME_CHANGE_SUCCESSFUL);
			return true;
		}else{
			// Session::set("feedback_negative", ERROR_UNKNOWN);
			return false;
		}
	}

	/**
	* Get users profile last modification date
	* @param INT the id of user to look for last modification date
	* @return ARRAY with user_modified value on successful result else BOOL false
	*/
	public function get_ProfileModified($userId){
		$query = $this->_db->selectOneAssoc("SELECT user_modified
									FROM ".PREFIX."usr_i 
									WHERE user_id = :user_id"
									,array(':user_id' => $userId));
		// if there's NOT one result but only first row fetched (we only have one result)
		if($query){
			return $query;
		}else{
			return false;
		}
	}

	/** 
	* Deletes user image by id from images table in DB, for security match both id's
	* @param INT user id 
	* @param INT image id to delete 
	* @return BOOL success or failure
	*/
	public function set_ImageDelete($userId,$imgPath=''){
		if($imgPath=='')
			return false;
		$query_a = $this->_db->delete(PREFIX."usr_img",
							array('user_img_path' => $imgPath,
								'user_id' => $userId));
		if(sizeof($query_a) == 1){
			return true;
		}else{
			return false;
		}
	}

	/** 
	* Set selected avatar image for user as none in DB, unfortunately due to PDO i will update directly....
	* @param INT user id to unset avatar image
	* @return BOOL success or failure
	*/
	public function set_ImageSelectedNone($userId){
		$query_a = $this->_db->updateDirect(PREFIX."usr_i, ".PREFIX."usr_img
											SET
											".PREFIX."usr_i.user_img_selected = '',
											".PREFIX."usr_img.user_img_selected = '0'
											WHERE 
											".PREFIX."usr_img.user_id='".$userId."' AND ".PREFIX."usr_i.user_id='".$userId."'");
		if(sizeof($query_a) == 1){
			return true;
		}else{
			return false;
		}
	}

	/** 
	* Set selected avatar image in user information table and user images table
	* @param INT user id
	* @param INT image id to set
	* @param STRING image path 
	* @return BOOL success or failure
	*/
	public function set_ImageSelected($userId,$userImg='',$imgSelected=''){
		if($imgSelected=='' OR $userImg=='')
			return false;
		$query_a = $this->_db->updateDirect(PREFIX."usr_i, ".PREFIX."usr_img
											SET
											".PREFIX."usr_i.user_img_selected = '$imgSelected',
											".PREFIX."usr_img.user_img_selected = IF(".PREFIX."usr_img.user_img='$userImg','1','0')
											WHERE 
											".PREFIX."usr_img.user_id='".$userId."' AND ".PREFIX."usr_i.user_id='".$userId."'");
		if(sizeof($query_a) == 1){
			return true;
		}else{
			return false;
		}
	}

	/** 
	* Inserts new image user have uploaded to server user images table
	* PLEASE NOTE THE IMAGE SHOULD BE CHECKED AND SET IN BOTH DB ADDRESES OR NOT 
	* I THINK IT SHOULD RETURN THE CONSTRUCTED PATHS....
	* @param INT user id 
	* @param STRING the new image path on server 
	* @return BOOL success or failure
	**/
	public function set_ConcatNewImage($userId,$imgPath=''){
		if($imgPath == '')
			return false;
		/* Add new image path to current user , this path should be checked by administrator */
		$query = $this->_db->insert(PREFIX."usr_img",
							array('user_id' => $userId,
									'user_img_path' => $imgPath));
		if($query >= 1){
			return true;
		}else{
			return false;
		}
	}


	/**
	* Get all user image paths and selected image path if such was set
	* @param INT user id 
	* @returns ARRAY with paths or BOOL false on none found
	*/
	public function get_UserImages($userId){
		$query = $this->_db->select("SELECT *
									FROM ".PREFIX."usr_img 
									WHERE user_id = :user_id"
									,array(':user_id' => $userId));
		// if there's NOT one result but only first row fetched (we only have one result)
		if($query){
			return $query;
		}else{
			return false;
		}
	}
	
	// Unfortunately due to FUCKING PDO the CONCAT_WS(sparator , string 1 , string 2) not working
	// we return upon success or failure the user images paths 
	// public function set_ConcatNewImage($user_img_paths=''){
		// $user_add = $this->get_users_add();
		// $usedData = $user_add[0]->user_img_paths;
		// // $query_a = $this->_db->update(PREFIX."usr_".Session::get("user_gender")."_i",
		// $query_a = $this->_db->update(PREFIX."usr_i",
							// //array('user_img_paths' => "CONCAT_WS('|',user_img_paths,".$user_img_paths.")"),
							// array('user_img_paths' => '|'.$user_img_paths.$usedData),
							// array('user_id' => Session::get('user_id')));
		// if(sizeof($query_a) == 1){
			// return '|'.$user_img_paths.$usedData;
		// }else{
			// return $usedData;
		// }
	// }

}