<?php

namespace AuthStack\OAuth2\Model\Protocol;

use AuthStack\OAuth2\OAuth2Constants;

class Client
{
    const T_PUBLIC = 'public';
    const T_CONFIDENTIAL = 'confidential';

    // Used for validation when registering clients
    const STATE_GRANTS_TO_RESPONSES = [
        OAuth2Constants::GRANT_TYPE_AUTH_CODE => OAuth2Constants::RESP_TYPE_CODE,
        OAuth2Constants::GRANT_TYPE_IMPLICIT => OAuth2Constants::RESP_TYPE_TOKEN,
        OAuth2Constants::GRANT_TYPE_PWD => OAuth2Constants::RESP_TYPE_NONE,
        OAuth2Constants::GRANT_TYPE_CREDS => OAuth2Constants::RESP_TYPE_NONE,
        OAuth2Constants::GRANT_TYPE_REFRESH_TOKEN => OAuth2Constants::RESP_TYPE_NONE,
        OAuth2Constants::GRANT_TYPE_JWT_BEARER => OAuth2Constants::RESP_TYPE_NONE,
        OAuth2Constants::GRANT_TYPE_SAML2_BEARER => OAuth2Constants::RESP_TYPE_NONE,
    ];

    protected $client_id;
    protected $client_secret;
    protected $redirect_uris = [];

    /**
     * OAuth2 Client model defined by https://tools.ietf.org/html/rfc7591
     *
     * @var array
     */
    protected $model = [

        /**
         * Array of redirection URI strings for use in redirect-based flows
         * such as the authorization code and implicit flows.  As required by
         * Section 2 of OAuth 2.0 [RFC6749], clients using flows with
         * redirection MUST register their redirection URI values.
         * Authorization servers that support dynamic registration for
         * redirect-based flows MUST implement support for this metadata
         * value.
         */
        'redirect_uris' => [],

        /**
         * none
         * client_secret_post
         * client_secret_basic
         */
        'token_endpoint_auth_method' => '',

        /**
         *  Array of OAuth 2.0 grant type strings that the client can use at the token endpoint.
         * These grant types are defined as follows:
         *
         * authorization_code
         * implicit
         * password
         * client_credentials
         * refresh_token
         * urn:ietf:params:oauth:grant-type:jwt-bearer
         * urn:ietf:params:oauth:grant-type:saml2-bearer
         *
         */
        'grant_types' => [],

        /**
         * Array of the OAuth 2.0 response type strings that the client can
         * use at the authorization endpoint.  These response types are
         * defined as follows:
         *
         * code
         * token
         */
        'response_types' => [],

        /**
         * Human-readable string name of the client to be presented to the end-user during authorization
         */
        'client_name' => '',

        /**
         * URL string of a web page providing information about the client.
         * If present, the server SHOULD display this URL to the end-user in
         * a clickable fashion.
         */
        'client_uri' => '',

        /**
         * URL string that references a logo for the client.  If present, the
         * server SHOULD display this image to the end-user during approval.
         * The value of this field MUST point to a valid image file.  The
         * value of this field MAY be internationalized
         */
        'logo_uri' => '',

        /**
         * String containing a space-separated list of scope values (as
         * described in Section 3.3 of OAuth 2.0 [RFC6749]) that the client
         * can use when requesting access tokens.  The semantics of values in
         * this list are service specific.  If omitted, an authorization
         * server MAY register a client with a default set of scopes.
         */
        'scope' => '',

        /**
         * Array of strings representing ways to contact people responsible
         * for this client, typically email addresses.  The authorization
         * server MAY make these contact addresses available to end-users for
         * support requests for the client.  See Section 6 for information on
         * Privacy Considerations.
         */
        'contacts' => [],

        /**
         * URL string that points to a human-readable terms of service
         * document for the client that describes a contractual relationship
         * between the end-user and the client that the end-user accepts when
         * authorizing the client.  The authorization server SHOULD display
         * this URL to the end-user if it is provided.  The value of this
         * field MUST point to a valid web page.  The value of this field MAY
         * be internationalized, as described in Section 2.2.
         */
        'tos_uri' => '',

        /**
         * URL string that points to a human-readable privacy policy document
         * that describes how the deployment organization collects, uses,
         * retains, and discloses personal data.  The authorization server
         * SHOULD display this URL to the end-user if it is provided.  The
         * value of this field MUST point to a valid web page.  The value of
         * this field MAY be internationalized, as described in Section 2.2.
         */
        'policy_uri' => '',

        /**
         * URL string referencing the client's JSON Web Key (JWK) Set
         * [RFC7517] document, which contains the client's public keys.  The
         * value of this field MUST point to a valid JWK Set document.  These
         * keys can be used by higher-level protocols that use signing or
         * encryption.  For instance, these keys might be used by some
         * applications for validating signed requests made to the token
         * endpoint when using JWTs for client authentication [RFC7523].  Use
         * of this parameter is preferred over the "jwks" parameter, as it
         * allows for easier key rotation.  The "jwks_uri" and "jwks"
         * parameters MUST NOT both be present in the same request or
         * response.
         */
        'jwks_uri' => '',

        /**
         * Client's JSON Web Key Set [RFC7517] document value, which contains
         * the client's public keys.  The value of this field MUST be a JSON
         * object containing a valid JWK Set.  These keys can be used by
         * higher-level protocols that use signing or encryption.  This
         * parameter is intended to be used by clients that cannot use the
         * "jwks_uri" parameter, such as native clients that cannot host
         * public URLs.  The "jwks_uri" and "jwks" parameters MUST NOT both
         * be present in the same request or response.
         */
        'jwks' => [],

        /**
         * A unique identifier string (e.g., a Universally Unique Identifier
         * (UUID)) assigned by the client developer or software publisher
         * used by registration endpoints to identify the client software to
         * be dynamically registered.  Unlike "client_id", which is issued by
         * the authorization server and SHOULD vary between instances, the
         * "software_id" SHOULD remain the same for all instances of the
         * client software.  The "software_id" SHOULD remain the same across
         * multiple updates or versions of the same piece of software.  The
         * value of this field is not intended to be human readable and is
         * usually opaque to the client and authorization server.
         */
        'software_id' => 0,

        /**
         * A version identifier string for the client software identified by
         * "software_id".  The value of the "software_version" SHOULD change
         * on any update to the client software identified by the same
         * "software_id".  The value of this field is intended to be compared
         * using string equality matching and no other comparison semantics
         * are defined by this specification.  The value of this field is
         * outside the scope of this specification, but it is not intended to
         * be human readable and is usually opaque to the client and
         * authorization server.  The definition of what constitutes an
         * update to client software that would trigger a change to this
         * value is specific to the software itself and is outside the scope
         * of this specification.
         */
        'software_version' => '',

    ];


    /**
     * @param string $id
     * @return Client
     */
    public function setClientID(string $id): self
    {
        $this->client_id = $id;

        return $this;
    }

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

    /**
     * @param string $secret
     * @return Client
     */
    public function setClientSecret(string $secret): self
    {
        $this->client_secret = $secret;

        return $this;
    }

    /**
     * @return string
     */
    public function getClientSecret(): string
    {
        return $this->client_secret;
    }

    public function addRedirectURI(string $uri)
    {

    }

    protected function isValidUrl(string $url): bool
    {
        $result = filter_var($url, FILTER_VALIDATE_URL);

        if(!$result) return false;

        return !(bool)strpos($url, '#');
    }
}