<?php

abstract class APIControllerAbstract
{
    /**
     * Property: method
     * The HTTP method this request was made in, either GET, POST, PUT or DELETE
     */
    protected $method = '';
    /**
     * Property: endpoint
     * The Model requested in the URI. eg: /offers
     */
    protected $endpoint = '';
    /**
     * Property: verb
     * An optional additional descriptor about the endpoint, used for things that can
     * not be handled by the basic methods. eg: /offers/page
     */
    protected $verb = '';
    /**
     * Property: args
     * Any additional URI components after the endpoint and verb have been removed, in our
     * case, an integer ID for the resource. eg: /<endpoint>/<verb>/<arg0>/<arg1>
     * or /<endpoint>/<arg0>
     */
    protected $args = Array();
    /**
     * Property: file
     * Stores the input of the PUT request
     */
    protected $file = NULL;
    /**
     * Property: input
     * Stores the input of the POST request
     */
    protected $input = '';
    /**
     * Property: response
     * Stores the response of the GET request
     */
    protected $response = '';

    /**
     * Constructor: __construct
     * Allow for CORS, assemble and pre-process the data
     */
    public function __construct($request)
    {
        header("Access-Control-Allow-Orgin: *");
        header("Access-Control-Allow-Methods: *");
        header("Content-Type: application/json; charset=utf8");

        $this->args = explode('/', rtrim($request, '/'));
        $this->endpoint = array_shift($this->args);
        if (array_key_exists(0, $this->args) && !is_numeric($this->args[0]))
        {
            $this->verb = array_shift($this->args);
        }

        $this->method = $_SERVER['REQUEST_METHOD'];
        if ($this->method == 'POST' && array_key_exists('HTTP_X_HTTP_METHOD', $_SERVER))
        {
            if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'DELETE')
            {
                $this->method = 'DELETE';
            }
            else if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'PUT')
            {
                $this->method = 'PUT';
            }
            else
            {
                throw new Exception("Unexpected Header");
            }
        }

        switch ($this->method)
        {
            case 'POST':
                $this->input = $this->_cleanInputs(file_get_contents('php://input'));
                $this->request = $this->_cleanInputs($_POST);
                break;
            case 'PUT':
                $this->input = $this->_cleanInputs(file_get_contents("php://input"));
                $this->request = $this->_cleanInputs($_POST);
                break;
            case 'DELETE':
                $this->input = $this->_cleanInputs(file_get_contents("php://input"));
                $this->request = $this->_cleanInputs($_POST);
                break;
            default:
                $this->_response('Invalid Method', 405);
                break;
        }
    }

    public function processAPI()
    {
        if ((int)method_exists($this, $this->endpoint) > 0)
        {
            return $this->_response($this->{$this->endpoint}($this->args));
        }
        return $this->_response("No Endpoint: ".$this->endpoint, 404);
    }

    protected function _response($data, $status = 200)
    {
        header("HTTP/1.1 " . $status . " " . $this->_requestStatus($status));
        $this->log($data);
        return json_encode($data);
    }

    private function _cleanInputs($data)
    {
        $clean_input = Array();
        if (is_array($data))
        {
            foreach ($data as $k => $v)
            {
                $clean_input[$k] = $this->_cleanInputs($v);
            }
        }
        else
        {
            $clean_input = trim(strip_tags($data));
        }
        return $clean_input;
    }

    private function _requestStatus($code)
    {
        $status = array(
            200 => 'OK',
            401 => 'Unauthorized',
            404 => 'Not Found',
            405 => 'Method Not Allowed',
            500 => 'Internal Server Error',
        );
        return ($status[$code])?$status[$code]:$status[500];
    }

    public function log($data)
    {
        $BaseModel = new BaseModel();
        $data_log = new stdClass();
        $response = $BaseModel->verifyData($this->input);
        if ($response['status'] == 'secure')
        {
            $data_log->success = true;
        }
        else
        {
            $data_log->success = false;
        }
        $data_log->endpoint = $this->endpoint;
        if ($this->verb != '')
        {
            $data_log->endpoint .= '/'.$this->verb;
        }
        $data_log->external_uuid = $_SERVER['HTTP_X_ORIGIN'];
        $data_log->data = json_encode($data)
                          .' METHOD:'.$_SERVER['HTTP_X_HTTP_METHOD'];
        $BaseModel->logApiAccess($data_log);
    }
}
?>
