<?php

class Atmail_Provider_SMS_SMSGlobal extends Atmail_Provider_SMS_Abstract
{


	/* 
		For purposes of proof of concept we need a 3rd party service we can query for voice mails. 
		Twilio is suitable, except that they dont house the VM info for us, they want to call a partner script to 
		log the messages (they only host the VM file) so we will need to impliment a mini provider server to 
		answer queries for current VM, get, delete etc.
		
		N.B. with RAD parts of the client server seperation concept have become merger due to implimenting a virtual service (MySQL so made sense to talk to "server" via SQL layer for speed of development).
		Obviously in final implimentation of a real service, what has been learned in this process must be applied into a cleanly seperated client server model
		where Server will do all the communication to the external service, and client is the local cached/archived data acquired from such server layer 
		e.g. SWL table must be split or modded to server client purposes only (cached/archived VM content, transcriptions, readFlag etc.)

	*/
	public $fieldMap = array('from' => 'SMSFrom', 'to' => 'SMSTo', 'received' => 'MessageDate', 'message' => 'Message' ); //maps public field names to internal field names
	public function __construct( Array $configArray )
	{
		
		Zend_Registry::get('log')->debug( "\n" . print_r($configArray, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$configArray \n");
		
		$this->dbAdapter = Zend_Registry::get('dbAdapter');
		$this->PhoneNumber = $configArray['PhoneNumber'];
		$this->Account = $this->_config['Account'];
		//$this->userData = Zend_Auth::getInstance()->getStorage()->read();
		//$this->Account = $this->userData['Account'];
		if( !parent::__construct($configArray) )
			return false;

	}
	
	public function create( Array $args = array() )
	{
		
		Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		//get first SMS enabled account if username and password not specified
		//Zend_Registry::get('log')->debug( "\n" . print_r($this->myAccounts, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$this->myAccounts \n");
		if( empty($args['message']) && !empty($args['Message']) )
			$args['message'] = $args['Message'];
		if( empty($args['to']) && !empty($args['SMSTo']) )
			$args['to'] = $args['SMSTo'];
		if( empty($args['from']) && !empty($args['SMSFrom']) )
			$args['from'] = $args['SMSFrom'];
		if( empty($args['from']))
			$args['from'] = $this->PhoneNumber;
		$url = 'http://www.smsglobal.com/http-api.php?action=sendsms&user=' . rawurlencode($this->_config['AuthorizationName']) . '&password=' . rawurlencode($this->_config['Password']) . '&from=' . rawurlencode($args['from']) . '&to=' . rawurlencode($args['to']) . '&text=' . rawurlencode($args['message']);
		Zend_Registry::get('log')->debug( "\n" . print_r($url, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$url \n");
		$result = file_get_contents($url);
		Zend_Registry::get('log')->debug( "\n" . print_r($result, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$result \n");
		
		if( strpos($result, 'OK') !== false)
			return $this->store( array('from' => $args['from'], 'to' => $args['to'], 'message' => $args['message'], 'Account' => $this->Account ) );
		else
			return array('response' => array('message' => "Failed sending SMS"), 'status' => 'failed' );
			

		// After sending an SMS, need to add to the index ( So Sent visible )
		//TODO: also store service used to send the message.
		return true;
		
	}
	
	public function getList( Array $args = array() )
	{
        
		//Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		if( !empty($args['searchFuzzy']) )	
		{

			foreach( array('SMSFrom', 'SMSTo', 'Message') as $v )
				$searchTerms[] = "$v LIKE " . $this->dbAdapter->quote('%' . $args['query'] . '%');

			$searchTerms = implode(" OR ", $searchTerms);

			//carriers will only know to msisdn and wont know account ( msisdn can logically be the secure where clause) (also allows e.g. sales teal having access to all business sms shared boxes)//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where Account=? and SMSFrom=SMSFromCnt) as SMSCount from SMS where Account=? and SMSTo=? and ($searchTerms) Group by SMSFrom order by id desc", array( $args['Account'], $args['Account'], $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt) as SMSCount from SMS where SMSTo=? and ($searchTerms) Group by SMSFrom order by id desc", array( $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt AND SMSTo=?) as SMSCount from SMS where SMSTo=? and ($searchTerms) Group by SMSFrom order by id desc", array( $this->PhoneNumber,  $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("SELECT  `SMSFrom`, `SMSTo`, `Message`, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix, MessageDate FROM SMS WHERE id IN (SELECT MAX(id) FROM SMS WHERE SMSTo=? AND ($searchTerms) GROUP BY SMSFrom) ORDER BY MessageDate DESC", array($this->PhoneNumber) );

			$rows = $this->dbAdapter->fetchAll("SELECT *, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix FROM SMS WHERE id IN ( 
				SELECT MAX(id) AS id FROM SMS WHERE SMSTo=? AND ($searchTerms) GROUP BY SMSFrom 
				UNION 
				SELECT MAX(id) AS id FROM (SELECT id, SMSTo FROM SMS as S1 WHERE SMSFrom=? AND ($searchTerms) AND 0 = (SELECT COUNT(*) FROM SMS WHERE SMSFrom = S1.SMSTo AND SMSTo=?)) S2 GROUP BY SMSTo
				)
				ORDER BY MessageDate DESC", array($this->PhoneNumber,$this->PhoneNumber,$this->PhoneNumber) );

		}
		else
		{

			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt) as SMSCount from SMS where SMSTo=? Group by SMSFrom order by id desc", array( $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt AND SMSTo=?) as SMSCount from SMS where SMSTo=? Group by SMSFrom order by id desc", array( $this->PhoneNumber,  $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("SELECT  `SMSFrom`, `SMSTo`, `Message`, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix, MessageDate FROM SMS WHERE id IN (SELECT MAX(id) FROM SMS WHERE SMSTo=? GROUP BY SMSFrom) ORDER BY MessageDate DESC", array($this->PhoneNumber) );
			$rows = $this->dbAdapter->fetchAll("SELECT *, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix FROM SMS WHERE id IN (
				SELECT MAX(id) AS id FROM SMS WHERE SMSTo=? GROUP BY SMSFrom
				UNION
				SELECT MAX(id) AS id FROM (SELECT id, SMSTo FROM SMS as S1 WHERE SMSFrom=? AND 0 = (SELECT COUNT(*) FROM SMS WHERE SMSFrom = S1.SMSTo AND SMSTo=?)) S2 GROUP BY SMSTo
				)
				ORDER BY MessageDate DESC", array($this->PhoneNumber,$this->PhoneNumber,$this->PhoneNumber) );

		}
		
		foreach( $rows as &$row )
		{
			
			$row['MessageDate'] = date('r',$row['MessageDateUnix']);
			foreach( $this->fieldMap as $public => $internal )
			{
				if( $public != $internal )
				{
					$row[$public] = $row[$internal];
					unset($row[$internal]);
				}
			}
			unset($row['Account']);
			unset($row['MessageDateUnix']);
		}
		return array("status" => "success", "totalNumberOfItems" => count($rows), "page" => 1, "itemsPerPage" => count($rows), "data" => $rows);
		
	}

	public function getSummary( Array $args = array() )
	{
        
		//Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		if( !empty($args['searchFuzzy']) )	
		{

			foreach( array('SMSFrom', 'SMSTo', 'Message') as $v )
				$searchTerms[] = "$v LIKE " . $this->dbAdapter->quote('%' . $args['query'] . '%');

			$searchTerms = implode(" OR ", $searchTerms);

			//carriers will only know to msisdn and wont know account ( msisdn can logically be the secure where clause) (also allows e.g. sales teal having access to all business sms shared boxes)//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where Account=? and SMSFrom=SMSFromCnt) as SMSCount from SMS where Account=? and SMSTo=? and ($searchTerms) Group by SMSFrom order by id desc", array( $args['Account'], $args['Account'], $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt) as SMSCount from SMS where SMSTo=? and ($searchTerms) Group by SMSFrom order by id desc", array( $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt AND SMSTo=?) as SMSCount from SMS where SMSTo=? and ($searchTerms) Group by SMSFrom order by id desc", array( $this->PhoneNumber,  $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("SELECT  `SMSFrom`, `SMSTo`, `Message`, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix, MessageDate FROM SMS WHERE id IN (SELECT MAX(id) FROM SMS WHERE SMSTo=? AND ($searchTerms) GROUP BY SMSFrom) ORDER BY MessageDate DESC", array($this->PhoneNumber) );

			$rows = $this->dbAdapter->fetchAll("SELECT *, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix FROM SMS WHERE id IN ( 
				SELECT MAX(id) AS id FROM SMS WHERE SMSTo=? AND ($searchTerms) GROUP BY SMSFrom 
				UNION 
				SELECT MAX(id) AS id FROM (SELECT id, SMSTo FROM SMS as S1 WHERE SMSFrom=? AND ($searchTerms) AND 0 = (SELECT COUNT(*) FROM SMS WHERE SMSFrom = S1.SMSTo AND SMSTo=?)) S2 GROUP BY SMSTo
				)
				ORDER BY MessageDate DESC", array($this->PhoneNumber,$this->PhoneNumber,$this->PhoneNumber) );

		}
		else
		{

			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt) as SMSCount from SMS where SMSTo=? Group by SMSFrom order by id desc", array( $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("select SMS.SMSFrom as SMSFromCnt, SMS.*, (select count(id) from SMS where SMSFrom=SMSFromCnt AND SMSTo=?) as SMSCount from SMS where SMSTo=? Group by SMSFrom order by id desc", array( $this->PhoneNumber,  $this->PhoneNumber ));
			//$arr = $this->dbAdapter->fetchAll("SELECT  `SMSFrom`, `SMSTo`, `Message`, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix, MessageDate FROM SMS WHERE id IN (SELECT MAX(id) FROM SMS WHERE SMSTo=? GROUP BY SMSFrom) ORDER BY MessageDate DESC", array($this->PhoneNumber) );
			$rows = $this->dbAdapter->fetchAll("SELECT *, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix FROM SMS WHERE id IN (
				SELECT MAX(id) AS id FROM SMS WHERE SMSTo=? GROUP BY SMSFrom
				UNION
				SELECT MAX(id) AS id FROM (SELECT id, SMSTo FROM SMS as S1 WHERE SMSFrom=? AND 0 = (SELECT COUNT(*) FROM SMS WHERE SMSFrom = S1.SMSTo AND SMSTo=?)) S2 GROUP BY SMSTo
				)
				ORDER BY MessageDate DESC", array($this->PhoneNumber,$this->PhoneNumber,$this->PhoneNumber) );

		}
		foreach( $rows as &$row )
		{
			
			$row['MessageDate'] = date('r',$row['MessageDateUnix']);
			foreach( $this->fieldMap as $public => $internal )
			{
				if( $public != $internal )
				{
					$row[$public] = $row[$internal];
					unset($row[$internal]);
				}
			}
			unset($row['Account']);
			unset($row['MessageDateUnix']);
		}
		return array("status" => "success", "totalNumberOfItems" => count($rows), "page" => 1, "itemsPerPage" => count($rows), "data" => $rows);
		
	}

	public function getThread( Array $args = array() )
	{
        
		Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		
		if( !array_key_exists('phoneNumber', $args) )
			throw new Exception("Error: need phoneNumber in order to get thread of messages sent to or from that number");
		$rows = $this->dbAdapter->fetchAll("select *, UNIX_TIMESTAMP(MessageDate) AS MessageDateUnix from SMS where ( SMSFrom=? and SMSTo=? ) or ( SMSTo=? and SMSFrom=? ) group by id order by id", array( $this->PhoneNumber, $args['phoneNumber'], $this->PhoneNumber, $args['phoneNumber'] ));
	    foreach( $rows as &$row )
		{
			
			$row['MessageDate'] = date('r',$row['MessageDateUnix']);
			foreach( $this->fieldMap as $public => $internal )
			{
				if( $public != $internal )
				{
					$row[$public] = $row[$internal];
					unset($row[$internal]);
				}
			}
			unset($row['Account']);
			unset($row['MessageDateUnix']);
		}
		return array("status" => "success", "totalNumberOfItems" => count($rows), "page" => 1, "itemsPerPage" => count($rows), "data" => $rows);
		
	}

	public function getInfo( Array $args = array() )
	{
		return null;
	}
	
	public function delete( Array $args )
	{
		
		//CONSIDER: changing how this works to to store a copy of incoming to each accountNumber owner so that each owner can delete their own copy of a specific incoming message without others going missing
		if( array_key_exists('id', $args) )
			$itemsAffected = $this->dbAdapter->query("DELETE FROM SMS WHERE ( SMSFrom=? AND id=? ) OR ( SMSTo=? AND id=? )", array( $this->PhoneNumber, $args['id'], $this->PhoneNumber, $args['id'] ))->rowCount();
		else
			$itemsAffected = $this->dbAdapter->query("DELETE FROM SMS WHERE ( SMSFrom=? AND SMSTo=? ) OR ( SMSTo=? AND SMSFrom=? )", array( $this->PhoneNumber, $args['from'], $this->PhoneNumber, $args['from'] ))->rowCount();
		//$itemsAffected = $this->dbAdapter->query($q)->rowCount();
		
		if( $itemsAffected > 1 )
			return array('response' => array('message' => "SMS conversation deleted"), 'status' => 'success', "numberOfMessagesDeleted" => $itemsAffected);	
		else
			return array('response' => array('message' => "SMS(s) deleted"), 'status' => 'success', "numberOfMessagesDeleted" => $itemsAffected);	
		

	}
	
	private function store( $args = array() )
	{

		Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		if( empty($args['message']) && !empty($args['Message']) )
			$args['message'] = $args['Message'];
		if( empty($args['to']) && !empty($args['SMSTo']) )
			$args['to'] = $args['SMSTo'];
		if( empty($args['from']) && !empty($args['SMSFrom']) )
			$args['from'] = $args['SMSFrom'];
		Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		
		$numberOfAffectedRows = $this->dbAdapter->insert("SMS", array(
				'Account' => $args['Account'], 
				'SMSTo' => $args['to'],
				'SMSFrom' => $args['from'],
				'Message' => $args['message'],
				'MessageDate' => new Zend_Db_Expr('NOW()')
			)
		);
			
		if( $numberOfAffectedRows == 1 )
			return array('response' => array('message' => "SMS added"), 'status' =>'success');
		else
			return array('response' => array('message' => "Failed adding SMS"), 'status' => 'failed' );

	}
	
	private function mapToInternal( $publicField )
	{
		
		if( array_key_exists($publicField, $this->fieldMap) )
			return $this->fieldMap[$publicField];
		else
			return $publicField;
		
	}

	private function mapToPublic( $internalField )
	{
		
		$result = array_search($internalField, $this->fieldMap);
		if( $result )
			return $result;
		else
			return $internalField;
		
	}

	
}
