<?php

/**
 * Feed Class
 * Also takes care of spot (device) & messages
 * 
 * To add a new feed, create a new records in the feed table:
 * INSERT INTO feeds (ref_feed_id, id_spot, id_project) VALUES ('<feed_id>', '<related_spot_id>', '<related_project_id>');
 */
class Feed extends PhpObject {
	
	//Spot feed
	const FEED_HOOK = 'https://api.findmespot.com/spot-main-web/consumer/rest-api/2.0/public/feed/';
	const FEED_TYPE_XML = '/message.xml';
	const FEED_TYPE_JSON = '/message.json';
	
	//DB Tables
	const SPOT_TABLE = 'spots';
	const FEED_TABLE = 'feeds';
	const MSG_TABLE = 'messages';
	
	/**
	 * Database Handle
	 * @var Db
	 */
	private $oDb;
	
	private $iFeedId;
	private $sRefFeedId;
	private $iLastUpdate;
	
	public function __construct(Db &$oDb, $iFeedId) {
		parent::__construct(__CLASS__, Settings::DEBUG);
		$this->oDb = &$oDb;
		$this->setFeedId($iFeedId);
	}
	
	public function setFeedId($iFeedId) {
		$this->iFeedId = $iFeedId;
		$asFeed = $this->oDb->selectRow(self::FEED_TABLE, $this->iFeedId);
		$this->sRefFeedId = $asFeed['ref_feed_id'];
		$this->iLastUpdate = strtotime($asFeed['last_update']);
	}
	
	public function getMessages($asActivePeriod = array()) {
		$asInfo = array(
			'select'	=> array('id_message', 'ref_msg_id', 'type', 'latitude', 'longitude', 'site_time', 'unix_time'),
			'from'		=> self::MSG_TABLE,
			'constraint'=> array(Db::getId(self::FEED_TABLE) => $this->iFeedId),
			'constOpe'	=> array(Db::getId(self::FEED_TABLE) => "="),
			'orderBy'	=> array('site_time'=>'ASC')
		);
		
		if(!empty($asActivePeriod)) {
			$asInfo['constraint']['site_time'] = $asActivePeriod;
			$asInfo['constOpe']['site_time'] = "BETWEEN";
		}

		return $this->oDb->selectRows($asInfo);
	}
	
	public function checkUpdateFeed($sProjectMode) {
		//Feed updated once a day in Blog Mode
		if($sProjectMode == Project::MODE_BLOG && date('Y-m-d-H', $this->iLastUpdate) != date('Y-m-d-H')) $this->updateFeed();
	}
	
	private function updateFeed() {
		$asData = $this->retrieveFeed();
		$sLastUpdate = date(Db::TIMESTAMP_FORMAT);
		if(!isset($asData['response']['errors']) || empty($asData['response']['errors'])) {
			$asMsgs = $asData['response']['feedMessageResponse']['messages'];
			if(array_key_exists('message', $asMsgs)) $asMsgs = $asMsgs['message'];
			
			$asFeed = $asData['response']['feedMessageResponse']['feed'];
			
			if(!empty($asMsgs))
			{
				//Update Spot Info from the first message
				$asFirstMsg = array_values($asMsgs)[0];
				$asSpotInfo = array(
					'ref_spot_id'	=> $asFirstMsg['messengerId'],
					'name'			=> $asFirstMsg['messengerName'],
					'model'			=> $asFirstMsg['modelId']
				);
				$iSpotId = $this->oDb->insertUpdateRow(self::SPOT_TABLE, $asSpotInfo, array('ref_spot_id'));
				
				//Update Feed Info and last update date
				$asFeedInfo = array(
					'ref_feed_id'					=> $asFeed['id'],
					Db::getId(self::SPOT_TABLE)		=> $iSpotId,
					'name'							=> $asFeed['name'],
					'description'					=> $asFeed['description'],
					'status'						=> $asFeed['status'],
					'last_update'					=> $sLastUpdate
				);
				$iFeedId = $this->oDb->insertUpdateRow(self::FEED_TABLE, $asFeedInfo, array('ref_feed_id'));
				
				//Update Messages
				foreach($asMsgs as $asMsg)
				{
					$asMsg = array(
						'ref_msg_id'				=> $asMsg['id'],
						Db::getId(self::FEED_TABLE)	=> $iFeedId,
						'type'						=> $asMsg['messageType'],
						'latitude'					=> $asMsg['latitude'],
						'longitude'					=> $asMsg['longitude'],
						'iso_time'					=> $asMsg['dateTime'],								//ISO 8601 time (backup)
						'site_time'					=> date(Db::TIMESTAMP_FORMAT, $asMsg['unixTime']),	//Conversion to Site Time (see Settings::TIMEZONE)
						'unix_time'					=> $asMsg['unixTime'], 								//UNIX Time (backup)
						'content'					=> $asMsg['messageContent'],
						'battery_state'				=> $asMsg['batteryState']
					);
					$this->oDb->insertUpdateRow(self::MSG_TABLE, $asMsg, array('ref_msg_id'));
				}
			}
		}
		else $this->oDb->updateRow(self::FEED_TABLE, $this->iFeedId, array('last_update'=>$sLastUpdate));
	}
	
	private function retrieveFeed() {
		$sUrl = self::FEED_HOOK.$this->sRefFeedId.self::FEED_TYPE_JSON;
		$sContent = file_get_contents($sUrl);
		return json_decode($sContent, true);
	}
}	
