<?php
/**
 * Abstract class for MioTeam API
 * Based on http://coreymaynard.com/blog/creating-a-restful-api-with-php/
 */


abstract class API
{
    /**
     * 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: /files
     */
    protected $endpoint = '';
    /**
     * Property: verb
     * An optional additional descriptor about the endpoint, used for things that can
     * not be handled by the basic methods. eg: /files/process
     */
    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: apiKey
     * Stores the input of the ApiKey received
     */
     protected $apiKey = '';
    /**
     * Property: apiSecret
     * Stores the ApiKey constant
     */
     protected $apiSecret = 'jr56kl9';
    /**
     * Property: authToken
     * Stores the input of the authorization token received
     */
     protected $authToken = '';
    /**
     * Property: userId
     * Stores the anagrafica key for the user record accessing the API
     */
     protected $userId = '';
    /**
     * Property: codiceCommunity
     * Stores the team code for the current user
     */
     protected $codiceCommunity = '';
     
     /*
      * allowed files format for image upload
      *
      */
     private $_supportedFormats = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif'];
     
     

    /**
     * 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");

        $this->args = explode('/', rtrim($request, '/'));

        // get ApiKey
        $this->apiKey = array_pop($this->args);
        
        // isolate endpoint
        $this->endpoint = array_shift($this->args);

        // check if endpoint is auth or accounts, otherwise get token
        if ($this->endpoint<>"auth" && $this->endpoint<>"accounts") {
            // get token
            $this->authToken = array_pop($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");
            }
        }
        
        // check if endpointrequires additional action
        switch ($this->endpoint) {
            // list of endpoints:
            case 'endpoint1':
            case 'bacheca':
                if ($this->method == 'GET') {
                    // extract verb
                    // can be 'feed','last'
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'news':
                if ($this->method == 'GET') {
                    // extract verb
                    // can be 'feed','last'
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'events':
                if ($this->method == 'GET') {
                    // extract verb
                    // can be 'feed','last'
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'messaggi':
                if ($this->method == 'GET') {
                    // extract verb
                    // can be 'feed','last'
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'chat':
                if ($this->method == 'GET') {
                    // extract verb
                    // can be 'message'
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'user':
                if ($this->method == 'GET') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'accounts':
                if ($this->method == 'GET') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                if ($this->method == 'POST') {
                    // extract verb
                    if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                        $this->verb = array_shift($this->args);
                    }
                }
                break;
            case 'endpoint2':
                // extract verb
                if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
                    $this->verb = array_shift($this->args);
                }
                break;
        }

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

    
    public function processAPI() {
        if ($this->apiKey<>$this->apiSecret) {
//            throw new Exception('Invalid API Key');
            return $this->_response('Bad Request', 400);
        } else {
            if ($this->endpoint<>"auth" && $this->endpoint<>"accounts" && $this->_checkAuth()==FALSE ) {
                // Auth code not valid or expired 
                return $this->_response('Expired token', 400);
            } else {
                if (method_exists($this, $this->endpoint)) {
                    $ret = $this->{$this->endpoint}($this->args);
                    // print "Ret: ";print_r ($ret);
                    return (is_array($ret)?$this->_response($ret[0],$ret[1]):$this->_response($ret));
                }
                return $this->_response("No Endpoint: $this->endpoint", 404);
            }
           
        }
/*        
        if (method_exists($this, $this->endpoint)) {
            return $this->_response($this->{$this->endpoint}($this->args));
        }
        return $this->_response("No Endpoint: $this->endpoint", 404);
 * 
 */
    }

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

    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) {
        // print "Status code".$code;
        $status = array(  
            200 => 'OK',
            400 => 'Bad Request',
            401 => 'Unauthorized',   
            404 => 'Not Found',   
            405 => 'Method Not Allowed',
            500 => 'Internal Server Error',
        ); 
        return ($status[$code])?$status[$code]:$status[500]; 
    }    

    
    private function _checkAuth() {
        $debug=TRUE;
        $log_active=TRUE;
        // Collega log file & stamap info di debug
        if ($log_active!=false) {
                $logfile = fopen ("/var/www/log/mioteamapiBETA_".date("Ymd").'.log',"a");
                fwrite ($logfile,"******************************************************************************************\n");
                fwrite ($logfile,"**\n");
                fwrite ($logfile,"**\n\n");
                fwrite ($logfile,"Started Bacheca api endpoint on ".date("d")."/".date("m")."/".date("Y")."-".date("H").":".date("i")."\n\n");
        }
        if ($log_active) {fwrite ($logfile,"function _checkAuth started\r\n");}
        if ($debug) {print "function _checkAuth started\r\n";}
        $query="SELECT user_token, anagrafica_id, UNIX_TIMESTAMP(data) as 'data' FROM api_user_auth WHERE user_token='$this->authToken';";
        if ($debug) {print "Query to get token details: ".$query."\r\n";}
        $rows=$this->do_select_query ($query);
        if (count($rows)==1) {
            if ($debug) {print "Token found\r\n";}
            $myauth = $rows [0];
            if ($debug) {print "Row from auth table: ";print_r ($myauth);print " \r\n";}
            $mytimestamp = $myauth ['data'];
            $query="SELECT id, UserID, CodiceCommunity FROM anagrafica WHERE id='".$myauth['anagrafica_id']."';";
            $userResult=$this->do_select_query ($query);
            if (count($userResult)==1) {
                $user = $userResult [0];
                if ($debug) {print "anagrafica data found for id:".$myauth['anagrafica_id']." \r\n";}
                $this->userId=$user['UserID'];
                $this->anagraficaId=$myauth['anagrafica_id'];
                if ($debug) {print "UserID:".$this->userId." \r\n";}
                $this->codiceCommunity=$user['CodiceCommunity'];
                if ($debug) {print "codiceCommunity:".$this->codiceCommunity." \r\n";}
            } else {
                // user not found - maybe deleted? return false
                if ($debug) {print "User not found in anagrafica - maybe deleted?  \r\n";}
                return FALSE;
            }
            // TBD - Insert expiry date check here
            $now = (new DateTime)->getTimestamp();
            if ($debug) {print "Current TimeStamp: $now \r\n";}
            if ($debug) {print "Current Time: ".date("Y-m-d H:i:s",$now)."\r\n";}
            if ($debug) {print "Auth TimeStamp: $mytimestamp \r\n";}
            if ($debug) {print "Auth Time: ".date("Y-m-d H:i:s",$mytimestamp)."\r\n";}
            if ($debug) {print "timestamp difference: ".(($now-$mytimestamp))." \r\n";}
            if ($log_active) {fwrite ($logfile,"Current TimeStamp: $now \r\n");}
            if ($log_active) {fwrite ($logfile,"Current Time: ".date("Y-m-d H:i:s",$now)."\r\n");}
            if ($log_active) {fwrite ($logfile,"Auth TimeStamp: $mytimestamp \r\n");}
            if ($log_active) {fwrite ($logfile,"Auth Time: ".date("Y-m-d H:i:s",$mytimestamp)."\r\n");}
            if ($log_active) {fwrite ($logfile,"timestamp difference: ".(($now-$mytimestamp))." \r\n;");}
            // expiry in 1 day
            if ((intval($now) - intval($mytimestamp)) > 300) {
                // 86400 = 24*60*60
                if ($log_active) {fwrite ($logfile, "Token Expired!\r\n");}
                return FALSE;
            }
            if ($log_active) {fwrite ($logfile, "Token Still Valid!\r\n");}
            return TRUE;
        } else {
            if ($log_active) {fwrite ($logfile, "not found in database table\r\n");}
            if ($debug) {print "Token not found in database table \r\n";}
        }
        
        return FALSE;
    }

    
    /*
     * Helper for DB queries SELECT
     */
    protected function do_select_query($query) {
        $res = Database :: prepare ( $query ) ;
        $res -> execute ( ) ;
        $return_rows = $res -> fetchAll ( ); 
        $res -> closeCursor ( ) ;
        return $return_rows;
    }

    /*
     * Helper for DB queries UPDATE/INSERT/DELETE
     */
    protected function do_update_query($query) {
        $res = Database :: prepare ( $query ) ;
        $res -> execute ( ) ;
        // $return_rows = $res -> fetchAll ( ); 
        $res -> closeCursor ( ) ;
        return $return_rows;
    }
    
    /*
     * Function to perform file upload
     */
    public function uploadFile ($file){
        if (is_array($file)) {
            // continue
            if (in_array($file['type'],$this->_supportedFormats)) {
                // continue
                $saveDir = "http://community.mioteam.it/mioteamdata/communities/".$this->codiceCommunity."/usersfolders/".$this->userId."/";
                move_uploaded_file($file['tmp_name'],$saveDir.$file['name']);
                return 'file upload successful: '.$saveDir.$file['name'];
            } else {
                return "File format not supported";
            }
        } else {
            return "No file uploaded";
        }
    }
    
}


?>