<?php

/**
 * Extends the BaseTwitter class with the intent of using
 * PHP sessions to store user ids and access tokens.
 */
class Atmail_Provider_SocialNetwork_Twitter extends Atmail_Provider_SocialNetwork_Abstract
{


	public $fieldMap = array( 
		"statuses_home_timeline" => "statuses/home_timeline", 
		"statuses_mentions" => "statuses/mentions", 
		"statuses_user_timeline" => "statuses/user_timeline"
	); //maps public field names to internal field names
	private $_myData = null;
	private $_myContactsIds = null;
	private $_myContactsDetails = null;
	private $_myContactsSummary = null;
	
	public function __construct( Array $configArray ) 
	{
		$this->_session = new Zend_Session_Namespace('defaultNamespace');
		$this->dbAdapter = Zend_Registry::get('dbAdapter');
		$this->username = $configArray['UserId'];
		$this->displayName = $configArray['DisplayName'];
		$this->Account = $this->_config['Account'];
		$consumer_key = Zend_Registry::get('config')->Twitter['consumer_key'];
		$consumer_secret = Zend_Registry::get('config')->Twitter['consumer_secret'];
		$userAccessTokenSerialized = $configArray['Password'];
		$userTokenParts = explode("|", $userAccessTokenSerialized);
//Zend_Registry::get('log')->debug( "\n" . print_r($userTokenParts, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$userTokenParts \n");
		require_once('Twitter/twitteroauth/twitteroauth.php');
		//require_once('config.php');
		
		//$accessToken = new Zend_Oauth_Token_Access();
		//$accessToken->setTokenSecret($userTokenParts[1]);
		//$accessToken->setToken($userTokenParts[0]);
		//$this->twitterInterface = new Zend_Service_Twitter( array('username' => $this->username, 'accessToken' => $accessToken) );
		

		/* Create a TwitterOauth object with consumer/user tokens. */
		$this->twitterInterface = new TwitterOAuth($this->consumer_key, $this->consumer_secret, $userTokenParts[0], $userTokenParts[1]);
		
		//??????????
		//$access_token = $this->twitterInterface->getAccessToken('1234');
		//Zend_Registry::get('log')->debug( "\n" . print_r($access_token, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$access_token \n");
		
		//$content = $this->twitterInterface->get('account/rate_limit_status');
        //Zend_Registry::get('log')->debug( "\n" . print_r($content, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$content \n");
        
		
		
		if( !parent::__construct($configArray) )
			return false;
		
	}
	
	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;
		
	}
	
	private function getLegalArgsForResource($resource, $args)
	{

//Zend_Registry::get('log')->debug( "\n" . print_r($resource, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$resource \n");
//Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		
		//maps atmail field names to Twitter field names and only returns legal fields 
		$hashAllowedAtmailToTwitter = array(
			'limit' => 'count',
			'since_id' => 'since_id', 
			'max_id' => 'max_id',
			'page' => 'page',
			'trim' => 'trim_user',
			'include_rts' => 'include_rts',
			'include_entities' => 'include_entities',
			'contributor_details' => 'contributor_details'
		);
		
		//some fields must be bool
		if( array_key_exists('trim', $args) )
			$args['trim'] = ($args['trim']?'1':'0');
			
		switch($resource)
		{

			case 'statuses_user_timeline':
				$hashAllowedAtmailToTwitter['id'] = 'screen_name';
			break;
			case 'statuses_mentions':
				//https://dev.twitter.com/docs/api/1/get/statuses/mentions
			break;
			case 'statuses_home_timeline':
				//https://dev.twitter.com/docs/api/1/get/statuses/home_timeline
				$hashAllowedAtmailToTwitter['exclude_replies'] = 'exclude_replies';
			break;

		}
//Zend_Registry::get('log')->debug( "\n" . print_r($hashAllowedAtmailToTwitter, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$hashAllowedAtmailToTwitter \n");
		
		
		$resultArgs = array();
		foreach( $args as $k => $v )
		{
			
			if( array_key_exists($k, $hashAllowedAtmailToTwitter) )
				$resultArgs[$hashAllowedAtmailToTwitter[$k]] = trim($v);
			
		}
//Zend_Registry::get('log')->debug( "\n" . print_r($resultArgs, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$resultArgs \n");
		
		return $resultArgs;
		
	}
	
	
	public function get( Array $args = array() )
	{
		
		if( !array_key_exists('folder',$args) )
			$args['folder'] = 'statuses_home_timeline';
//Zend_Registry::get('log')->debug( "\n" . print_r($args['folder'], true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args['folder'] \n");
		
		$twitterArgs = $this->getLegalArgsForResource($args['folder'], $args);
//Zend_Registry::get('log')->debug( "\n" . print_r($twitterArgs, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$twitterArgs \n");
		
		return $this->twitterInterface->get($args['folder'], $twitterArgs);
		
	}
	
	public function getList( Array $args = array() )
	{
        
		//Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		if( !array_key_exists('folder',$args) )
			$args['folder'] = "statuses_home_timeline";
		
		$twitterArgs = $this->getLegalArgsForResource($args['folder'], $args);
		$folder = $this->mapToInternal($args['folder']);
//Zend_Registry::get('log')->debug( "\n" . print_r($folder, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$folder \n");
		
//Zend_Registry::get('log')->debug( "\n" . print_r($twitterArgs, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$twitterArgs \n");
		
		$return = $args;
		try {

			$content = $this->twitterInterface->get($folder, $twitterArgs);
//Zend_Registry::get('log')->debug( "\n" . print_r($content, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$content \n");
//Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ": \$content: " . count($content) );

			
			if( array_key_exists('error',$content) )
			{
				if( $content['error'] == "Timestamp out of bounds" )
					throw new Exception("Request rejected because Webserver time is incorrect. Webserver time must be updated.");
				else
					throw new Exception($content['error']);
			}
			//foreach( $content as &$row )
			//	$row['created_at_ISO8601'] = UnixGMTToISO8601TZ( strtotime($row['created_at']) );
			
			$return['serviceData'] = $content;
			$return['success'] = "true"; //Did the action complete without failure (server fails, network down etc.)
			$return['result'] = "true"; //Did the executing the action result in a success or fail for the commend (e.g. delete, or add)
			$return['noteEnglish'] = "Fetched remote data successfully"; //used for english display and translation
			$return['noteCode'] = "200"; //used for programatic success and result handling
			$return['lastUpdated'] = time();
			$return['serviceType'] = "SocialNetwork";
			$return['serviceName'] = "Twitter";
			$return['myId'] = $this->username;
			$return['myDisplayName'] = $this->displayName;
			$return['folder'] = $this->mapToPublic($args['folder']);
			
		} catch( Exception $e) {
			
			$return['success'] = "true"; //Did the action complete without failure (server fails, network down etc.)
			$return['result'] = "false"; //Did the executing the action result in a success or fail for the commend (e.g. delete, or add)
			$return['noteEnglish'] = "Failed fetching remote data: " . $e->getMessage(); //used for english display and translation
			$return['noteCode'] = "404"; //used for programatic success and result handling
			$return['lastUpdated'] = time();
			$return['serviceType'] = "SocialNetwork";
			$return['serviceName'] = "Twitter";
			$return['myId'] = $this->username;
			$return['myDisplayName'] = $this->displayName;
			$return['folder'] = $this->mapToPublic($args['folder']);
			
		}
//Zend_Registry::get('log')->debug( "\n" . print_r($return, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$return \n");
		return $return;
			
	}

	public function getSummary( Array $args = array() )
	{
		
		return $this->getList( $args );
		
	}
	
	public function getThread( Array $args = array() )
	{
        
		//Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		try {
			$id = (string)$args['mid'];
			$twitterRequestArgs = array('max_id' => $id, 'count' => '1');
			$content = $this->twitterInterface->get($args['folder'], $twitterRequestArgs);
			//Zend_Registry::get('log')->debug( "\n" . print_r($content[0], true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$content(" . count($content) . ") \n");
			return $content[0];

		} catch( Exception $e) {

			return array('Failed: Unable to reach Twitter servers.');

		}

	}
	
	public function getStream( Array $args = array() )
	{

		if( !empty($args['id']) )
			$args['folder'] = "statuses_user_timeline";
//Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		
		$rows = $this->getList($args);
//Zend_Registry::get('log')->debug( "\n" . print_r($rows, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$rows \n");
		
		$stream = array();
		//if failes for whatever reason return empty
		if( $rows['result'] == 'false' || !isset($rows['serviceData']) )
		{
		
			return $stream;
			
		}
			
		foreach( $rows['serviceData'] as $row )
		{
			
			$ts = UnixGMTToISO8601TZ( strtotime($row['created_at']) );
			$stream[] = array(
				'pid' => $args['pid'], 
				'providerType' => 'SocialNetwork', 
				'providerName' => 'Twitter', 
				'providerDescription' => 'Main Twitter Account', 
				'id' => $row['id_str'], 
				'receivedDateISO8601' => $ts,
				'timeAgo' => timeago(strtotime($ts)),
				'seen' => 'false', 
				'from' => array(
					'id' => $row['user']['screen_name'],
					'name' => $row['user']['name']
				),
				'subject' => null,
				'messageType' => $row['source'], 
				'summary' => $row['text'],
				'avatar' => $_SERVER['HTTPS']?$row['user']['profile_image_url_https']:$row['user']['profile_image_url']
			);
			
		}
		return $stream;
		
	}


	public function getInfo( Array $args = array() )
	{
		
		throw new Exception('Error: not yet implemented');
		if( !array_key_exists('messageId', $args) )
			throw new Exception('Error: messageId must be specified');
		return $rows[0];
		
	}
	
	
	public function deleteThread( Array $args )
	{
		
		if( !array_key_exists('messageId', $args) )
			throw new Exception('Error: from field must be specified to delete thread');
		//Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ': $q=' . $q);
		//return $this->dbAdapter->query($q);

	}
	public function delete( Array $args )
	{
		
		if( !array_key_exists('messageId', $args) )
			throw new Exception('Error: messageId must be specified');
			
		//Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ': $q=' . $q);
		//return $this->dbAdapter->query($q);

	}
	
	public function post( Array $args )
	{
		
Zend_Registry::get('log')->debug( "\n" . print_r($args, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$args \n");
		unset($args['pid']); //unneeded arg related to Providers framework
		try {
            if( !array_key_exists('url',$args) || $args['url'] == '')
				$args['url'] = "statuses/update";
			$result = $this->twitterInterface->post($args['url'],array('status' => $args['message']) );
Zend_Registry::get('log')->debug( "\n" . print_r($result, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$content \n");
			return $result;

		} catch( Exception $e) {
			
			Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ": Error: " . $e->getMessage());
            return array('Failed: Unable to reach Twitter servers.' . $e->getMessage());

		}
		
	}
	
	public function getMyData()
	{
		if( $this->_myData != null )
			return $this->_myData;
		try {
			
			//$response = $this->twitterInterfacetwitter->account->verifyCredentials();
			
			$this->_myData = $this->twitterInterface->get('account/verify_credentials');
			//Zend_Registry::get('log')->debug( "\n" . print_r($this->_myData, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$this->_myData \n");
			
			return $this->_myData;

		} catch( Exception $e) {
            
			Zend_Registry::get('log')->debug( __METHOD__ . ' #' . __LINE__ . ": Error: " . $e->getMessage());
			return array('Failed: Unable to reach Twitter servers.');

		}
		
	}
	
	public function getMyName()
	{
		
		$this->getMyData();
		return $this->_myData['name'];
		
	}

	public function getMyId()
	{
		
		$this->getMyData();
		return $this->_myData['id'];
	
	}
	
	public function getMyProfileImageUrl()
	{
		
		$this->getMyData();
		return $this->_myData['profile_image_url'];
		
	}
	
	public function &getContactsIds( Array $args = array() )
	{
		
		if( $this->_myContactsIds !== null )
			return $this->_myContactsIds;
		//TODO: handling if previous_cursor_str and previous_cursor_str are not 0 (more pages to get)
		$result = $this->twitterInterface->get('friends/ids', array('cursor' => "-1") ); //up to 5000 TODO: handling of more than 5000
		$this->_myContactsIds = $result['ids'];
Zend_Registry::get('log')->debug( "\n" . print_r($this->_myContactsIds, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$this->_myContactsIds \n");
		
		return $this->_myContactsIds;
		
	}
	
	public function &getContactsDetails( Array $args = array() )
	{
		
		if( $this->_myContactsDetails !== null )
			return $this->_myContactsDetails;
			
		$this->_myContactsDetails = array();
		try {
			
			$this->getContactsIds();
			$chunks = array_chunk($this->_myContactsIds, 100);

			foreach( $chunks as $chunk )
			{
				$idString = "";
				foreach( $chunk as $id)
				{
					$idString .= $id . ",";
					
				}
				$idString = trim($idString, ",");
				Zend_Registry::get('log')->debug( "\n" . print_r($idString, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$idString \n Length: " . strlen($idString));
				
				$contactsDetails = $this->twitterInterface->get('users/lookup', array('user_id' => $idString) );
				$this->_myContactsDetails = array_merge($this->_myContactsDetails,$contactsDetails);
				Zend_Registry::get('log')->debug( "\n" . print_r($this->_myContactsDetails, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$this->_myContactsDetails \n");
				
			}
			
			return $this->_myContactsDetails;

		} catch( Exception $e) {

			return array('Error: ' . __METHOD__ . ' #' . __LINE__ . ": " . $e->getMessage() );

		}
	}
	
	public function &getContactsSummary( Array $args = array() )
	{
		
		if( $this->_myContactsSummary !== null )
			return $this->_myContactsSummary;
		
		$this->_myContactsSummary = array();
		$this->getContactsDetails();
		foreach( $this->_myContactsDetails as &$contact )
		{
			
			$firstSpacePos = mb_strpos($contact['name'], " ");
			if( $firstSpacePos === false )
			{
			
				$UserFirstName = $contact['name'];
				$UserLastName = "";
			
			}
			else
			{
				
				$UserFirstName = mb_substr($contact['name'],0,$firstSpacePos);
				$UserLastName = mb_substr($contact['name'],$firstSpacePos+1);
				
			}
			$details = array(
				
				'TwitterId' => $contact['screen_name'], 
				'UserFirstName' => $UserFirstName, 
				'UserLastName' => $UserLastName, 
				'Location' => $contact['location'], 
				'Timezone' => $contact['time_zone']

			);
			$this->_myContactsSummary[$contact['screen_name']] = $details;
			
		}
		
		return $this->_myContactsSummary;
		
	}
	
	public static function getProfileImageUrl( Array $args )
	{
		
		if( empty($args['id']) )
			throw new Exception(__METHOD__ . ' #' . __LINE__ . " must specify id");
			
		return "http://api.twitter.com/1/users/profile_image?screen_name=" . $args['id'] . "&size=original";
	
	}
	
	public function getProfileImage( Array $args )
	{
		
		if( empty($args['id']) )
			throw new Exception(__METHOD__ . ' #' . __LINE__ . " must specify id");
			
		try 
		{
			
			return @file_get_contents( self::getProfileImageUrl($args) );
			
		} 
		catch( Exception $e) 
		{

			return 'Failed: Unable to reach Twitter servers.' . $e->getMessage();

		}
		
		
	}
	
	public function getFriendsStatus(  Array $args  )
	{
		
		
		$requiredParams = array('id');
		foreach( $requiredParams as $requiredParam )
			if( !array_key_exists($requiredParam, $args ) )
				throw new Exception( __CLASS__ . "::" . __METHOD__ . "#" . __LINE__ . ' Called without required param: ' . $requiredParam);
		//set the subset of ids that must be queried
		if( !is_array($args['id']) )
			$this->_myContactsIds = array($args['id']);
		else
			$this->_myContactsIds = $args['id'];
//Zend_Registry::get('log')->debug( "\n" . print_r($this->_myContactsIds, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$this->_myContactsIds \n");
		
		$results = $this->getContactsDetails();
//Zend_Registry::get('log')->debug( "\n" . print_r($results, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$results \n");
		
		$statuses = array();
		foreach( $results as $row )
		{
//Zend_Registry::get('log')->debug( "\n" . print_r($row, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$row \n");
			
			$statuses[] = array( 
				'id' => $row['screen_name'], 
				'oid' => $row['id_str'], 
				'LastMessageType' => 'Twitter', 
				'LastMessage' => $row['status']['text'], 
				'LastMessageDatetime' => Unix_to_MySQL_DATETIME_Locale(strtotime($row['status']['created_at'])), 
				'timestampISO8601' => date('c', strtotime($row['status']['created_at'])), 
				'timestampRaw' => $row['status']['created_at']
			);
			
		}
		
		
Zend_Registry::get('log')->debug( "\n" . print_r($statuses, true) . "\n" . __METHOD__ . ' #' . __LINE__ . ": \$statuses \n");
		if( is_array($args['id']) )
			return $statuses;
		else
			return $statuses[0];

		
	}
	
}