<?php
/**
 * ###############################################
 *
 * SWIFT Framework
 * _______________________________________________
 *
 * @author		Varun Shoor
 *
 * @package		SWIFT
 * @copyright	Copyright (c) 2001-2012, Kayako
 * @license		http://www.kayako.com/license
 * @link		http://www.kayako.com
 *
 * ###############################################
 */
SWIFT_Loader::LoadInterface('REST:REST');
/**
 * The API Controller
 *
 * @author Varun Shoor
 */
class Controller_api extends SWIFT_Controller
{
	// Core Constants
	const FUNCTION_GET = 'Get';
	const FUNCTION_POST = 'Post';
	const FUNCTION_PUT = 'Put';
	const FUNCTION_DELETE = 'Delete';
	const FUNCTION_LIST = 'GetList';

	const SORT_ASC  = 'ASC';
	const SORT_DESC = 'DESC';

	/**
	 * Constructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __construct()
	{
		parent::__construct();

		$_SWIFT = SWIFT::GetInstance();

		$this->Load->Library('XML:XML');
		$this->Load->Library('REST:RESTServer');
		$this->Load->Library('REST:RESTManager');

		if ($this->Settings->Get('g_enableapiinterface') != '1')
		{
			$this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_FORBIDDEN);

			exit;

			return false;
		}

		$_incomingVariableContainer = $this->RESTServer->GetVariableContainer();

		if (!isset($_incomingVariableContainer['salt']) || empty($_incomingVariableContainer['salt'])) {
			$this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_UNAUTHORIZED);

			echo 'NO SALT PROVIDED!';

			exit;

			return false;
		}

		$_signatureToken = $_incomingVariableContainer['salt'];

		if (!$this->RESTManager->Authenticate($this->RESTServer->Get('apikey'), str_replace(' ', '+', $this->RESTServer->Get('signature')), $_signatureToken))
		{
			$this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_UNAUTHORIZED);

			echo 'FAILED TO AUTHENTICATE';

			exit;

			return false;
		}

		SWIFT_CronManager::RunPendingTasks();

		return true;
	}

	/**
	 * Destructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __destruct()
	{
		parent::__destruct();

		return true;
	}

	/**
	 * @author Saloni Dhall <saloni.dhall@kayako.com>
	 *
	 * @param string $_sortOrder
	 *
	 * @return bool
	 */
	static public function IsValidSortOrder($_sortOrder)
	{
		return in_array(strtoupper($_sortOrder), array(self::SORT_ASC, self::SORT_DESC));
	}

	/**
	 * Attempt to call a method in the class pointer if it doesnt exist in this local class
	 *
	 * @author Varun Shoor
	 * @param string $_name The Function Name
	 * @param array $_arguments The Function Arguments
	 * @return mixed "Function Result" (MIXED) on Success, "false" otherwise
	 */
	public function __call($_name, $_arguments)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_functionName = false;
		switch ($this->RESTServer->GetMethod())
		{
			case SWIFT_RESTServer::METHOD_GET:
				$_functionName = self::FUNCTION_GET;

				break;

			case SWIFT_RESTServer::METHOD_POST:
				$_functionName = self::FUNCTION_POST;

				break;

			case SWIFT_RESTServer::METHOD_PUT:
				$_functionName = self::FUNCTION_PUT;

				break;

			case SWIFT_RESTServer::METHOD_DELETE:
				$_functionName = self::FUNCTION_DELETE;

				break;

			default:
				throw new SWIFT_Exception('Invalid Function Called in API Controller: ' . htmlspecialchars($_name));

				break;
		}

		// List Function?
		if ($this->RESTServer->GetMethod() == SWIFT_RESTServer::METHOD_GET && $_name == SWIFT_Controller::DEFAULT_ACTION)
		{
			$_functionName = self::FUNCTION_LIST;
		}

		if ($_name == SWIFT_Controller::DEFAULT_ACTION)
		{
			$_defaultArgument = '';
		} else {
			$_defaultArgument = $_name;
		}

		/*
		 * ###############################################
		 * PERMISSION CHECKS
		 * ###############################################
		 */

		if ($this->Settings->Get('g_enableapiinterface') != '1')
		{
			$this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_FORBIDDEN);

			exit;

			return false;
		}

		$_argumentContainer = array_merge(array($_defaultArgument), $_arguments);

		/*
		 * ###############################################
		 * BEGIN AUTHENTICATION
		 * ###############################################
		 */

		$_incomingVariableContainer = $this->RESTServer->GetVariableContainer();

		if (!isset($_incomingVariableContainer['salt']) || empty($_incomingVariableContainer['salt'])) {
			$this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_UNAUTHORIZED);

			echo 'NO SALT PROVIDED!: ' . $_functionName;

			exit;

			return false;
		}

		$_signatureToken = $_incomingVariableContainer['salt'];

		if (!$this->RESTManager->Authenticate($this->RESTServer->Get('apikey'), str_replace(' ', '+', $this->RESTServer->Get('signature')), $_signatureToken))
		{
			$this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_UNAUTHORIZED);

			echo 'FAILED TO AUTHENTICATE: ' . $_functionName;

			exit;

			return false;
		}


		/**
		 * Begin Hook: restauthentication
		 */

		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('restauthentication')) ? eval($_hookCode) : false;

		/**
		 * End Hook
		 */


		$_ReflectionObject = new ReflectionClass($this);

		if ($_functionName && $_ReflectionObject instanceof ReflectionClass)
		{
			if ($_ReflectionObject->hasMethod($_functionName))
			{
				// Before we call this, we need to update the router..
				$_SWIFT->Router->SetAction($_functionName);

				return call_user_func_array(array($this, $_functionName), $_argumentContainer);
			} else {
				throw new SWIFT_Exception('Undeclared Function Called in API Controller: ' . htmlspecialchars($_functionName));

				return false;
			}
		}

		return false;
	}
}
?>