<?php
require_once(__DIR__.'/../includes/sysinit.php');
class FirebaseMessaging
{
	const FCM_BASE_URL = 'https://fcm.googleapis.com/fcm/';
	var $sdb, $token, $message, $title, $url;
	private $group, $groupName, $recipientTokens, $groupNotificationKey;
	
	function __construct()
	{
		$this->sdb = new SableDB;
	}
	
	function __destruct(){}
	
	public function actionTokenDB($data)
	{
		$this->token = $data['fcm_key_id'];
		if ($data['action']) $this->addUserKey(); else $this->deleteUserKey();
	}
	
	private function getRecipientTokens()
	{
		$this->getGroupName();
		$sql = 'select fcm_key_id 
				from fcm_notification 
				where (fcm_group_name = "'.$this->groupName.'")';
		$rows = $this->sdb->getRows($sql);
		$this->recipientTokens = [];
		foreach($rows as $row) $this->recipientTokens[] = $row['fcm_key_id'];
	}
	
	private function addUserKey()
	{
		$this->group = 1;
		
		/**
		we will cater for the following groups:
		1 = champ-public	--> This is for someone using the app on the web that is not logged in.
		2 = champ-admin	--> Champ administrators
		3 = champ-client	--> Champ client (logged in as a client)
		4 = more to be added if necessary
		**/
		if (isset($_SESSION['user']['access_level']))
		{
			if ($_SESSION['user']['access_level'] >= SABLE_ACCESS_SUPER)
			{
				$this->group = 2;
			}
			else
			{
				$coyid = isset($_SESSION['user']['company_id']) ? $_SESSION['user']['company_id']  : 0;
				$_SESSION['user']['member_type'] = $coyid ? 1 : 2;	
				if ($_SESSION['user']['member_type'] === 1) 
				{
					$this->group = 3;
				}
				else 
				{
					$this->group = 1;
				}
			}
		}
		
		$this->getGroupName();
		$uc = isset($_SESSION['user']['user_code']) ? $_SESSION['user']['user_code'] : 'NULL';
		$sql = 'insert into fcm_notification (fcm_key_id, fcm_group_name, fcm_ip, user_code, fcm_session_id) values 
				("'.$this->token.'", "'.$this->groupName.'", "'.SableGeneralFunctions::getRealIpAddr().'", 
				'.$uc.', "'.session_id().'") on duplicate key update  
				fcm_session_id = "'.session_id().'", 
				fcm_ip = "'.SableGeneralFunctions::getRealIpAddr().'"';
		if ($this->group !== 1) $sql .= ', fcm_group_name = "'.$this->groupName.'"';
		$res = $this->sdb->updateQuery($sql);
		if ($res) $this->addKeysToGroup($this->token);
		SableSystem::ajaxResponse(false, NULL, NULL, 6, NULL, NULL, NULL);
	}
	
	private function storeGroupNotificationKey()
	{
		$sql = 'insert into fcm_group (fcm_group_name, fcm_group_token) 
				values ("'.$this->groupName.'", "'.$this->groupNotificationKey.'") 
				on duplicate key update  
				fcm_group_token = "'.$this->groupNotificationKey.'"';
		$res = $this->sdb->updateQuery($sql);
	}
	
	private function getGroupNotificationKey()
	{
		/**
		https://fcm.googleapis.com/fcm/notification?notification_key_name=appUser-Chris
		Content-Type:application/json
		Authorization:key=API_KEY
		project_id:SENDER_ID
		{}
		**/
		$this->getGroupName();
		$header = ['Content-Type: application/json', 'Authorization: key='.FCM_SERVER_KEY, 'project_id:'.FCM_SENDER_ID];
		$response = $this->submitGetCall($header, 'notification?notification_key_name='.$this->groupName);
		if (isset($response['notification_key']))
		{
			$this->groupNotificationKey = $response['notification_key'];
			$this->storeGroupNotificationKey();
			return true;
		} else return false;
	}
	
	private function removeKeysFromGroup($token = null)
	{
		//if all recipients are removed from a group, then group will automatically be deleted also
		$this->getRecipientTokens();
		$data = [];
		$data["operation"]				= 'remove';
		$data["notification_key_name"]	= $this->groupName;
		$data["notification_key"]		= $this->groupNotificationKey;
		if ($token)
			$data["registration_ids"]		= array($token);
		else
			$data["registration_ids"]		= $this->recipientTokens;
		$header = ['Content-Type: application/json', 'Authorization: key='.FCM_SERVER_KEY, 'project_id:'.FCM_SENDER_ID];
		$response = $this->submitPostCall($header, $data, 'notification');
		
		if ($response['notification_key']) 
		{
			$this->groupNotificationKey = $response['notification_key'];
			$this->storeGroupNotificationKey();
			$sql = 'delete from fcm_notification where fcm_group_name = "'.$this->groupName.'"';
			$this->sdb->updateQuery($sql);
		}
	}
	
	private function deleteUserKey()
	{
		$sql = 'delete from fcm_notification where fcm_key_id = "'.$this->token.'"';
		$res = $this->sdb->updateQuery($sql);
		if ($res) $this->removeKeysFromGroup($this->token);
		SableSystem::ajaxResponse(false, NULL, NULL, 6, NULL, NULL, NULL);		
	}
	
	public function sendMessage($title, $message, $group, $url)
	{
		$this->message 	= $message;
		$this->title 	= $title;
		$this->group 	= $group;
		$this->url 		= $url;
		$this->notifyGroup();
	}
	
	private function getGroupName()
	{
		$result = 'champ-public'; //default
		switch($this->group)
		{
			case 1: $result = 'champ-public';		break;
			case 2: $result = 'champ-admin';		break;
			case 3: $result = 'champ-consumer';		break;
			case 4: $result = 'champ-manufacturer';	break;
		}
		$this->groupName = $result;
		//return $result;
	}
	
	private function addKeysToGroup($token = null)
	{
		//keys that already exist will be ignored.
		/**
		{
		   "operation": "add",
		   "notification_key_name": "appUser-Chris",
		   "notification_key": "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ",
		   "registration_ids": ["51"]
		}
		**/
		$this->getRecipientTokens();
		$data = [];
		$data["operation"]				= 'add';
		$data["notification_key_name"]	= $this->groupName;
		$data["notification_key"]		= $this->groupNotificationKey;
		if ($token)
			$data["registration_ids"]		= array($token);
		else
			$data["registration_ids"]		= $this->recipientTokens;
		$header = ['Content-Type: application/json', 'Authorization: key='.FCM_SERVER_KEY, 'project_id:'.FCM_SENDER_ID];
		$response = $this->submitPostCall($header, $data, 'notification');
		
		if ($response['notification_key']) 
		{
			$this->groupNotificationKey = $response['notification_key'];
			$this->storeGroupNotificationKey();
		}
	}
	
	private function createGroup()
	{
		/**
		https://fcm.googleapis.com/fcm/notification
		Content-Type:application/json
		Authorization:key=API_KEY
		project_id:SENDER_ID
		
		{
		   "operation": "create",
		   "notification_key_name": "appUser-Chris",
		   "registration_ids": ["4", "8", "15", "16", "23", "42"]
		}
		
		EXAMPLE:
		curl -X POST --header "Authorization: key=<API_ACCESS_KEY>" \
			--Header "Content-Type: application/json" \
			https://fcm.googleapis.com/fcm/send \
			-d "{\"to\":\"<YOUR_DEVICE_ID_TOKEN>\",\"notification\":{\"body\":\"Yellow\"},\"priority\":10}"			
		**/
		$this->getRecipientTokens();
		$data = [];
		$data["operation"]				= 'create';
		$data["notification_key_name"]	= $this->groupName;
		$data["registration_ids"]		= $this->recipientTokens;
		$header = ['Content-Type: application/json', 'Authorization: key='.FCM_SERVER_KEY, 'project_id:'.FCM_SENDER_ID];
		$response = $this->submitPostCall($header, $data, 'notification');
		if (isset($response['notification_key']))
		{
			$this->groupNotificationKey = $response['notification_key'];
		}
	}
	
	private function getNotificationKey()
	{
		$found = $this->getGroupNotificationKey();
		if (!$found) $this->createGroup();
		$this->storeGroupNotificationKey();
		$this->addKeysToGroup();
	}
	
	private function notifyGroup()
	{
		$this->getNotificationKey();
		$payload	=	[
								'title'			=> $this->title, 
								'body'			=> $this->message,
								//'icon'			=> 'manifest_logo.png',
								//'badge'			=> 'notification_badge.png',
								'priority'		=> 'normal',								
								'click_action'	=> $this->url,
								'tag'			=> $this->groupName
						];
		$data		=	[
							'to'				=> $this->groupNotificationKey,
							'priority'			=> 'normal', 
							'content_available' => true,
							//'data'				=> ['msg' => $payload]
							'data'				=> $payload
						];
		$header = array('Content-Type: application/json', 'Authorization: key='.FCM_SERVER_KEY);
		$response = $this->submitPostCall($header, $data, 'send');
		/**
		{
		  "success":1,
		  "failure":2,
		  "failed_registration_ids":[
			 "regId1",
			 "regId2"
		  ]
		}
		**/
		//if ($response['success']) $this->removeKeysFromGroup();
	}
	
	private function submitPostCall($header, $data, $module)
	{
		$url = self::FCM_BASE_URL.$module;
		$json = json_encode($data);
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $header);		
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
		
		$httpCode = curl_getinfo($ch , CURLINFO_HTTP_CODE); // this results 0 every time
		$response = curl_exec($ch);
		
		$ok = true;
		if ($response === false) 
		{
			$ok = false;
			$response = curl_error($ch);
		}
		curl_close($ch);

		return $ok ? json_decode($response, true) : $response;
	}
	
	private function submitGetCall($header, $module)
	{
		$url = self::FCM_BASE_URL.$module;
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, 0);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $header);		
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		
		$httpCode = curl_getinfo($ch , CURLINFO_HTTP_CODE); // this results 0 every time
		$response = curl_exec($ch);
		
		$ok = true;
		if ($response === false) 
		{
			$ok = false;
			$response = curl_error($ch);
		}
		curl_close($ch);			

		return $ok ? json_decode($response, true) : $response;
	}
}