<?php

namespace Laravel\Passport\Bridge;

use Laravel\Passport\ClientRepository as ClientModelRepository;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;

class ClientRepository implements ClientRepositoryInterface
{
    /**
     * The client model repository.
     *
     * @var \Laravel\Passport\ClientRepository
     */
    protected $clients;

    /**
     * Create a new repository instance.
     *
     * @param  \Laravel\Passport\ClientRepository  $clients
     * @return void
     */
    public function __construct(ClientModelRepository $clients)
    {
        $this->clients = $clients;
    }

    /**
     * {@inheritdoc}
     */
    public function getClientEntity($clientIdentifier)
    {
        $record = $this->clients->findActive($clientIdentifier);

        if (! $record) {
            return;
        }

        return new Client(
            $clientIdentifier, $record->name, $record->redirect, $record->confidential()
        );
    }

    /**
     * {@inheritdoc}
     */
    public function validateClient($clientIdentifier, $clientSecret, $grantType)
    {
        // First, we will verify that the client exists and is authorized to create personal
        // access tokens. Generally personal access tokens are only generated by the user
        // from the main interface. We'll only let certain clients generate the tokens.
        $record = $this->clients->findActive($clientIdentifier);

        if (! $record || ! $this->handlesGrant($record, $grantType)) {
            return false;
        }

        return ! $record->confidential() || hash_equals($record->secret, (string) $clientSecret);
    }

    /**
     * Determine if the given client can handle the given grant type.
     *
     * @param  \Laravel\Passport\Client  $record
     * @param  string  $grantType
     * @return bool
     */
    protected function handlesGrant($record, $grantType)
    {
        if (is_array($record->grant_types) && ! in_array($grantType, $record->grant_types)) {
            return false;
        }

        switch ($grantType) {
            case 'authorization_code':
                return ! $record->firstParty();
            case 'personal_access':
                return $record->personal_access_client && $record->confidential();
            case 'password':
                return $record->password_client;
            case 'client_credentials':
                return $record->confidential();
            default:
                return true;
        }
    }
}
