<?php


namespace ModulesGarden\ProxmoxAddon\App\Services;


class RestFullApi
{
    const HTTP_GET = 'GET';
    const HTTP_PUT = 'PUT';
    const HTTP_POST ='POST';
    const HTTP_DELETE ='DELETE';
    protected $host;
    protected $headers = [];
    protected $response;
    protected $parsedResponse;
    protected $requestUrl;
    protected $actionPath;
    protected $method;
    protected $request;
    private $curl;
    private $logger;
    protected  $curlInfo;
    protected $apiUri;

    /**
     * RestFullApi constructor.
     * @param $host
     * @param $port
     * @param $protocol
     */
    public function __construct($host)
    {
        $this->host     = $host;
    }

    public function useJson(){
        $this->headers[]= "Content-Type: application/json";
        $this->headers[]= "Accept: application/json";
    }

    private function getRequestUrl(){
        return $this->host.$this->apiUri;
    }

    public function post($path, $request=[]){
        $this->method = self::HTTP_POST;
        $this->actionPath = $path;
        $this->request = $request;
        return $this->sendRequest();
    }

    public function get($path, $request=[]){
        $this->method = self::HTTP_GET;
        $this->actionPath = $path;
        $this->request = $request;
        return $this->sendRequest();
    }

    public function put($path, $request=[]){
        $this->method = self::HTTP_PUT;
        $this->actionPath = $path;
        $this->request = $request;
        return $this->sendRequest();
    }

    public function delete($path){
        $this->method = self::HTTP_DELETE;
        $this->actionPath = $path;
        $this->request = null;
        return $this->sendRequest();
    }

    private function sendRequest(){
        $this->requestUrl = $this->getRequestUrl().$this->actionPath;
        $this->curl              = curl_init();
        switch ($this->method)
        {
            case self::HTTP_GET:
                $this->requestUrl .="?". http_build_query($this->request);
                break;
            case self::HTTP_POST:
                if(is_array($this->request)){
                    $request = json_encode($this->request);
                }else{
                    $request = $this->request;
                }
                curl_setopt($this->curl,   CURLOPT_CUSTOMREQUEST , 'POST');
                curl_setopt($this->curl, CURLOPT_POST, true);
                curl_setopt($this->curl, CURLOPT_POSTFIELDS, $request);
                break;
            case self::HTTP_PUT:
                curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, self::HTTP_PUT);
                if(is_array($this->request)){
                    $request = json_encode($this->request);
                    curl_setopt($this->curl, CURLOPT_POSTFIELDS, $request);
                }
                break;
            case self::HTTP_DELETE:
                curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, self::HTTP_DELETE);
                break;
        }
        curl_setopt($this->curl, CURLOPT_URL,  $this->requestUrl);
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $this->headers);
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1);
        return $this->parseResponse()->processResponse();

    }

    public function setLogger($logger)
    {
        $this->logger = $logger;
    }

    private function debug(){
        if (!$this->logger || !method_exists($this->logger, 'log'))
        {
            return;
        }
        $action = sprintf("GET: %s\r\nPOST: %s\r\n", $this->requestUrl, print_r($this->request, true));
        if($this->method == self::HTTP_GET){
            $action = sprintf("GET: %s\r\nPOST: %s\r\n", $this->requestUrl, null);
        }
        $response = sprintf("HTTP %s %s", $this->curlInfo['http_code'], print_r($this->parsedResponse, true));
        $this->logger->log($this->method, $action, $this->response, $response);
    }

    private function parseResponse(){
        $this->response   = curl_exec($this->curl);
        $this->curlInfo = curl_getinfo($this->curl);
        $this->parsedResponse = json_decode($this->response , true);
        $this->debug();

        if (!$this->response)
        {
            $error = curl_error($this->curl);
            curl_close($this->curl);
            if($error  ){
                throw new \Exception('cURL Error: ' . $error);
            }
        }
        curl_close($this->curl);
        return $this;
    }

    private function processResponse(){
        if($this->parsedResponse['errors']){

            $errors =[];
            foreach ($this->parsedResponse['errors'] as $error){
                if(is_array($error)){
                    foreach ($error as $e){
                        $errors[]= $e;
                    }
                }elseif (is_string($error)){
                    $errors[]= $error;
                }
            }
            $message = implode(" ",$errors);
            throw new \Exception(  $message, $this->curlInfo['http_code']);
        }
        if($this->curlInfo['http_code'] >= 400 ){
            throw new \Exception(sprintf('Loging to host: %s failed ', $this->host));
        }
        return $this->parsedResponse;
    }
}