<?php
/**
 * Created by Glee Ltd.
 * User: Hieu
 * Date: 22-Apr-19
 * Time: 11:18 AM
 * Description:
 */

namespace Hura8\System;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;

final class APIClient
{
    private $headers = [];

    /* @var $client \GuzzleHttp\Client */
    protected $client;


    public function __construct($endpoint, $timeout = 10)
    {
        $this->client = new Client([
            // Base URI is used with relative requests
            'base_uri' => $endpoint,
            // You can set any number of default request options.
            'timeout'  => $timeout,
        ]);
    }


    public function post($path, array $parameters) {
        return $this->call_service("post", $path, $parameters);
    }


    public function get($path, array $parameters) {
        return $this->call_service("get", $path, $parameters);
    }


    public function setHeaders(array $headers) {
        // Authorization:
        /*$headers = [
            'Authorization' => "Basic ". base64_encode($this->api_key),
        ];*/
        $this->headers = $headers;
    }

    //ref: http://docs.guzzlephp.org/en/stable/quickstart.html#query-string-parameters
    // make a consistent call with the same $payload format: ["key" => "value", ...]
    /*
    return json {
        "errCode"   => 1|0, (1=error, 0=success)
        "msg"       => "error_message" | "",
    }*/
    protected function call_service($http_method, $path, array $payload) {

        try {

            // get
            if( $http_method == 'get' ) {

                $response = $this->client->request('GET', $path, [
                    'headers' => $this->headers,
                    'query'   => $payload
                ]);
            }

            // post
            else {

                $request_options = $this->buildPostRequestOptions($this->headers, $payload);
                $response = $this->client->request('POST', $path, $request_options);
            }

            return [
                "errCode" => "0",
                "msg" => $response->getBody()->getContents(),
            ];

        }
        catch (ServerException $e) {
            $response = $e->getResponse();
            //$errors = \json_decode($response->getBody()->getContents(), true);
            return [
                "errCode" => 1,
                "msg" => $response->getBody()->getContents(),
            ];
        }
        catch (ClientException $e) {
            $response = $e->getResponse();
            //$errors = \json_decode($response->getBody()->getContents(), true);
            return [
                "errCode" => 2,
                "msg" => $response->getBody()->getContents(),
            ];
        }
        catch (\Exception $e) {
            return [
                "errCode" => 3,
                "msg" => "Exception: ".$e->getMessage(),
            ];
        }
    }


    // ref: http://docs.guzzlephp.org/en/stable/request-options.html
    // form_params cannot be used with the multipart option. You will need to use one or the other.
    // Use form_params for application/x-www-form-urlencoded requests, and multipart for multipart/form-data requests.
    protected function buildPostRequestOptions(array $headers, array $payload) {
        $content_type = isset($headers["Content-Type"]) ? $headers["Content-Type"] : "";

        if($content_type == "application/x-www-form-urlencoded") {
            return [
                'headers' => $headers,
                'form_params' => $payload,
                //'debug' => true
            ];
        }

        if($content_type == "application/json") {
                return [
                    'headers' => $headers,
                    'json'    => $payload,
                    //'body'    => json_encode($payload),
                ];
        }


        // reformat the payload for multipart
        $multipart_request = [];
        foreach ($payload as $key => $value) {
            if( ! $key) continue;

            $multipart_request[] = [
                'name'     => $key,
                'contents' => (is_array($value)) ? json_encode($value) : $value,
            ];
        }

        // multipart/form-data
        return [
            'headers'   => $headers,
            'multipart' => $multipart_request,
        ];

    }
}
