<?php

Class PHPRC_CHIKKA
{
	private static $CHIKKA_LAST_COMPANY_CODE = "";
	private static $CHIKKA_LAST_SERVICE_CODE = "";
	private static $CHIKKA_LAST_REQUEST_COST = "P1.00";
	private static $CHIKKA_LAST_IS_SPAM = false;
	private static $CHIKKA_LAST_IS_VOLUME_LIMIT = false;
	private static $CHIKKA_ERROR_MESSAGE = "";
	
	private static $CHIKKA_LAST_SEND_INDEX = 0;
	private static $CHIKKA_LAST_SEND_UNIQUE_ID = "";

	
	
	// ==================================================================
	//					CHIKKA PARAMETER RETRIEVERS
	// ==================================================================
	
	/**
	 * Retrieves the last used send ID
	 * @return string
	 */
	public static function REF_PARAM_LAST_PROCESSED_INDEX()
	{
		return self::$CHIKKA_LAST_SEND_INDEX;
	}
	
	/**
	 * Retrieves the last used send ID
	 * @return string
	 */
	public static function REF_PARAM_LAST_UNIQUE_KEY()
	{
		return self::$CHIKKA_LAST_SEND_UNIQUE_ID;
	}

	/**
	 * Retrieves the last chikka error message.
	 * @return string
	 */
	public static function REF_PARAM_ERROR()
	{
		return self::$CHIKKA_ERROR_MESSAGE;
	}
	
	/**
	 * Generates unique key for the chikka transaction key.
	 * @return String 32-length chikka request key
	 */
	public static function REF_PARAM_GENERATE_ID()
	{
		// Prepare Transaction ID
		$TRANSACTION_ID = PHPVC_DATETIME::VAR_TO_STRING
				(
					PHPVC_DATETIME::VAR_NOW()
				) . '_' .
				PHPVC_STR::VAR_RANDOM(10, false, false, true);
				$TRANSACTION_ID = PHPVC_STR::VAR_REPLACE($TRANSACTION_ID, ' ', 'X');
				$TRANSACTION_ID = PHPVC_STR::VAR_REPLACE($TRANSACTION_ID, '.', 'X');
				$TRANSACTION_ID = PHPVC_STR::VAR_REPLACE($TRANSACTION_ID, '_', 'X');
				$TRANSACTION_ID = PHPVC_STR::VAR_REPLACE($TRANSACTION_ID, '-', 'X');
				$TRANSACTION_ID = PHPVC_STR::VAR_LEFT($TRANSACTION_ID, 32);
				
		return $TRANSACTION_ID;
	}
	
	/**
	 * Generate unique LoadFlow Key for the transaction
	 * @param String $REQUEST_DESCRIPTION <br />Request name (e.g. SMS_SEND)<br />
	 * @param String $REQUEST_IDENTIFIER <br />Request identifier (e.g. self::$CHIKKA_LAST_SEND_INDEX)<br />
	 * @return string
	 */
	public static function REF_PARAM_GENERATE_LOADFLOW_KEY
	(
		$REQUEST_DESCRIPTION,
		$REQUEST_IDENTIFIER
	)
	{
		$NOW =  PHPVC_DATETIME::VAR_NOW();
	
		return  PHPVC_DATETIME::VAR_YEAR($NOW) . "_" .
				PHPVC_DATETIME::VAR_MONTH($NOW) . "_" .
				PHPVC_DATETIME::VAR_DAY($NOW) . "::" .
				PHPVC_STR::VAR_REPLACE
					(
						PHPVC_STR::VAR_UCASE($REQUEST_DESCRIPTION), 
						' ', 
						'_'
					) . "::" .
					PHPVC_STR::VAR_REPLACE
					(
						PHPVC_STR::VAR_UCASE($REQUEST_IDENTIFIER),
						' ',
						'_'
					);			
	}
	
	
	
	// ==================================================================
	//					CHIKKA COMMON METHODS
	// ==================================================================
	
	/**
	 * Log Chikka Transaction errors
	 * @param String $TRANSACTION_TYPE Transaction type handled. It should be INCOMING, REPLY, SEND, or OUTGOING
	 * @param unknown $ERROR_MESSAGE
	 * @param unknown $JSON_STRING
	 */
	Private Static Function REF_LOG_ERROR($TRANSACTION_TYPE, $ERROR_MESSAGE, $JSON_STRING)
	{
		// Missing Transaction Type
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($TRANSACTION_TYPE))
		{
			PHPVC_LOG::VAR_ERROR("Chikka", "SMS [UNKNOWN TRANSACTION]");
			PHPVC_LOG::VAR_ERROR("Log Error", "No transaction type given.");
			PHPVC_LOG::VAR_ERROR("JSON", $JSON_STRING);
			PHPVC_LOG::VAR_BR();
			return;
		}
		$TRANSACTION_TYPE = PHPVC_STR::VAR_FIX($TRANSACTION_TYPE);
		$TRANSACTION_TYPE = PHPVC_STR::VAR_UCASE($TRANSACTION_TYPE);
		
		// Missing Error Message
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($ERROR_MESSAGE))
		{
			PHPVC_LOG::VAR_ERROR("Chikka", "SMS [" . $TRANSACTION_TYPE . "]");
			PHPVC_LOG::VAR_ERROR("Log Error", "No error message given.");
			PHPVC_LOG::VAR_ERROR("JSON", $JSON_STRING);
			PHPVC_LOG::VAR_BR();
			return;
		}
		else
		{
			self::$CHIKKA_ERROR_MESSAGE = $ERROR_MESSAGE;
		}
		
		// Check if transaction type valid
		// ........................................
		if
		(
			$TRANSACTION_TYPE == "INCOMING" ||
			$TRANSACTION_TYPE == "REPLY" ||
			$TRANSACTION_TYPE == "SEND" ||
			$TRANSACTION_TYPE == "OUTGOING"
		)
		{
			PHPVC_LOG::VAR_ERROR("Chikka", "SMS [" . $TRANSACTION_TYPE . "]");
			PHPVC_LOG::VAR_ERROR("Cause", self::$CHIKKA_ERROR_MESSAGE);
			PHPVC_LOG::VAR_ERROR("JSON Response", $JSON_STRING);
			PHPVC_LOG::VAR_BR();
			return;
		}
		
		// Invalid Transaction
		// ........................................
		else
		{
			PHPVC_LOG::VAR_ERROR("Chikka", "SMS [" . $TRANSACTION_TYPE . "]");
			PHPVC_LOG::VAR_ERROR("Log Error", "Invalid Transaction Type. Expecting [incoming, reply, send, or outgoing]");
			PHPVC_LOG::VAR_ERROR("JSON", $JSON_STRING);
			PHPVC_LOG::VAR_BR();
			return;
		}
	}
	
	/**
	 * Retrieve received SMS service code (e.g. [REGISTER xxx.xxxxx] returns [REGISTER])
	 * @return string
	 */
	public static function REF_FETCH_CODE()
	{
		// Check MESSAGE Parameter if exists
		if(isset($_POST['message']))
		{
			$STRING_ARR = explode(" ", $_POST['message']);
			if(empty($STRING_ARR))
			{
				return "";
			}
			else
			{
				return PHPVC_STR::VAR_FIX($STRING_ARR[0]);
			}
		}
		
		// Message param not exists
		else
		{
			return "";
		}
	}
	
	/**
	 * Checks if the shortcode format is valid or not
	 * @param unknown $SHORT_CODE
	 * @return boolean
	 */
	Public Static Function REF_IS_VALID_SHORTCODE($SHORT_CODE)
	{
		if
		(
				PHPVC_STR::VAR_CONTAINS_LEFT($SHORT_CODE, '29290') &&
				Strlen($SHORT_CODE) == 8 &&
				PHPVC_NUM::VAR_IS_NUMERIC($SHORT_CODE)
		)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	
	/**
	 * Terminates php request and send reply result to chikka api. This will terminates the PHP.
	 * @param unknown $IS_SUCCESS
	 */
	public static function REF_ON_COMPLETION($IS_SUCCESS)
	{
		if($IS_SUCCESS === true)
		{
			echo 'Accepted';
			exit();
		}
		else
		{
			echo 'Error';
			exit();
		}
	}

	// ==================================================================
	//					CHIKKA COMMON METHODS [VALIDATIONS]
	// ==================================================================
	/**
	 * Validate if Shortcode is legit
	 * @param unknown $SHORTCODE_TO_VALIDATE
	 * @return boolean
	 */
	public static function REF_VALIDATE_SHORTCODE($SHORTCODE_TO_VALIDATE)
	{
		// Access to mobile only auth admin
		PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
			
		// Get response database
		$DATA_SET = PHPCUS_MOBILE_SHORTCODE::CUS_GET
		(
			PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
			PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
			$SHORTCODE_TO_VALIDATE
		);
					
		// Load response message
		if(empty($DATA_SET) === false)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	/**
	 * Validate Company Code if legit.
	 * @param unknown $SHORTCODE_TO_VALIDATE
	 * @param unknown $COMPANY_CODE_TO_VALIDATE
	 * @return boolean
	 */
	public static function REF_VALIDATE_COMPANY_CODE
	(
		$SHORTCODE_TO_VALIDATE, 
		$COMPANY_CODE_TO_VALIDATE
	)
	{
		// Parameter Validation
		if
		(
			PHPVC_STR::VAR_IS_BLANK($SHORTCODE_TO_VALIDATE) ||
			PHPVC_STR::VAR_IS_BLANK($COMPANY_CODE_TO_VALIDATE)
		)
		{
			return false;
		}
		
		// Access to mobile only auth admin
		PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
		
		// Get response database
		$DATA_SET = PHPCUS_MOBILE_SHORTCODE::CUS_GET
		(
			PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
			PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
			$SHORTCODE_TO_VALIDATE,
			$COMPANY_CODE_TO_VALIDATE
		);
		
		// Load response message
		if(empty($DATA_SET) === false)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	// ==================================================================
	//					CHIKKA MESSAGE SENDER
	// ==================================================================
	
	/**
	 * Validate parameter for chikka requests. Returns error message if invalid.
	 * @param PDO $SQL_CONNECTION SQLConnection to be used to store outbox messages.
	 * @param String $MOBILE_NUMBER Mobile number where the message to be sent to. Can assign multiple numbers with comma(,).
	 * @param String $SHORT_CODE ShortCode given by the chikka.
	 * @param String $SEND_MESSAGE Message to be send, should be 420 or less characters.
	 * @param String $CLIENT_ID Chikka provided ClientID given to this website. (Public Key)
	 * @param String $SECRET_KEY Chikka provided SecretKey given to this website. (Private Key)
	 * @return string Error message, if valid parameters are given, returns empty string.
	 */
	private static function REF_SEND_SMS_VALIDATE
	(
			$MOBILE_NUMBER,
			$SHORT_CODE,
			$SEND_MESSAGE,
			$CLIENT_ID,
			$SECRET_KEY
	)
	{
		try
		{
			// Chikka is disabled
			// ........................................
			if(PHPSET::CHIKKA_ENABLED === false)
			{
				// return "CHIKKA IS DISABLED.";
			}
			
			// CHECK PHONE NUMBERS
			// ........................................
			$MOBILE_FOUND = false;
			$MOBILE_INDEX = 0;
			$SMS_MOBILE_NUMBERS = explode(",", $MOBILE_NUMBER);
			$SMS_MOBILE_CURRENT_NUMBER = "";
			
			while
			(
					ISSET($SMS_MOBILE_NUMBERS) &&
					count($SMS_MOBILE_NUMBERS) > $MOBILE_INDEX
			)
			{
				$SMS_MOBILE_CURRENT_NUMBER = $SMS_MOBILE_NUMBERS[$MOBILE_INDEX];
				if(PHPVC_STR::VAR_IS_PHONE(PHPVC_STR::VAR_FIX($SMS_MOBILE_CURRENT_NUMBER)) === false)
				{
					return "INVALID PHONE NUMBER. `" . $SMS_MOBILE_CURRENT_NUMBER . "` IS NOT A VALID MOBILE PHONE NUMBER.";
				}
				else if($MOBILE_INDEX > 10)
				{
					return "TOO MANY SENDER. REQUESTS IS LIMITED TO 10 AT MAXIMUM.";
				}
				else
				{
					$MOBILE_FOUND = true;
				}
				
				$MOBILE_INDEX ++;
			}
			
			
			// CHECK VALID MOBILE # EXISTS
			// ........................................
			if($MOBILE_FOUND === false)
			{
				return "THERE'S NO VALID MOBILE NUMBER.";
			}
			
			// INVALID SHORT CODE
			// ........................................
			if
			(
				self::REF_IS_VALID_SHORTCODE($SHORT_CODE) == false
			)
			{
				return "INVALID CHIKKA SHORT CODE `" . $SHORT_CODE . "`. IT MUST CONSTRUCTED AS `29290XXX`.";
			}
			
			// MESSAGE IS BLANK
			// ........................................
			if(PHPVC_STR::VAR_IS_BLANK($SEND_MESSAGE) === true)
			{
				return "MESSAGE CANNOT BE NULL.";
			}
			
			// MESSAGE IS TOO LONG
			// ........................................
			if(PHPVC_STR::VAR_LEN($SEND_MESSAGE) >= 420)
			{
				return "MESSAGE IS TOO LONG, MUST LESS THAN 420 CHARACTERS IN LENGTH.";
			}
			
			// INVALID CLIENT ID
			// ........................................
			if(PHPVC_STR::VAR_LEN($CLIENT_ID) <> 64)
			{
				return "INVALID CLIENT_ID. IT MUST 64 CHARACTERS LONG.";
			}
			
			// INVALID SECRET KEY
			// ........................................
			if(PHPVC_STR::VAR_LEN($SECRET_KEY) <> 64)
			{
				return "INVALID SECRET KEY. IT MUST 64 CHARACTERS LONG.";
			}
			
			// SUCCESS
			// ........................................
			return "";
		}
		catch(Exception $ERR)
		{
			return "ERR: " . $ERR->getMessage();
		}
	}

	/**
	 * Save [Sent SMS] details into database. Also checks for access rights.
	 * @param String $SHORT_CODE <br />Used Shortcode<br />
	 * @param String $COMPANY_CODE <br />Used Company Code<br />
	 * @param String $MOBILE_NUMBER <br />Receiver number. if sent to multiple number, give only one from the receivers.<br />
	 * @param String $SEND_MESSAGE <br />Message Sent<br />
	 * @throws Exception 
	 * @return boolean <br />TRUE on success, FALSE on failure. If FALSE caller should terminate the execution.<br />
	 */
	public static function REF_SEND_SMS_OUTBOX_INSERT
	(
		$TRANSACTION_ID,
		$SHORT_CODE,
		$COMPANY_CODE,
			
		$MOBILE_NUMBER,
		$SEND_MESSAGE
	)
	{
		// if already exists (handling multiple number send)
		// ~~~~~~~~~~~~~~~~~~~~~~~~~
		if
		(
			isset($TRANSACTION_ID) || 
			PHPVC_STR::VAR_IS_BLANK($TRANSACTION_ID) == false
		)
		{
			try
			{
				// Fetch existing counter
				$DATA_SET = PHPCUS_MOBILE_OUTBOX::CUS_GET
				(
						PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
						$TRANSACTION_ID
				);
				
				// Load response message
				if(empty($DATA_SET) === false)
				{
					self::$CHIKKA_LAST_SEND_INDEX = $TRANSACTION_ID;
					return true;
				}
			}
			catch(Excepion $ERR)
			{
				$TRANSACTION_ID = null;
			}
		}
		
		// Save outbox (also checks access rights)
		// ~~~~~~~~~~~~~~~~~~~~~~~~~
		try
		{
			// Save request
			$DATA_SET =
				PHPCUS_MOBILE_OUTBOX::CUS_SAVE
				(
						PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
						self::REF_PARAM_GENERATE_ID(),
						$SHORT_CODE,
						$COMPANY_CODE,
						
						$MOBILE_NUMBER,
						$SEND_MESSAGE,
						'false',
						PHPCUS_SP::STATUS_INACTIVE
				);
			
			// fetch result
			if
			(
				empty($DATA_SET) ||
				PHPRC_PDO_MYSQL_ARRAY::REF_FIELD_CONTAINS($DATA_SET, "INSERTED_ID") === false
			)
			{
				Throw new Exception("No inserted ID retrieved");
			}
			else
			{
				self::$CHIKKA_LAST_SEND_INDEX = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH($DATA_SET, "INSERTED_ID");
			}
			
			// return result
			return true;
		}
		catch(Exception $ERR)
		{
			self::REF_LOG_ERROR
			(
					'SEND',
					'SQL Failed. [Outbox/Insert]',
					$ERR->getMessage(),
					$RESPONSE_CONTENTS
					);
			return false;
		}
	}
	
	/**
	 * Update [Sent SMS] status at database. [False -> True] 
	 * @throws Exception
	 * @return boolean
	 */
	public static function REF_SEND_SMS_OUTBOX_UPDATE()
	{
		// Save outbox (update status)
		// ~~~~~~~~~~~~~~~~~~~~~~~~~
		try
		{
			// Save request
			$DATA_SET =
				PHPCUS_MOBILE_OUTBOX::CUS_SAVE
				(
						self::$CHIKKA_LAST_SEND_INDEX,
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
						
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,

						'true',
						PHPCUS_SP::STATUS_ACTIVE
				);
			
			// Fetch result
			if
			(
					empty($DATA_SET) ||
					PHPRC_PDO_MYSQL_ARRAY::REF_FIELD_CONTAINS($DATA_SET, "INSERTED_ID") === false
			)
			{
				Throw new Exception("No updated ID retrieved");
			}
			else
			{
				self::$CHIKKA_LAST_SEND_INDEX = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH($DATA_SET, "INSERTED_ID");
			}

			// return result
			return true;
		}
		catch(Exception $ERR)
		{
			self::REF_LOG_ERROR
			(
					'SEND',
					'SQL Failed. [Outbox/Update]',
					$ERR->getMessage(),
					$RESPONSE_CONTENTS
			);
			return false;
		}
	}
	
	/**
	 * Save [Sent SMS per Mobile Number] entry into database, as pending request.
	 * @param unknown $TRANSACTION_ID
	 * @param unknown $MOBILE_NUMBER
	 * @throws Exception
	 * @return boolean
	 */
	private static function REF_SEND_SMS_HISTORY_INSERT
	(
		$TRANSACTION_ID,
		$MOBILE_NUMBER
	)
	{
		// Save outbox (also checks access rights)
		// ~~~~~~~~~~~~~~~~~~~~~~~~~
		try
		{
			// Access to mobile only auth admin
			PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
			
			// Save request
			$DATA_SET =
				PHPCUS_MOBILE_OUTBOX_HISTORY::CUS_SAVE
				(
						PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
						self::$CHIKKA_LAST_SEND_INDEX,
						$TRANSACTION_ID,
						$MOBILE_NUMBER,
						PHPCUS_SP::STATUS_INACTIVE
				);
			
			// fetch result
			if
			(
				empty($DATA_SET) ||
				PHPRC_PDO_MYSQL_ARRAY::REF_FIELD_CONTAINS($DATA_SET, "INSERTED_ID") === false
			)
			{
				Throw new Exception("No inserted ID retrieved");
			}
			
			// return result
			return true;
		}
		catch(Exception $ERR)
		{
			self::REF_LOG_ERROR
			(
				'SEND',
				'SQL Failed [Outbox History/Insert].',
				$ERR->getMessage(),
				$RESPONSE_CONTENTS
			);
			return false;
		}
	}
	
	/**
	 * Add charges to SMS Send request
	 * @param unknown $SHORT_CODE <br />Shortcode used to Send<br />
	 * @param unknown $COMPANY_CODE <br />Company code used to send<br />
	 * @param unknown $UNIQUE_ID <br />Unique identifier<br />
	 * @return boolean
	 */
	private static function REF_SEND_SMS_OUTBOX_FEE_CHARGE
	(
		$SHORT_CODE,
		$COMPANY_CODE,
		$UNIQUE_ID
	)
	{
		// Access to mobile only auth admin
		PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
		
		return self::REF_ADJUST_LOAD
		(
			$SHORT_CODE,
			$COMPANY_CODE,
			"SMS_SEND_CHARGE",
			$UNIQUE_ID,
			"Message sent request [" + $UNIQUE_ID + "]",
			-1
		);
	}
	

	public static function REF_SEND_SMS_OUTBOX_FEE_REFUND
	(
		$SHORT_CODE,
		$COMPANY_CODE,
		$UNIQUE_ID
	)
	{
		// Access to mobile only auth admin
		PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
		
		self::REF_ADJUST_LOAD
		(
			$SHORT_CODE,
			$COMPANY_CODE,
			"SMS_SEND_REFUND",
			$UNIQUE_ID,
			"Message sending failure (refund) [" + $UNIQUE_ID + "]",
			1
		);
	}
	
	/**
	 * Send SMS message using chikka API
	 * @param PDO $SQL_CONNECTION SQLConnection to be used to store outbox messages.
	 * @param String $MOBILE_NUMBER Mobile number where the message to be sent to. Can assign multiple numbers with comma(,).
	 * @param String $SHORT_CODE ShortCode given by the chikka.
	 * @param String $SEND_MESSAGE Message to be send, should be 420 or less characters.
	 * @param String $CLIENT_ID Chikka provided ClientID given to this website. (Public Key)
	 * @param String $SECRET_KEY Chikka provided SecretKey given to this website. (Private Key)
	 * @return boolean|string
	 */
	public static function REF_SEND_SMS
	(	
			$TRANSACTION_ID,
			$MOBILE_NUMBER,
			$SHORT_CODE,
			$COMPANY_CODE,
			
			$SEND_MESSAGE,
			$CLIENT_ID,
			$SECRET_KEY
	)
	{		
		// INITIALIZATION
		// ........................................
		self::$CHIKKA_LAST_SEND_INDEX = 0;
		self::$CHIKKA_LAST_SEND_UNIQUE_ID = "";
		self::$CHIKKA_ERROR_MESSAGE = "";
		
		$SMS_SENT_SUCCESS = false;
		$SMS_SENT_FAILURE = false;
		$SMS_MOBILE_NUMBERS = null;
		$SMS_MOBILE_INDEX = 0;
		
		$RESPONSE_CONTENTS = "";
		$CHIKKA_JSON = null;
		
		try
		{	
			// SANITIZE PARAMETERS
			// ........................................
			$MOBILE_NUMBER = PHPVC_STR::VAR_REPLACE($MOBILE_NUMBER, " ", "");
			$MOBILE_NUMBER = PHPVC_STR::VAR_REPLACE($MOBILE_NUMBER, "+", "");
			$MOBILE_NUMBER = PHPVC_STR::VAR_REPLACE($MOBILE_NUMBER, "-", "");
			
			$SHORT_CODE = PHPVC_STR::VAR_FIX($SHORT_CODE);
			$SEND_MESSAGE = PHPVC_STR::VAR_FIX($SEND_MESSAGE);
			$CLIENT_ID = PHPVC_STR::VAR_FIX($CLIENT_ID);
			$SECRET_KEY = PHPVC_STR::VAR_FIX($SECRET_KEY);
			
			
			// VALIDATE PARAMETERS (will not save as outbox)
			// ........................................
			self::$CHIKKA_ERROR_MESSAGE = self::REF_SEND_SMS_VALIDATE($MOBILE_NUMBER, $SHORT_CODE, $SEND_MESSAGE, $CLIENT_ID, $SECRET_KEY);
			if(PHPVC_STR::VAR_IS_BLANK(self::$CHIKKA_ERROR_MESSAGE) === false)
			{
				self::REF_LOG_ERROR('SEND', 'Validation Failure', self::$CHIKKA_ERROR_MESSAGE);
				return false;
			}
			
			// Save outbox (also checks access rights)
			// ~~~~~~~~~~~~~~~~~~~~~~~~~
			if
			(
				self::REF_SEND_SMS_OUTBOX_INSERT
				(
					$TRANSACTION_ID,
					$SHORT_CODE, $COMPANY_CODE,
					$MOBILE_NUMBER, $SEND_MESSAGE
				) == false
			)
			{
				return false;
			}
			
			// SEND SMS (With multiple number request support, divided with (,))
			// ........................................
			$SMS_MOBILE_NUMBERS = explode(",", $MOBILE_NUMBER);
			$SMS_MOBILE_CURRENT_NUMBER = "";
			
			while(count($SMS_MOBILE_NUMBERS) > $SMS_MOBILE_INDEX)
			{
				
				// Adjust Load (deduct)
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				if
				(
					self::REF_SEND_SMS_OUTBOX_FEE_CHARGE
					(
						$SHORT_CODE, $COMPANY_CODE,
						self::$CHIKKA_LAST_SEND_INDEX
					) == false
				)
				{
					// Error handler
					self::REF_LOG_ERROR('SEND', "You don't have enough load to process this request.", null);
					return false;
				}
				
				// Prepare receiver mobile numbers
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				$SMS_MOBILE_CURRENT_NUMBER = $SMS_MOBILE_NUMBERS[$SMS_MOBILE_INDEX];
				$MOBILE_NUMBER = PHPVC_STR::VAR_FIX($SMS_MOBILE_CURRENT_NUMBER);
				
				// Prepare request parameter
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				$HTTP_PARAMS = "";
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "message_type", "SEND");
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "mobile_number", $MOBILE_NUMBER);
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "shortcode", $SHORT_CODE);
					
				self::$CHIKKA_LAST_SEND_UNIQUE_ID = self::REF_PARAM_GENERATE_ID();
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "message_id", self::$CHIKKA_LAST_SEND_UNIQUE_ID);
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "message", $SEND_MESSAGE);
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "client_id", $CLIENT_ID);
				$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "secret_key", $SECRET_KEY);
					
				// Send request
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				try 
				{
					if(PHPSET::CHIKKA_ENABLED == true)
					{
						$RESPONSE_CONTENTS = PHPRC_HTTP::REF_REQUEST("https://post.chikka.com/smsapi/request", $HTTP_PARAMS);
					}
					else
					{
						$RESPONSE_CONTENTS = "{\"status\":\"200\",\"message\":\"ACCEPTED\"}";
					}
				}
				catch(Exception $ERR)
				{
					// Adjust Load (refund)
					self::REF_SEND_SMS_OUTBOX_FEE_REFUND
					(
						$SHORT_CODE, $COMPANY_CODE,
						self::$CHIKKA_LAST_SEND_INDEX
					);
							
					// Error handler
					self::REF_LOG_ERROR('SEND', $ERR->getMessage(), 'NULL');
					PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
					return false;
				}
	
				// Validation [JSON]
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				if(PHPRC_JSON::REF_IS_JSON_STRING($RESPONSE_CONTENTS) === false)
				{
					// Adjust Load (refund)
					self::REF_SEND_SMS_OUTBOX_FEE_REFUND
					(
						$SHORT_CODE, $COMPANY_CODE,
						self::$CHIKKA_LAST_SEND_INDEX
					);
					
					// Error handler
					self::REF_LOG_ERROR('SEND', "Invalid JSON Response", $RESPONSE_CONTENTS);
					return false;
				}
				$CHIKKA_JSON = PHPRC_JSON::REF_CREATE($RESPONSE_CONTENTS);
				
				// Validation [Request Status]
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				if
				(
					PHPRC_JSON::REF_ISSET($CHIKKA_JSON, "status") === false || 
					PHPRC_JSON::REF_ISSET($CHIKKA_JSON, "message") === false
				)
				{
					// Adjust Load (refund)
					self::REF_SEND_SMS_OUTBOX_FEE_REFUND
					(
						$SHORT_CODE, $COMPANY_CODE,
						self::$CHIKKA_LAST_SEND_INDEX
					);
					
					// Error handler
					self::REF_LOG_ERROR('SEND', "Missing Status / Message Parameter", $RESPONSE_CONTENTS);
					return false;
				}
				
				// Validation [Request Status Value ( != 200 )]
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				if(PHPVC_NUM::VAR_NVAL(PHPRC_JSON::REF_READ($CHIKKA_JSON, "status")) <> 200)
				{
					// Adjust Load (refund)
					self::REF_SEND_SMS_OUTBOX_FEE_REFUND
					(
						$SHORT_CODE, $COMPANY_CODE,
						self::$CHIKKA_LAST_SEND_INDEX
					);
					
					// Error handler
					self::REF_LOG_ERROR
					(
						'SEND', 
						"Request failed. " . PHPRC_JSON::REF_READ($CHIKKA_JSON, "status") . " : " . 
						PHPRC_JSON::REF_READ($CHIKKA_JSON, "message"), 
						$RESPONSE_CONTENTS
					);
					return false;
				}
				
				// Save successfully sent request.
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				if
				(
					self::REF_SEND_SMS_HISTORY_INSERT
					(
						self::$CHIKKA_LAST_SEND_UNIQUE_ID,
						$MOBILE_NUMBER
					) == false
				)
				{
					return false;
				}
				
				// Increment Value
				// ~~~~~~~~~~~~~~~~~~~~~~~~~
				$SMS_MOBILE_INDEX ++;
			}
			
			// Save outbox (update status) and Return result
			// ........................................
			return self::REF_SEND_SMS_OUTBOX_UPDATE();
		}
		catch(Exception $ERR)
		{
			self::REF_LOG_ERROR('SEND', $ERR->getMessage(), $RESPONSE_CONTENTS);
			return false;
		}
	}
	
	

	// ==================================================================
	//					CHIKKA MESSAGE RECEIVER
	// ==================================================================
	
	/**
	 * Validate RECEIVED SMS parameters
	 * @param unknown $SQL_CONNECTION
	 * @param unknown $SEND_MESSAGE
	 * @param unknown $REQUEST_COST
	 * @param unknown $CLIENT_ID
	 * @param unknown $SECRET_KEY
	 * @return string Error message
	 */
	public static function REF_RECEIVE_SMS_VALIDATE($SEND_MESSAGE, $REQUEST_COST, $CLIENT_ID, $SECRET_KEY)
	{
		// SEND MESSAGE IS BLANK (Edit: if blank auto. added)
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($SEND_MESSAGE))
		{
			//return "Missing Response message to received text.";
		}
		
		// INVALID COST
		// ........................................
		$REQUEST_COST = PHPVC_STR::VAR_FIX($REQUEST_COST);
		$REQUEST_COST = PHPVC_STR::VAR_UCASE($REQUEST_COST);
		if
		(
			$REQUEST_COST <> "FREE" &&
			$REQUEST_COST <> "P1.00" &&
			$REQUEST_COST <> "P2.50" &&
			$REQUEST_COST <> "P5.00" &&
			$REQUEST_COST <> "P10.00" &&
			$REQUEST_COST <> "P15.00"
		)
		{
			return "Invalid rerquest cost [" . $REQUEST_COST . "] expecting [FREE/P1.00/P2.50/P5.00/P10.00/P15.00].";
		}
		
		// CHECK SMS RECEIVE PARAMETER
		// ........................................
		if(isset($_POST['message_type']) === false)
		{
			return "Missing Parameter [message_type]";
		}
		else if(PHPVC_STR::VAR_UCASE($_POST['message_type']) <> "INCOMING")
		{
			return "Wrong Parameter [message_type] = [" . $_POST['message_type'] . "], expecting [incoming]";
		}
		else if(isset($_POST['mobile_number']) === false)
		{
			return "Missing Parameter [mobile_number]";
		}
		else if(isset($_POST['shortcode']) === false)
		{
			return "Missing Parameter [shortcode]";
		}
		else if(isset($_POST['request_id']) === false)
		{
			return "Missing Parameter [request_id]";
		}
		else if(isset($_POST['message']) === false)
		{
			return "Missing Parameter [message]";
		}
		else if(isset($_POST['timestamp']) === false)
		{
			return "Missing Parameter [timestamp]";
		}
		
		// INVALID SHORT CODE
		// ........................................
		if
		(
			self::REF_IS_VALID_SHORTCODE($_POST['shortcode']) == false
		)
		{
			return "INVALID CHIKKA SHORT CODE `" . $SHORT_CODE . "`. IT MUST CONSTRUCTED AS `29290XXX`.";
		}
		
		// INVALID CLIENT ID
		// ........................................
		if(PHPVC_STR::VAR_LEN($CLIENT_ID) <> 64)
		{
			return "INVALID CLIENT_ID. IT MUST 64 CHARACTERS LONG.";
		}
		
		// INVALID SECRET KEY
		// ........................................
		if(PHPVC_STR::VAR_LEN($SECRET_KEY) <> 64)
		{
			return "INVALID SECRET KEY. IT MUST 64 CHARACTERS LONG.";
		}
		
		// No Error
		return "";
		
	}
	
			
	/**
	 * Check if the current SMS is blocked by spam filter.
	 * @param unknown $LIMIT_PER_PERIOD Max allowed SMS per number per period.
	 * @param unknown $LOCK_PERIOD Spam moniroting period.
	 * @return boolean Returns TRUE on spam message, else FALSE.
	 */
	public static function REF_RECEIVE_SMS_IS_SPAM
	(
		$LIMIT_PER_PERIOD,
		$LOCK_PERIOD
	)
	{
		// Compute Lock Period Time
		$PERIOD_STARTS_FROM = PHPVC_DATETIME::VAR_NOW();
		$PERIOD_STARTS_FROM = PHPVC_DATETIME::VAR_ADD_HOUR($PERIOD_STARTS_FROM, $LOCK_PERIOD * -1);
		
		// Access to mobile only auth admin
		PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
		
		// Get response database
		$DATA_SET = PHPCUS_MOBILE_INBOX::CUS_GET
		(
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				$_POST['shortcode'],
				$_POST['mobile_number'],
				self::$CHIKKA_LAST_SERVICE_CODE,
				
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				
				$PERIOD_STARTS_FROM,
				PHPRC_SQL_FLAGS::FLAG_DATETIME_NULL
		);
		
		// Load response message
		if(empty($DATA_SET) === false)
		{
			if
			(
				$LIMIT_PER_PERIOD >
				PHPRC_PDO_MYSQL_ARRAY::REF_FETCH_INT
				(
					$DATA_SET,
					'RECORD_COUNT'
				)
			)
			{
				return false;
			}
			else
			{
				return true;
			}
		}
		else
		{
			return false;
		}
	}
	
	
	/**
	 * Handles Chikka Message receiver
	 * @param String $SEND_MESSAGE Response to return.
	 * @param String $APPLIED_SERVICE_CODE Applied service code of message.
	 * @return boolean|unknown
	 */
	public static function REF_RECEIVE_SMS
	(
			$SEND_MESSAGE = null, 
			$APPLIED_COMPANY_CODE = null, 
			$APPLIED_SERVICE_CODE = null, 
			$APPLIED_SERVICE_CHARGE = null
	)
	{
		// Initialize
		self::$CHIKKA_LAST_SEND_INDEX = 0;
		self::$CHIKKA_LAST_REQUEST_COST = PHPSET::CHIKKA_DEFAULT_CHARGE;
		self::$CHIKKA_LAST_COMPANY_CODE = "";
		self::$CHIKKA_LAST_SERVICE_CODE = "";
		self::$CHIKKA_LAST_IS_SPAM = false;
		self::$CHIKKA_LAST_IS_VOLUME_LIMIT = false;
		
		// Check if optional parameters is passed correctly
		if
		(
			(
				isset($SEND_MESSAGE) ||
				isset($APPLIED_COMPANY_CODE) ||
				isset($APPLIED_SERVICE_CODE) ||
				isset($APPLIED_SERVICE_CHARGE)
			) &&
			(
				isset($SEND_MESSAGE) == false ||
				isset($APPLIED_COMPANY_CODE) == false ||
				isset($APPLIED_SERVICE_CODE) == false ||
				isset($APPLIED_SERVICE_CHARGE) == false
			)
		)
		{
			$SEND_MESSAGE = 'Server error:: Invalid arguments. Please contact the system administrator.';
			$APPLIED_COMPANY_CODE = '';
			$APPLIED_SERVICE_CODE = 'ON_ERROR';
		}
	
		// Initialize
		$REQUEST_COST = PHPSET::CHIKKA_DEFAULT_CHARGE;
		$CLIENT_ID = '';
		$SECRET_KEY = '';
		
		// Load Keys from shortcode
		if
		(
			isset($_POST['shortcode']) && 
			PHPVC_STR::VAR_IS_BLANK($_POST['shortcode']) == false
		)
		{
			// Access to mobile only auth admin
			PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
			
			// Get response database
			$DATA_SET = PHPCUS_MOBILE_SHORTCODE::CUS_GET
			(
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				$_POST['shortcode'],
					
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
				PHPRC_SQL_FLAGS::FLAG_DECIMAL_NULL,
				PHPRC_SQL_FLAGS::FLAG_DECIMAL_NULL,
				PHPRC_SQL_FLAGS::FLAG_TINYINT_NULL,
					
				"MOBILE_GROUP_ID",
				"ASC"
			);
			
			// Load ShortCode Key
			if(empty($DATA_SET) === false)
			{
				$CLIENT_ID = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
					(
						$DATA_SET,
						'MOBILE_CLIENT_ID'
					);

				$SECRET_KEY = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
					(
						$DATA_SET,
						'MOBILE_SECRET_KEY'
					);
			}
			else
			{
				self::REF_LOG_ERROR('INCOMING', 'Key retrieval Failure', 'Unable to load the requested ShortCode [' . $_POST['shortcode'] . '] security keys.');
				return false;
			}
		}
		
		// Parameter Validation
		self::$CHIKKA_ERROR_MESSAGE = "";
		self::$CHIKKA_ERROR_MESSAGE = self::REF_RECEIVE_SMS_VALIDATE($SEND_MESSAGE, $REQUEST_COST, $CLIENT_ID, $SECRET_KEY);
		if(PHPVC_STR::VAR_IS_BLANK(self::$CHIKKA_ERROR_MESSAGE) === false)
		{
			self::REF_LOG_ERROR('INCOMING', 'Validation Failure', self::$CHIKKA_ERROR_MESSAGE);
			return false;
		}
		
		// Actual Function
		$RESPONSE_CONTENTS = "";
		try
		{
			// Fetch and identify COMPANY CODE / SERVICE CODE
			// ........................................
			if
			(
				isset($APPLIED_COMPANY_CODE) == false && 
				PHPVC_STR::VAR_IS_BLANK($APPLIED_SERVICE_CODE)
			)
			{
				self::$CHIKKA_LAST_COMPANY_CODE = self::REF_FETCH_CODE();
				if
				(
						self::REF_VALIDATE_COMPANY_CODE
						(
								$_POST['shortcode'],
								self::$CHIKKA_LAST_COMPANY_CODE
						) == false
				)
				{
					self::$CHIKKA_LAST_SERVICE_CODE = self::$CHIKKA_LAST_COMPANY_CODE;
					self::$CHIKKA_LAST_COMPANY_CODE = "";
				}
				else
				{
					if(StrLen($_POST['message']) > StrLen(self::$CHIKKA_LAST_COMPANY_CODE) + 1)
					{
						$_POST['message'] = PHPVC_STR::VAR_DLEFT($_POST['message'], StrLen(self::$CHIKKA_LAST_COMPANY_CODE) + 1);
					}
					else
					{
						$_POST['message'] = '';
					}
					self::$CHIKKA_LAST_SERVICE_CODE = self::REF_FETCH_CODE();
				}	
			}
			else
			{
				self::$CHIKKA_LAST_COMPANY_CODE = $APPLIED_COMPANY_CODE;
				self::$CHIKKA_LAST_SERVICE_CODE = $APPLIED_SERVICE_CODE;
			}

			
			// Prepare response message if NULL [need to handle else, when specific body text is given]
			// ........................................
			if(PHPVC_STR::VAR_IS_BLANK($SEND_MESSAGE))
			{
				$SEND_MESSAGE = self::REF_RECEIVE_SMS_AUTO_RESPONSE_CODE
				(
					$_POST['shortcode'],
					self::$CHIKKA_LAST_COMPANY_CODE,
					self::$CHIKKA_LAST_SERVICE_CODE
				);
				$REQUEST_COST = self::$CHIKKA_LAST_REQUEST_COST;
			}
			
			// Prepare Parameter
			// ........................................
			$HTTP_PARAMS = "";
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "message_type", "REPLY");
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "mobile_number", $_POST['mobile_number']);
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "shortcode", $_POST['shortcode']);
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "request_id", $_POST['request_id']);
			
			self::$CHIKKA_LAST_SEND_UNIQUE_ID = self::REF_PARAM_GENERATE_ID();
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "message_id", self::$CHIKKA_LAST_SEND_UNIQUE_ID);
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "message", $SEND_MESSAGE);
			
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "request_cost", $REQUEST_COST);
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "client_id", $CLIENT_ID);
			$HTTP_PARAMS = PHPRC_HTTP_PARAM::REF_ADD($HTTP_PARAMS, "secret_key", $SECRET_KEY);
			
			// Send request
			// ........................................
			try
			{
				if(PHPSET::CHIKKA_ENABLED == true)
				{
					$RESPONSE_CONTENTS = PHPRC_HTTP::REF_REQUEST("https://post.chikka.com/smsapi/request", $HTTP_PARAMS);
				}
				else
				{
					$RESPONSE_CONTENTS = "{\"status\":\"200\",\"message\":\"ACCEPTED\"}";
				}
				$RESPONSE_CONTENTS = "{\"status\":\"200\" ,\"message\":\"ACCEPTED\"}";
				PHPVC_LOG::VAR_COMMENTS('CHIKKA REPTY', $SEND_MESSAGE);
			}
			catch(Exception $ERR)
			{
				self::REF_LOG_ERROR('INCOMING', $ERR->getMessage(), 'NULL');
				PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
				return false;
			}
			
			// Validation [JSON]
			// ........................................
			if(PHPRC_JSON::REF_IS_JSON_STRING($RESPONSE_CONTENTS) === false)
			{
				self::REF_LOG_ERROR('INCOMING', "Invalid JSON Response", $RESPONSE_CONTENTS);
				return false;
			}
			$CHIKKA_JSON = PHPRC_JSON::REF_CREATE($RESPONSE_CONTENTS);
			
			// Validation [Request Status]
			// ........................................
			if
			(
					PHPRC_JSON::REF_ISSET($CHIKKA_JSON, "status") === false ||
					PHPRC_JSON::REF_ISSET($CHIKKA_JSON, "message") === false
			)
			{
				self::REF_LOG_ERROR('INCOMING', "Missing Status / Message Parameter", $RESPONSE_CONTENTS);
				return false;
			}
			
			// Validation [Request Status Value ( != 200 )]
			// ........................................
			if(PHPVC_NUM::VAR_NVAL(PHPRC_JSON::REF_READ($CHIKKA_JSON, "status")) <> 200)
			{
				self::REF_LOG_ERROR
				(
						'INCOMING',
						"Request failed. " . PHPRC_JSON::REF_READ($CHIKKA_JSON, "status") . " : " .
						PHPRC_JSON::REF_READ($CHIKKA_JSON, "message"),
						$RESPONSE_CONTENTS
				);
				return false;
			}
			
			// SAVE SMS
			// ........................................
			try 
			{
				// Access to mobile only auth admin
				PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
				
				// Remove ServiceCode from Message Body
				$MESSAGE_BODY = PHPVC_STR::VAR_FIX($_POST['message']);
				if(PHPVC_STR::VAR_CONTAINS_LEFT($MESSAGE_BODY, self::$CHIKKA_LAST_SERVICE_CODE))
				{
					if(PHPVC_STR::VAR_LEN($MESSAGE_BODY) > PHPVC_STR::VAR_LEN(self::$CHIKKA_LAST_SERVICE_CODE))
					{
						$MESSAGE_BODY = PHPVC_STR::VAR_DLEFT($MESSAGE_BODY, PHPVC_STR::VAR_LEN(self::$CHIKKA_LAST_SERVICE_CODE));
					}
					else
					{
						$MESSAGE_BODY = 'No Message';
					}
				}
				
				// Send Save request
				$DATA_SET = PHPCUS_MOBILE_INBOX::CUS_SAVE
				(
						PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
						$_POST['request_id'],
						$_POST['shortcode'],
						PHPVC_STR::VAR_UCASE(self::$CHIKKA_LAST_COMPANY_CODE),
						
						$_POST['mobile_number'],
						PHPVC_STR::VAR_UCASE(self::$CHIKKA_LAST_SERVICE_CODE),
						$MESSAGE_BODY,
						$SEND_MESSAGE,
						$REQUEST_COST,
						'true',
						1
				);
				
				// Get inserted ID
				if
				(
						empty($DATA_SET) ||
						PHPRC_PDO_MYSQL_ARRAY::REF_FIELD_CONTAINS($DATA_SET, "INSERTED_ID") === false
				)
				{
					Throw new Exception("No inserted ID retrieved");
				}
				else
				{
					$CHIKKA_LAST_SEND_INDEX = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH($DATA_SET, "INSERTED_ID");
				}
			}
			catch(Exception $ERR)
			{
				self::REF_LOG_ERROR
				(
						'INCOMING',
						'SQL Failed.',
						$ERR->getMessage(),
						$RESPONSE_CONTENTS
				);
				return false;
			}
			
			// Return success
			// ........................................
			return true;
		}
		catch (Exception $ERR)
		{
			self::REF_LOG_ERROR
			(
					'INCOMING',
					'Thrown Exception',		
					$ERR->getMessage(),
					$RESPONSE_CONTENTS
			);
			return false;
		}
	}
	
	
	// ==================================================================
	//					CHIKKA NOTIFICATION RECEIVER
	// ==================================================================
	
	/**
	 * Validates the notification receiver POST status
	 * @return string
	 */
	private static function REF_NOTIFICATION_VALIDATE()
	{
		// CHECK SMS RECEIVE PARAMETER
		// ........................................
		if(isset($_POST['message_type']) === false)
		{
			return "Missing Parameter [message_type]";
		}
		else if(PHPVC_STR::VAR_UCASE($_POST['message_type']) <> "OUTGOING")
		{
			return "Wrong Parameter [message_type] = [" . $_POST['message_type'] . "], expecting [outgoing]";
		}	
		else if(isset($_POST['shortcode']) === false)
		{
			return "Missing Parameter [shortcode]";
		}
		else if(isset($_POST['message_id']) === false)
		{
			return "Missing Parameter [message_id]";
		}
		else if(isset($_POST['status']) === false)
		{
			return "Missing Parameter [status]";
		}
		else if(isset($_POST['credits_cost']) === false)
		{
			return "Missing Parameter [credits_cost]";
		}
		else if(isset($_POST['timestamp']) === false)
		{
			return "Missing Parameter [timestamp]";
		}
		
		// INVALID SHORT CODE
		// ........................................
		if
		(
				self::REF_IS_VALID_SHORTCODE($_POST['shortcode']) == false
		)
		{
			return "INVALID CHIKKA SHORT CODE `" . $SHORT_CODE . "`. IT MUST CONSTRUCTED AS `29290XXX`.";
		}
		
		// RETURN SUCCESS
		// ........................................
		return "";
	}
	
	/**
	 * Save Chikka notification into the database
	 */
	public static function REF_NOTIFICATION_RECEIVER()
	{
		// Parameter Validation
		self::$CHIKKA_ERROR_MESSAGE = "";
		self::$CHIKKA_ERROR_MESSAGE = self::REF_NOTIFICATION_VALIDATE();
		if(PHPVC_STR::VAR_IS_BLANK(self::$CHIKKA_ERROR_MESSAGE) === false)
		{
			self::REF_LOG_ERROR('OUTGOING', 'Validation Failure', self::$CHIKKA_ERROR_MESSAGE);
			echo "Error";
			exit();
		}
		
		// Actual Function
		try
		{
			// Check Status
			if(PHPVC_STR::VAR_UCASE($_POST["status"]) == "SENT")
			{
				$STATUS_VAL = 2;
			}
			else 
			{
				$STATUS_VAL = 1;
			}
			
			// Access to mobile only auth admin
			PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE
			(
					'mobile', 
					'$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG'
			);
			
			// Save notification to database
			PHPCUS_MOBILE_NOTIFICATION::CUS_SAVE
			(
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
					$_POST["message_id"],
					$_POST["shortcode"],
					$_POST["credits_cost"],
					'true',
					$STATUS_VAL
			);
			
			// return result
			echo "Accepted";
			exit;
		}
		catch (Exception $ERR)
		{
			self::REF_LOG_ERROR('OUTGOING', 'Thrown Exception', $ERR->getMessage());
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			echo "Error";
			exit();	
		}
	}
	

	
	
	// ==================================================================
	//					CHIKKA SQL FUNCTIONALITIES
	// ==================================================================
	
	/**
	 * Prepare auto response code for the invalid service code request
	 * @param unknown $SHORTCODE
	 * @return string
	 */
	Public Static Function REF_SERVICE_CODE_ON_ERROR
	(
		$SHORTCODE,
		$COMPANY_CODE
	)
	{
		// Get Message Service Code
		// ........................................
		$RESPONSE_MESSAGE = "";
		$SERVICE_CODE = "ON_ERROR";
		
		// Handle invalid service code
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
		{
			// Access to mobile only auth admin
			PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
			
			// Get response database
			$DATA_SET = PHPCUS_MOBILE_SERVICE_CODE::CUS_GET
			(
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
				$SHORTCODE,
				$COMPANY_CODE,
				$SERVICE_CODE
			);
			
			// Load response message
			if(empty($DATA_SET) === false)
			{
				self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
				self::$CHIKKA_LAST_REQUEST_COST = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
				(
					$DATA_SET,
					'SCODE_CHARGE'
				);
				
				$RESPONSE_MESSAGE = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
				(
					$DATA_SET,
					'SCODE_RESPONSE'
				);
			}
		}
			
		// Hanlde if no available error message given for invalid service code
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
		{
			self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
			$RESPONSE_MESSAGE = "Incorrect code. Please check your code and try again.";
		}
			
		// Return result
		// ........................................
		return $RESPONSE_MESSAGE;
	}
	
	/**
	 * Prepare auto response code for the volume limit request.
	 * @param unknown $SHORTCODE
	 * @return string
	 */
	Public Static Function REF_SERVICE_CODE_ON_VOLUME_LIMIT
	(
			$SHORTCODE,
			$COMPANY_CODE
	)
	{
		// Get Message Service Code
		// ........................................
		$RESPONSE_MESSAGE = "";
		$SERVICE_CODE = "ON_VOLUME_LIMIT";
		
		// Handle invalid service code
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
		{
			// Access to mobile only auth admin
			PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
			
			// Get response database
			$DATA_SET = PHPCUS_MOBILE_SERVICE_CODE::CUS_GET
			(
					PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
					$SHORTCODE,
					$COMPANY_CODE,
					$SERVICE_CODE
			);
			
			// Load response message
			if(empty($DATA_SET) === false)
			{
				self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
				self::$CHIKKA_LAST_REQUEST_COST = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
				(
					$DATA_SET,
					'SCODE_CHARGE'
				);
				
				$RESPONSE_MESSAGE = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
				(
					$DATA_SET,
					'SCODE_RESPONSE'
				);
			}
		}
		
		// Hanlde if no available error message given for invalid service code
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
		{
			self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
			$RESPONSE_MESSAGE = "Similar request has already been processed. Please try again later.";
		}
		
		// Return result
		// ........................................
		return $RESPONSE_MESSAGE;
	}
	
	/**
	 * Prepare auto response code for the spam request
	 * @param unknown $SHORTCODE
	 * @return string
	 */
	Public Static Function REF_SERVICE_CODE_ON_SPAM
	(
		$SHORTCODE,
		$COMPANY_CODE
	)
	{
		// Get Message Service Code
		// ........................................
		$RESPONSE_MESSAGE = "";
		$SERVICE_CODE = "ON_SPAM";
		
		// Handle invalid service code
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
		{
			// Access to mobile only auth admin
			PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
			
			// Get response database
			$DATA_SET = PHPCUS_MOBILE_SERVICE_CODE::CUS_GET
			(
					PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
					$SHORTCODE,
					$COMPANY_CODE,
					$SERVICE_CODE
			);
			
			// Load response message
			if(empty($DATA_SET) === false)
			{
				self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
				self::$CHIKKA_LAST_REQUEST_COST = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
				(
					$DATA_SET,
					'SCODE_CHARGE'
				);
				
				$RESPONSE_MESSAGE = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
				(
					$DATA_SET,
					'SCODE_RESPONSE'
				);
			}
		}
		
		// Hanlde if no available error message given for invalid service code
		// ........................................
		if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
		{
			self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
			$RESPONSE_MESSAGE = "Sorry, this service is not available with your number.";
		}
		
		// Return result
		// ........................................
		return $RESPONSE_MESSAGE;
	}
	
	/**
	 * Add or deduct load amount from mobile entry.
	 * @param String $SHORTCODE <br />Requester Shortcode.<br />
	 * @param String $COMPANY_CODE <br />Requester Company code.<br />
	 * @param String $ADJUSTMENT_REQUEST_TYPE <br />Request Code. (e.g. SMS_SEND)<br />
	 * @param String/Integer $ADJUSTMENT_UNIQUE_KEY <br />Request Unique key. (e.g. self::$CHIKKA_LAST_SEND_INDEX)<br />
	 * @param String $ADJUSTMENT_DESCRIPTION <br />Description to be saved on load flow log.
	 * @param Double $ADJUSTMENT_AMOUNT <br />[IN] or [OUT] of loadflow<br />
	 * @throws Exception
	 * @return boolean
	 */
	public static function REF_ADJUST_LOAD
	(
		$SHORTCODE,
		$COMPANY_CODE,
			
		$ADJUSTMENT_REQUEST_TYPE,
		$ADJUSTMENT_UNIQUE_KEY,	
		$ADJUSTMENT_DESCRIPTION,
		$ADJUSTMENT_AMOUNT
	)
	{
		// Adjust Amount
		try
		{
			// Get unique key
			$LOADFLOW_KEY = self::REF_PARAM_GENERATE_LOADFLOW_KEY
							(
								$ADJUSTMENT_REQUEST_TYPE, 
								$ADJUSTMENT_UNIQUE_KEY
							);
			
			// Get shortcode ID
			$DATA_SET = PHPCUS_MOBILE_SHORTCODE::CUS_GET
			(
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
				$SHORTCODE,
				$COMPANY_CODE
			);
			
			// fetch result
			$MOBILE_ID = 0;
			if
			(
				empty($DATA_SET) ||
				PHPRC_PDO_MYSQL_ARRAY::REF_FIELD_CONTAINS($DATA_SET, "MOBILE_ID") === false
			)
			{
				Throw new Exception("Unable to retrieve shortcode ID with SHORTCODE[" + $SHORTCODE + "] / COMPANY CODE[" + $COMPANY_CODE + "]");
			}
			else
			{
				$MOBILE_ID =PHPRC_PDO_MYSQL_ARRAY::REF_FETCH($DATA_SET, "MOBILE_ID");
			}
			
			// Apply Adjustment
			$DATA_SET = PHPCUS_MOBILE_LOADFLOW::CUS_SAVE
			(
				PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
				$MOBILE_ID,
				$LOADFLOW_KEY,
				$ADJUSTMENT_DESCRIPTION,
				$ADJUSTMENT_AMOUNT,
				PHPCUS_SP::STATUS_ACTIVE
			);
			
			// Adjustment success
			return true;
		}
		catch(Excepion $ERR)
		{
			// Check not enough load
			if
			(
				$ERR->getMessage() <> null &&
				PHPVC_STR::VAR_IS_BLANK($ERR->getMessage()) == false &&
				PHPVC_STR::VAR_CONTAINS($ERR->getMessage(), 'Not enough load.')
			)
			{
				return false;
			}

			// Error
			else
			{
				self::REF_LOG_ERROR('LOAD ADJUST', 'Thrown Exception', $ERR->getMessage());
				PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			}
		}
	}
	
	
	/**
	 * Fetch a automated response code for the chikka
	 * @param unknown $SHORTCODE
	 * @param unknown $RECEIVED_MESSAGE
	 */
	Public Static Function REF_RECEIVE_SMS_AUTO_RESPONSE_CODE
	(
		$SHORTCODE, 
		$COMPANY_CODE, 
		$SERVICE_CODE
	)
	{
		// Parameter Validation
		PHPVC_AV::VAR_VALIDATE_NULL($SHORTCODE, 'SHORTCODE');
		
		// Actual Function
		try
		{
			// Get Message Service Code
			// ........................................
			PHPVC_LOG::VAR_INFO("COMPANY CODE", $COMPANY_CODE);
			PHPVC_LOG::VAR_INFO("SERVICE CODE", $SERVICE_CODE);
			$RESPONSE_MESSAGE = "";
			
			// Get corresponding response message
			// ........................................
			if(PHPVC_STR::VAR_IS_BLANK($SERVICE_CODE) === false)
			{
				// Access to mobile only auth admin
				PHPCUS_SP::CUS_AUTHENTICATION_OVERRIDE('mobile', '$2y$10$qav38ZPeS0fNyCc7SD.4xe2o8G5pvE2FuENkjCzCA.6IFIIEpWnoG');
				
				// Adjust IS_NULL_FLAG
				if(PHPVC_STR::VAR_IS_BLANK($COMPANY_CODE))
				{
					$COMPANY_CODE = PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL;
				}
				
				// Get response database
				$DATA_SET = PHPCUS_MOBILE_SERVICE_CODE::CUS_GET
				(
						PHPRC_SQL_FLAGS::FLAG_BIGINT_NULL,
						$SHORTCODE,
						$COMPANY_CODE,
						$SERVICE_CODE,
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
						PHPRC_SQL_FLAGS::FLAG_NVARCHAR_NULL,
						
						PHPRC_SQL_FLAGS::FLAG_TINYINT_NULL,
						PHPRC_SQL_FLAGS::FLAG_INT_NULL,
						PHPRC_SQL_FLAGS::FLAG_INT_NULL,
						
						PHPCUS_System::STATUS_ACTIVE
				);
				

	
				// Load response message
				if(empty($DATA_SET) === false)
				{
					// Check Volume Control Limit
					self::$CHIKKA_LAST_IS_VOLUME_LIMIT =
						PHPCUS_MOBILE_VOLUME_CONTROL::CUS_IS_VOLUME_LIMIT
						(
								$SHORTCODE,
								$COMPANY_CODE,
								$SERVICE_CODE,
								$_POST['mobile_number']
						);	
					if(self::$CHIKKA_LAST_IS_VOLUME_LIMIT == true)
					{
						$RESPONSE_MESSAGE = self::REF_SERVICE_CODE_ON_VOLUME_LIMIT($SHORTCODE, $COMPANY_CODE);
					}
					
					// Check Spam Filter Status [2 = Active, 1 = Inactive]
					// [NO SPAM FILTER IMPLEMETED YET]
					
					// Set regular response code
					if
					(
						self::$CHIKKA_LAST_IS_VOLUME_LIMIT == false &&
						self::$CHIKKA_LAST_IS_SPAM == false
					)
					{	
						self::$CHIKKA_LAST_SERVICE_CODE = $SERVICE_CODE;
						self::$CHIKKA_LAST_REQUEST_COST = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
						(
							$DATA_SET,
							'SCODE_CHARGE'
						);
						
						$RESPONSE_MESSAGE = PHPRC_PDO_MYSQL_ARRAY::REF_FETCH
						(
							$DATA_SET,
							'SCODE_RESPONSE'
						);
					}
				}
			}
			
			// Handle invalid service code
			// ........................................
			if(PHPVC_STR::VAR_IS_BLANK($RESPONSE_MESSAGE))
			{
				$RESPONSE_MESSAGE = self::REF_SERVICE_CODE_ON_ERROR($SHORTCODE, $COMPANY_CODE);
			}
			
			// Resize Response Message to < 420 char
			// ........................................
			if(Strlen($RESPONSE_MESSAGE) > 420)
			{
				$RESPONSE_MESSAGE = PHPVC_STR::VAR_LEFT($RESPONSE_MESSAGE, 420);
			}
				
			
			// Return result
			// ........................................
			return $RESPONSE_MESSAGE;
		}
		catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			return "Server is busy. Please try again later.";
		}
	}
}

?>