<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class FM extends MY_Model{
	function __construct(){
		parent::__construct();
	}
	
	function build_condition($data_array, $field_name, $var="", $in=TRUE){
		$condition = "";
		$value_array = array();
		
		foreach($data_array as $d){
			if(is_array($d)){
				$value = $d[$var];
			}
			else if(is_object($d)){
				$value = $d->$var;
			}
			else{
				$value = $d;
			}
			
			if(! in_array($value, $value_array)){
				if($condition == ""){
					$condition .= $field_name;
					if(! $in) $condition .= " NOT";
					$condition .= " IN ";
					$condition .= "(";
				}
				else{
					$condition .= ", ";
				}
				
				$condition .= "'".$value."'";
				
				array_push($value_array, $value);
			}
		}
		if($condition != "") $condition .= ")";
		
		return $condition;
	}

	function index_array($array=array(), $index="", $become_array=FALSE){
		$result = array();
		
		if(count($array) > 0 && $index != ""){
			foreach($array as $v){
				if(isset($v->$index)){
					if(! $become_array){
						if(! isset($result[$v->$index])) $result[$v->$index] = $v;
					}
					else{
						if(! isset($result[$v->$index])) $result[$v->$index] = array();
						array_push($result[$v->$index], $v);
					}
				}
			}
		}
		
		return $result;
	}
	
	function keep_all_page_filter(){
		foreach($this->session->all_userdata() as $key=>$value){
			if(strlen($key) > 10 && substr($key, 0, 10) == "flash:old:" && substr($key, -11) == "page_filter"){
				$flashdata_name = substr($key, 10);
				
				if(! in_array($flashdata_name, array("success", "error"))){
					$this->session->keep_flashdata($flashdata_name);
				}
			}
		}
	}
	
	function profiler(){
		$this->output->enable_profiler(TRUE);
	}
	
	function get_mac(){
		//Rules: Local network only
		$ipAddress = $_SERVER['REMOTE_ADDR'];
		$macAddr = NULL;
		
		if(! in_array($ipAddress, array("::1", "127.0.0.1"))){
			$arp = `arp -a $ipAddress`;
			$lines = explode("\n", $arp);
			
			foreach($lines as $line){
				$cols = preg_split('/\s+/', trim($line));
				if($cols[0] == $ipAddress){
					$macAddr = $cols[1];
					break;
				}
			}
		}
		else{
			$macAddr = "SERVER";
		}
		
		return $macAddr;
	}
	
	function date_friendly($date=""){
		$result = $date;
		
		if($date != ""){
			if(date("Y-m-d", strtotime($date)) == date("Y-m-d")){
				$result = "Today";
			}
			elseif(date("Y-m-d", strtotime($date." +1 day")) == date("Y-m-d")){
				$result = "Yesterday";
			}
			else{
				$result = date("d M Y", strtotime($date));
			}
		}
		
		return $result;
	}
	
	function js_nl($string=""){
		return str_replace(array("\r\n", "\r", "\n"), "\\n", $string);
	}
	
	function append($original_string="", $addon_string="", $connector=" AND "){
		if(strlen($addon_string) > 0){
			if($original_string != "") $original_string .= $connector;
			$original_string .= $addon_string;
		}
		
		return $original_string;
	}
	
	function is_date($string=""){
		return $string == date("Y-m-d", strtotime($string));
	}
	
	function is_datetime($string=""){
		return $string == date("Y-m-d H:i:s", strtotime($string));
	}
	
	//Encryption (Hex Mixed)---
	function encrypt($string=""){
		$result = "";
		
		if($string != ""){
			foreach(str_split($string) as $char){
				//Char to ASCII Code
				$char = ord($char);	//Ex: * = 42
				
				//To Hex
				$char = dechex($char);	//Ex: 42 = 2a
				
				//Reverse string
				$char = substr($char, 1, 1).substr($char, 0, 1);	//Ex: 2a = a2
				
				//Mix
				$char = $this->mix($char[0]).$this->mix($char[1]);
				
				$result .= $char;
			}
		}
		
		return $result;
	}
	
	function decrypt($string=""){
		$data = "";
		$len = strlen($string);
		
		for($i=0; $i<$len; $i=$i+2){
			if(isset($string[$i], $string[$i+1])){
				$s1 = $this->de_mix($string[$i]);
				$s2 = $this->de_mix($string[$i+1]);
			
				$val = hexdec( $s1) + hexdec( $s2 ) * 16;
				$data .= chr($val);
			}
		}
		
		return $data;
	}
	
	public function mix($char){
		$original_string = "0123456789abcdef";
		$mix_string = "FEDCBA9876543210G";
		
		$position = strpos($original_string, $char) + 1;
		
		return $mix_string[$position];
	}
	
	function de_mix($x){
		$array = 	"0123456789abcdef";
		$mix = 		"FEDCBA9876543210G";
	
		$position = strpos($mix,$x, 0) - 1;
		
		return $array[$position];
	}
	//-------------------------

	function convert_number_to_word($number, $separator="", $conjunction="", $hyphen="", $decimal="", $negative="", $decimal_special=FALSE){
		/*
		 * Decimal Special:	(Min. 2 decimal places)
		 * Example 1: 0.74 = "Point Seventy-Four" instead of "Point Seven Four"
		 * Example 2: 0.2 = "Point Twenty" instead of "Point Two"
		 * Example 2: 0.345 = "Point Three Hundred Fourty-Five" instead of "Point Three Four Five"
		 */
		if($separator == "") $separator = ", ";
		if($conjunction == "") $conjunction = " and ";
		if($hyphen == "") $hyphen = "-";
		if($decimal == "") $decimal = " point ";
		if($negative == "") $negative = "negative ";
		$dictionary = array(
			0					=> "zero",
			1					=> "one",
			2					=> "two",
			3					=> "three",
			4					=> "four",
			5					=> "five",
			6					=> "six",
			7					=> "seven",
			8					=> "eight",
			9					=> "nine",
			10					=> "ten",
			11					=> "eleven",
			12					=> "twelve",
			13					=> "thirteen",
			14					=> "fourteen",
			15					=> "fifteen",
			16					=> "sixteen",
			17					=> "seventeen",
			18					=> "eighteen",
			19					=> "nineteen",
			20					=> "twenty",
			30					=> "thirty",
			40					=> "fourty",
			50					=> "fifty",
			60					=> "sixty",
			70					=> "seventy",
			80					=> "eighty",
			90					=> "ninety",
			100					=> "hundred",
			1000				=> "thousand",
			1000000				=> "million",
			1000000000			=> "billion",
			1000000000000		=> "trillion",
			1000000000000000	=> "quadrillion",
			1000000000000000000	=> "quintillion"
		);
		
		if (!is_numeric($number)) {
			return FALSE;
		}
		
		if (($number >= 0 && (int) $number < 0) || (int) $number < 0 - PHP_INT_MAX) {	//Overflow
//			trigger_error(
//				"convert_number_to_words only accepts numbers between -" . PHP_INT_MAX . " and " . PHP_INT_MAX,
//				E_USER_WARNING
//			);
			return FALSE;
		}
	
		if ($number < 0) {
			return $negative . $this->convert_number_to_word(abs($number), $separator, $conjunction, $hyphen, $decimal, $negative, $decimal_special);
		}
		
		$string = $fraction = NULL;
		
		if (strpos($number, ".") !== FALSE) {
			list($number, $fraction) = explode(".", $number);
		}
		
		switch (true) {
			case $number < 21:
				$string = $dictionary[(double)$number];
				break;
			case $number < 100:
				$tens = ((int) ($number / 10)) * 10;
				$units = $number % 10;
				$string = $dictionary[(double)$tens];
				if ($units) {
					$string .= $hyphen . $dictionary[(double)$units];
				}
				break;
			case $number < 1000:
				$hundreds = $number / 100;
				$remainder = $number % 100;
				$string = $dictionary[(double)$hundreds] . " " . $dictionary[(double)100];
				if ($remainder) {
					$string .= $conjunction . $this->convert_number_to_word($remainder, $separator, $conjunction, $hyphen, $decimal, $negative, $decimal_special);
				}
				break;
			default:
				$baseUnit = pow(1000, floor(log($number, 1000)));
				$numBaseUnits = (int) ($number / $baseUnit);
//				$remainder = $number % $baseUnit;
				$remainder = $number - ($baseUnit * $numBaseUnits);
				$string = $this->convert_number_to_word($numBaseUnits, $separator, $conjunction, $hyphen, $decimal, $negative, $decimal_special) . " " . $dictionary[(double)$baseUnit];
				if ($remainder) {
					$string .= $remainder < 100 ? $conjunction : $separator;
					$string .= $this->convert_number_to_word($remainder, $separator, $conjunction, $hyphen, $decimal, $negative, $decimal_special);
				}
				break;
		}
		
		if (NULL !== $fraction && is_numeric($fraction)) {
			$string .= $decimal;
			if(! $decimal_special){
				$words = array();
				foreach (str_split((string) $fraction) as $number) {
					$words[] = $dictionary[(double)$number];
				}
				$string .= implode(" ", $words);
			}
			else{
				$fraction = str_pad($fraction, 2, "0");
				$string .= $this->convert_number_to_word($fraction, $separator, $conjunction, $hyphen, $decimal, $negative, $decimal_special);
			}
		}
		
		return $string;
	}
	
	function get_current_user(){
		$this->load->model("user_model");
		
		$ci = get_instance();
		if(! isset($ci->user) || $ci->user == NULL || ! is_object($ci->user)){
			$user_array = $this->session->userdata('user_id') != ""? $this->user_model->get_data(array(
				'condition' => "<T>.<PK> = '".$this->session->userdata('user_id')."'",
			)):array();
			
			if(count($user_array) > 0){
				$ci->user = $user_array[0];
			}
			else{
				$ci->user = NULL;
			}
		}
		
		return $ci->user;
	}
	
	function get_logo(){
		$this->load->model("logo_model");
		
		$ci = get_instance();
		if(! isset($ci->logo) || $ci->logo == NULL || ! is_object($ci->logo)){
			$data_array = $this->logo_model->get_data(array(
				'sort' => " ",
				'' => "",
			));
			
			if(count($data_array) > 0){
				$ci->logo = $data_array[0];
			}
			else{
				$ci->logo = NULL;
			}
		}
		
		return $ci->logo;
	}
	
	function get_profile(){
		$this->load->model("profile_model");
		
		$ci = get_instance();
		if(! isset($ci->profile) || $ci->profile == NULL || ! is_object($ci->profile)){
			$data_array = $this->profile_model->get_data(array(
				'sort' => " ",
				'' => "",
			));
			
			if(count($data_array) > 0){
				$ci->profile = $data_array[0];
			}
			else{
				$ci->profile = NULL;
			}
		}
		
		return $ci->profile;
	}
	
	function get_setting(){
		$this->load->model("setting_model");
		
		$ci = get_instance();
		if(! isset($ci->setting) || $ci->setting == NULL || ! is_object($ci->setting)){
			$data_array = $this->setting_model->get_data(array(
				'sort' => " ",
				'' => "",
			));
			
			if(count($data_array) > 0){
				$ci->setting = $data_array[0];
			}
			else{
				$ci->setting = NULL;
			}
		}
		
		return $ci->setting;
	}
	
	function get_pccode(){
		$ci = get_instance();
		
		if(isset($ci->pccode)){
			if($ci->pccode == ""){
				$logo = $this->get_logo();
				
				if($logo != NULL && isset($logo->PCCODE)){
					$ci->pccode = $logo->PCCODE;
				}
			}
			
			return $ci->pccode;
		}
		
		return "";
	}

	function generate_btn($btn_array=array()){
		$content = "";
		foreach($btn_array as $x=>$v){
			if($x == 0){
				$content .= "<a ";
				if(isset($v['href']) && $v['href'] != "") $content .= "href=\"".$v['href']."\" ";
				if(isset($v['data-toggle']) && $v['data-toggle'] != "") $content .= "data-toggle=\"".$v['data-toggle']."\" ";
				if(isset($v['onClick']) && $v['onClick'] != "") $content .= "onClick=\"".$v['onClick']."\" ";
				if(isset($v['description']) && $v['description'] != "") $content .= "title=\"".$v['description']."\" ";
				if(isset($v['target']) && $v['target'] != "") $content .= "target=\"".$v['target']."\" ";
				$content .= "class=\"btn btn-default btn-xs\" style=\"float: none; margin: 0;\">";
				if(isset($v['icon']) && $v['icon'] != "") $content .= "<i class=\"".$v['icon']."\"></i>";
				$content .= "</a>";
			}
			else{
				if($x == 1){
					$content .= "<a href=\"javascript:;\" data-toggle=\"dropdown\" class=\"btn btn-default btn-xs dropdown-toggle\" style=\"float: none; margin: -3px; padding-left: 4px; padding-right: 4px;\">";
					$content .= 	"<i class=\"fa fa-caret-down\"></i>";
					$content .= "</a>";
					$content .= "<ul class=\"dropdown-menu\" style=\"top: 20px; left: auto; right: -4px;\">";
				}
				
				$content .= "<li>";
				$content .= 	"<a ";
				if(isset($v['href']) && $v['href'] != "") $content .= "href=\"".$v['href']."\" ";
				if(isset($v['data-toggle']) && $v['data-toggle'] != "") $content .= "data-toggle=\"".$v['data-toggle']."\" ";
				if(isset($v['onClick']) && $v['onClick'] != "") $content .= "onClick=\"".$v['onClick']."\" ";
				if(isset($v['target']) && $v['target'] != "") $content .= "target=\"".$v['target']."\" ";
				$content .= 	">";
				if(isset($v['icon']) && $v['icon'] != "") $content .= "<i class=\"".$v['icon']."\"></i> ";
				if(isset($v['description']) && $v['description'] != "") $content .= $v['description'];
				$content .= 	"</a>";
				$content .= "</li>";
			}
		}
		if(count($btn_array) > 1) $content .= "</ul>";
		
		return $content;
	}
	
	function generate_table_header($header_array=array()){
		$content = "";
		$content .= "<tr>";
		
		$first_header_with_sort = TRUE;
		foreach($header_array as $v){
			$sort = isset($v['sort'])? $v['sort']:"";
			$encrypted_sort = $this->encrypt($sort);
			
			$content .= "<th";
			if(isset($v['style']) && $v['style'] != "") $content .= " style='".$v['style']."'";
			if($sort != "") $content .= " data-sort='".$encrypted_sort."' onClick='data_list_sort(this);'";
			$content .= ">";
			if(isset($v['description'])) $content .= $v['description'];
			
			if($sort != ""){
				$content .= " <i class='fa fa-";
				if(($first_header_with_sort && $this->input->get('S') == "") || ($this->input->get('S') == $encrypted_sort)){
					$content .= $this->input->get('SD') != "1"? "caret-down":"caret-up";
				}
				else{
					$content .= "sort";
				}
				$content .= "'></i>";
				
				if($first_header_with_sort) $first_header_with_sort = FALSE;
			}
			
			$content .= "</th>";
		}
		
		$content .= "</tr>";
		
		return $content;
	}
	
	function str_esc($string="", $mode=""){
		switch($mode){
			case 1:	//SQL
				$string = str_replace("'", "''", $string);
				break;
			case 2:	//HTML
				$string = str_replace("\"", "&quot;", $string);
				break;
			case 3:	//Javascript
				$string = str_replace("\\", "\\\\", $string);
				$string = str_replace("\"", "\\\"", $string);
				break;
		}
		
		return $string;
	}
	
	function sort_inverse($sort=""){
		$result = "";
		
		$sort_array = explode(",", $sort);
		foreach($sort_array as $v){
			$v = trim($v);
			
			if(strpos($v, "IS NULL THEN 1 ELSE 0 END") === FALSE){
				$is_desc = substr($v, -5) == " DESC";
				
				if($is_desc){
					$v = substr($v, 0, -5);
				}
				else{
					$v .= " DESC";
				}
			}
			
			$result = $this->append($result, $v, ", ");
		}
		
		return $result;
	}
	
	function get_access($menu_array=array()){
		$access_array = count($menu_array) > 0? $this->index_array($this->access_model->get_data(array(
			'condition' => $this->build_condition($menu_array, "<T>.MENU")." AND <T>.USER_GROUP = '".$this->session->userdata('group_id')."'",
			'select' => "<T>.MENU",
		)), "MENU"):array();
		
		return $access_array;
	}
	
	function sql_translate($towards, $query){
		$towards = strtoupper($towards);
		$len = strlen($query);
		$result = "";
		
		switch($towards){
			case "MYSQL":
				$inside_quote = FALSE;
				$char_array = str_split($query);
				for($x=0; $x<count($char_array); $x++){
					$c = $char_array[$x];
					
					unset($next_c);
					if(($x + 1) < count($char_array)) $next_c = $char_array[$x + 1];
					
					if(in_array($c, array("[", "]")) && ! $inside_quote){
						$result .= "`";
					}
					elseif($c == "\\"){
						$result .= "\\\\";
					}
					else{
						if($c == "'") $inside_quote = ! $inside_quote;
						$result .= $inside_quote? $c:strtoupper($c);
					}
				}
				break;
			case "MSSQL":
				$inside_quote = FALSE;
				$bracked_opened = FALSE;
				
				$char_array = str_split($query);
				for($x=0; $x<count($char_array); $x++){
					$c = $char_array[$x];
					
					unset($next_c);
					if(($x + 1) < count($char_array)) $next_c = $char_array[$x + 1];
					
					if($c == "`" && ! $inside_quote){
						$result .= ! $bracked_opened? "[":"]";
						
						$bracked_opened = ! $bracked_opened;
					}
					elseif($c == "\\" && isset($next_c) && $next_c == "'"){
						$result .= "''";
						$x++;
					}
					elseif($c == "\\" && isset($next_c) && $next_c == "\\"){
						$result .= "\\";
						$x++;
					}
					elseif($c == "\\" && isset($next_c) && $next_c == "\""){
						$result .= "\"";
						$x++;
					}
					else{
						if($c == "'") $inside_quote = ! $inside_quote;
						$result .= $c;
					}
				}
				break;
		}
		
		return $result;
	}
	
	function gps_distance($params=array()){
		$result = NULL;
		
		if(isset($params['LAT_FROM'], $params['LONG_FROM'], $params['LAT_TO'], $params['LONG_TO'])){
			$lat_from_deg = (double)$params['LAT_FROM'];
			$long_from_deg = (double)$params['LONG_FROM'];
			$lat_to_deg = (double)$params['LAT_TO'];
			$long_to_deg = (double)$params['LONG_TO'];
			$earth_radius = isset($params['EARTH_RADIUS'])? (double)$params['EARTH_RADIUS']:6371000;
			
			$lat_from = deg2rad($lat_from_deg);
			$long_from = deg2rad($long_from_deg);
			$lat_to = deg2rad($lat_to_deg);
			$long_to = deg2rad($long_to_deg);
			
			$lat_delta = $lat_to - $lat_from;
			$long_delta = $long_to - $long_from;
			
			$angle = 2 * asin(sqrt(pow(sin($lat_delta / 2), 2) + cos($lat_from) * cos($lat_to) * pow(sin($long_delta / 2), 2)));
			$result = $angle * $earth_radius;	//In metres
		}
		
		return $result;
	}
	
	function period_to_string($period=0, $return_format=1){
		/*
		 * Note:
		 * - Period in seconds
		 * - Return Format:
		 * 		1:	01:48:02
		 * 		2:	1hr 48mins 2secs
		 */
		
		$result = "";
		
		$period = (int)$period;
		
		$hour = floor($period / 60 / 60);
		$period -= ($hour * 60 * 60);
		
		$minute = floor($period / 60);
		$period -= ($minute * 60);
		
		$second = floor($period);
		
		switch($return_format){
			case 2:
				if($hour > 0){
					$string = $hour."hr";
					if($string > 1) $string .= "s";
					
					$result = $this->fm->append($result, $string, " ");
				}
				if($minute > 0 || $result != ""){
					$string = $minute."min";
					if($string > 1) $string .= "s";
					
					$result = $this->fm->append($result, $string, " ");
				}
			
				$string = $second."sec";
				if($string > 1) $string .= "s";
				
				$result = $this->fm->append($result, $string, " ");
				break;
			case 1:
			default:
				$result .= str_pad($hour, 2, "0", STR_PAD_LEFT).":".str_pad($minute, 2, "0", STR_PAD_LEFT).":".str_pad($second, 2, "0", STR_PAD_LEFT);
				break;
		}
		
		return $result;
	}
	
	function generate_token($len=1){
		$result = "";
		$string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		
		while(strlen($result) < (int)$len){
			$result .= $string[mt_rand(0, strlen($string) - 1)];
		}
		
		return $result;
	}
	
	function curl_post($url="", $param=array()){
		/*
		 * Note: Need to enable php_curl.dll in the PHP Extensions
		 */
		$output = NULL;
		
		if(strlen($url) > 0){
			$postData = "";
			foreach($param as $k=>$v){ 
				$postData .= $k."=".urlencode($v)."&"; 
			}
			rtrim($postData, "&");
	
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL,$url);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
			curl_setopt($ch, CURLOPT_HEADER, false); 
			curl_setopt($ch, CURLOPT_POST, count($postData));
			curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);		
	
			$output = curl_exec($ch);
	
			curl_close($ch);
		}

		return $output;
	}
}