<?php
namespace IntellexApps\PHP\UploadFile\Network;

class Request
{

    public $method  = null;
    public $data    = null;
    public $files    = null;

    /**
     * Construct
     *
     * Request constructor.
     * @throws \Exception
     * @throws \HttpException
     */
    public function __construct()
    {
        // Build method
        $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 there is valid json in POST body
        $additionalData = [];
        $postBody = trim(file_get_contents('php://input'));
        if(!empty($postBody)) {
            $decoded = json_decode($postBody, true);
            if(json_last_error() == JSON_ERROR_NONE) {
                $additionalData = array_merge($additionalData, $decoded);
            }
        }

        // Handle files
        $this->files = $this->parseFiles();

        // Clean inputs
        switch($this->method) {
            case 'DELETE':
            case 'POST':
                $this->data = $this->cleanInputs(array_merge($_POST, $additionalData));
                break;
            case 'GET':
                $this->data = $this->cleanInputs($_GET);
                break;
            case 'PUT':
                $this->request = $this->cleanInputs(array_merge($_GET, $additionalData));
                $this->file = file_get_contents("php://input");
                break;
            case 'OPTIONS':
                $response = new Response();
                $response->output();
                die;
                break;
            default:
                $response = new Response();
                $response->output();
                break;
        }
    }

    /**
     * Parse files
     *
     * @return array
     */
    public function parseFiles()
    {
        if(empty($_FILES)) {
            return [];
        }

        $files = array();

        foreach($_FILES as $paramName => $values) {
            if(!isset($files[$paramName])) {
                $files[$paramName] = [];
            }
            foreach($values as $index => $items) {
                foreach($items as $itemIndex => $itemValue) {
                    $files[$paramName][$itemIndex][$index] = $itemValue;
                }
            }
        }
        return $files;
    }

    /**
     * Clean inputs
     *
     * @param $data
     * @return array|string
     */
    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;
    }

    /**
     * Get data
     *
     * @return array|null|string
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * Get files
     *
     * @return array
     */
    public function getFiles()
    {
        return $this->files;
    }

    /**
     * Get key
     *
     * @param $key
     * @return mixed|null
     */
    public function get($key)
    {
        if(isset($this->data[$key])) {
            return $this->data[$key];
        }

        return null;
    }


    /**
     * Set data
     *
     * @param $key
     * @param $value
     */
    public function set($key, $value)
    {
        if(!$this->data) {
            $this->data = [];
        }

        $this->data[$key] = $value;
    }
}