<?php
/**
 * Implements the support to register mobile devices as clients on REST-Like API bus.
 *
 * @author Camilo Carromeu <camilo@carromeu.com>
 * @category class
 * @package core
 * @subpackage api
 * @copyright 2005-2017 Titan Framework
 * @license http://www.titanframework.com/license/ BSD License (3 Clause)
 * @see ApiAuth, ApiEntity, ApiException, ApiList, BrowserDevice
 * @link http://www.titanframework.com/docs/api/
 */
class MobileDevice
{
	static private $active = NULL;

	const NO_USER = '_NO_USER_';
	const BY_LOGIN = '_BY_LOGIN_';
	const BY_MAIL = '_BY_MAIL_';
	const BY_ID = '_BY_ID_';

	public static function isActive ()
	{
		if (is_null (self::$active))
			self::$active = Database::tableExists ('_mobile');

		return self::$active;
	}

	public static function register ($name, $user = FALSE)
	{
		if (!self::isActive ())
			return NULL;

		$name = substr (str_replace (array ('"', "'"), '', trim ($name)), 0, 128);

		if ($user === FALSE)
			$user = User::singleton ()->getId ();

		$db = Database::singleton ();

		$id = Database::nextId ('_mobile', '_id');

		$pk = self::randomPrivateKey ();

		$sth = $db->prepare ("INSERT INTO _mobile (_id, _name, _pk, _user) VALUES (:id, :name, :pk, :user)");

		$sth->bindParam (':id', $id, PDO::PARAM_INT);
		$sth->bindParam (':name', $name, PDO::PARAM_STR, 128);
		$sth->bindParam (':pk', $pk, PDO::PARAM_STR, 16);
		$sth->bindParam (':user', $user, PDO::PARAM_INT);

		$sth->execute ();

		return (object) array ('name' => $name, 'id' => $id, 'pk' => $pk, 'user' => $user);
	}

	public static function unregister ($id, $user = FALSE)
	{
		if (!self::isActive ())
			return FALSE;

		if ($user === FALSE)
			$user = User::singleton ()->getId ();

		$sth = Database::singleton ()->prepare ("DELETE FROM _mobile WHERE _id = :id AND _user = :user");

		$sth->bindParam (':id', $id, PDO::PARAM_INT);
		$sth->bindParam (':user', $user, PDO::PARAM_INT);

		return $sth->execute ();
	}

	public static function randomPrivateKey ()
	{
		for ($s = '', $i = 0, $z = strlen ($a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1; $i != 16; $x = rand (0, $z), $s .= $a{$x}, $i++);

		return $s;
	}

	public static function validatePrivateKey ($pk)
	{
		return substr ((string) preg_replace ('/[^0-9A-Z]/i', '', $pk), 0, 16);
	}

	public static function formatPrivateKey ($pk)
	{
		$pk = self::validatePrivateKey ($pk);

		if (strlen ($pk) > 12)
			return substr ($pk,  0, 4) .'-'. substr ($pk,  4, 4) .'-'. substr ($pk,  8, 4) .'-'. substr ($pk,  12, 4);

		if (strlen ($pk) > 8)
			return substr ($pk,  0, 4) .'-'. substr ($pk,  4, 4) .'-'. substr ($pk,  8, 4);

		if (strlen ($pk) > 4)
			return substr ($pk,  0, 4) .'-'. substr ($pk,  4, 4);

		return $pk;
	}

	public static function getRegisteredDevice ($id)
	{
		$id = (int) preg_replace ('/[^0-9]/i', '', $id);

		if (!is_integer ($id) || !$id)
			throw new Exception ('Invalid value to parameter Client ID!');

		$db = Database::singleton ();

		$sth = $db->prepare ("SELECT _id AS id, _pk AS pk, _user AS user FROM _mobile WHERE _id = :id LIMIT 1");

		$sth->bindParam (':id', $id, PDO::PARAM_INT);

		$sth->execute ();

		return $sth->fetch (PDO::FETCH_OBJ);
	}

	public static function registerDeviceAccess ($id)
	{
		$id = (int) preg_replace ('/[^0-9]/i', '', $id);

		if (!is_integer ($id) || !$id)
			throw new Exception ('Invalid value to parameter Client ID!');

		$db = Database::singleton ();

		$sth = $db->prepare ("UPDATE _mobile SET _access = now(), _counter = _counter + 1 WHERE _id = :id");

		$sth->bindParam (':id', $id, PDO::PARAM_INT);

		return $sth->execute ();
	}

	public static function registerGoogleCloudMessage ($id, $gcm)
	{
		$id = (int) preg_replace ('/[^0-9]/i', '', $id);

		if (!is_integer ($id) || !$id)
			throw new Exception ('Invalid value to parameter Client ID!');

		if (trim ($gcm) == '')
			throw new Exception ('Invalid value to Registration ID of Google Cloud Message!');

		$db = Database::singleton ();

		$sth = $db->prepare ("UPDATE _mobile SET _gcm = :gcm, _update = now() WHERE _id = :id");

		$sth->bindParam (':id', $id, PDO::PARAM_INT);
		$sth->bindParam (':gcm', $gcm, PDO::PARAM_STR);

		if (!$sth->execute ())
			return FALSE;

		$sth = $db->prepare ("SELECT _name FROM _mobile WHERE _id = :id");

		$sth->bindParam (':id', $id, PDO::PARAM_INT);

		$sth->execute ();

		$obj = $sth->fetch (PDO::FETCH_OBJ);

		return $obj->_name;
	}

	public static function sendNotification ($apiKey, $ids, $message)
	{
		if (trim ($apiKey) == '' || !is_array ($ids) || !sizeof ($ids) || (!is_array ($message) && !is_object ($message)))
			return FALSE;

		$headers = array ('Content-Type:application/json', 'Authorization:key='. $apiKey);

		$data = array ('data' => $message, 'registration_ids' => $ids);

		$ch = curl_init ();

		curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt ($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
		curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
		curl_setopt ($ch, CURLOPT_POSTFIELDS, json_encode ($data));

		$response = curl_exec ($ch);

		curl_close ($ch);

		echo "Google Cloud Messaging Response: ". $response ." [for: ". implode (", ", $ids) ."] \n";

		return $response;
	}
}