<?php
/********************************************************************************
 * (c)1337 aheadware.com - All rights reserved
 ********************************************************************************/


class AHDB_Core_RestServer
{
    protected $serviceFolder;
    /** @var AHDB_Core_ACL null  */
    protected $acl;

    protected $requestMethod = 'get';

    protected $responseType = 'application/json';
    protected $responseStatus = 200;
    protected $response = array();

    /**
     * AHDB_Core_Rest constructor.
     * @param string $folder
     * @param AHDB_Core_ACL|null Access Control List
     */
    public function __construct( $serviceFolder, $acl = NULL )
    {
        if ( !is_string( $serviceFolder ) || !is_dir( $serviceFolder ) )
        {
            throw new Exception( 'Invalid service folder given.' );
        }

        $this->serviceFolder = $serviceFolder;
        $this->acl = $acl;
    }

    /**
     * Process request
     *
     * @param array $params
     */
    public function process( array $server = array() )
    {
        $service = NULL;
        $params = NULL;
        $getParams = $_GET;
        $paramsJson = file_get_contents( 'php://input' );
        json_decode( $paramsJson );
        if ( json_last_error() == JSON_ERROR_NONE )
        {
            $params = json_decode( $paramsJson, true );
        }

        if ( !is_array( $params ) )
        {
            $params = array();
        }

        $params = array_merge( $params, $getParams );

        // Check for required data
        if ( !isset( $server[ 'PHP_SELF' ] ) ||
             !isset( $server[ 'REQUEST_URI' ] ) )
        {
            throw new Exception( 'Missing server data.' );
        }

        // Method
        $this->requestMethod = (isset( $server[ 'REQUEST_METHOD' ] ) ) ? strtolower( $server[ 'REQUEST_METHOD' ] ) : 'get';

        // Service
        $uriPath = parse_url( $server[ 'REQUEST_URI' ], PHP_URL_PATH );
        $uripart = rtrim( $server[ 'PHP_SELF' ], 'index.php' );
        //$uripart = ltrim( $server[ 'REQUEST_URI' ], $uripart );
        $uripart = str_replace( $uripart, "", $uriPath );
        $uriparts = explode( '/', $uripart );

        if ( is_array( $uriparts ) && 0 < count( $uriparts ) )
        {
            $service = ucfirst( strtolower( $uriparts[0] ) );

            // USE Router instead to get additional params from route
            /*
            if ( 1 < count( $uriparts ) )
            {
                $params = array_slice( $uriparts, 1 );
            }
            */
        }

        $servicePath = $this->serviceFolder . '/' . $service . '.php';

        if ( file_exists( $servicePath ) )
        {
            require_once( $servicePath );

            if ( class_exists( $service ) )
            {
                // Merge
                $serviceInst = new $service( $params );

                if ( ( $serviceInst instanceof AHDB_Core_RestService ) )
                {
                    try
                    {
                        if ( isset( $this->acl ) )
                        {
                            if ( false === $this->acl->isAllowed( $service, $this->requestMethod ) )
                            {
                                throw new Exception( '404' );
                            }
                        }

                        $res = call_user_func( array( $serviceInst, $this->requestMethod ) );

                        if ( !is_array( $res ) )
                        {
                            $this->response = array( $res );
                        }
                        else
                        {
                            $this->response = $res;
                        }
                    }
                    catch ( Exception $e )
                    {
                        if ( 0 != $e->getCode() )
                        {
                            $this->responseStatus = $e->getCode();
                        }
                        $this->response = array( 'error' => $e->getMessage() );
                    }
                }
            }
        }
    }

    /**
     * Respond to client
     *
     * @param array $data
     */
    public function respond( array $response = NULL, $status = NULL )
    {

        // Overwrite resposne if set
        if ( is_array( $response ) )
        {
            $this->response = $response;
        }

        if ( isset( $status ) )
        {
            $this->responseStatus = $status;
        }

        // Output
        http_response_code( $this->responseStatus );
        header('Content-type: ' . $this->responseType );
        echo json_encode( $this->response );
    }
}