<?php

namespace AuthStack\OAuth2\Model\Protocol\Request\AuthorizationCode;


use AuthStack\OAuth2\Exception\OAuth2Exception;
use AuthStack\OAuth2\OAuth2Constants;
use AuthStack\OAuth2\Model\Protocol\Request\AbstractRequest;
use Illuminate\Http\Request;

class AuthorizationRequest extends AbstractRequest
{
    const T_RESP_TYPE = 'code';

    /**
     * Returns the following array:
     * ['response_type' => 'code', 'client_id' => 'string', 'redirect_uri' => 'string', 'scope' => 'string|optional', 'state' => 'string|optional']
     *
     * @return array
     */
    public function toArray(): array
    {
        // Removes empty values (and keys) and returns the resulting array
        $collection = collect($this->model)
            ->reject(function($value, $item) {
                return empty($value);
            })
            ->put('response_type', $this->getResponseType());

        return $collection->toArray();
    }

    /**
     * @return array
     */
    public function model(): array
    {
        return [
            'response_type', 'client_id', 'redirect_uri', 'scope', 'state'
        ];
    }

    /**
     * @param Request|null $request
     * @return AuthorizationRequest
     * @throws OAuth2Exception
     * @return self
     */
    public function receive(Request $request = null)
    {
        $request = $request ?? $request::createFromGlobals();

        $collection = collect();

        collect($this->model())->map(function($value) use ($request, $collection)
        {
            $collection->put($value, $request->input($value));
        });

        if($collection->get('response_type') !== $this->getResponseType())
        {
            throw new OAuth2Exception(OAuth2Constants::ERR_INVALID_REQUEST);
        }

        return $this->setModel($collection->toArray());
    }

    /**
     * @return string
     */
    public function getResponseType(): string
    {
        return OAuth2Constants::RESP_TYPE_CODE;
    }

    /**
     * @return mixed|null
     */
    public function getClientID()
    {
        return $this->getProperty('client_id');
    }

    /**
     * @return mixed|null
     */
    public function getRedirectURI()
    {
        return $this->getProperty('redirect_uri');
    }

    /**
     * @return mixed|null
     */
    public function getScope()
    {
        return $this->getProperty('scope');
    }

    /**
     * @return mixed|null
     */
    public function getState()
    {
        return $this->getProperty('state');
    }
}