<?php
namespace Fifa\ConnectId\Sdk\ApiClient\DataHolder;
use Exception;
use Fifa\ConnectId\Sdk\ActorResolver\ActorResolverInterface;
use Fifa\ConnectId\Sdk\Api\Resource\DataHolderApi as ResourceDataHolderApi;
use Fifa\ConnectId\Sdk\ApiClient\HttpResponseLogging;
use Fifa\ConnectId\Sdk\ApiModelValidation\FifaIdValidator;
use Fifa\ConnectId\Sdk\Exception\FifaConnectIdException;
use Fifa\ConnectId\Sdk\Exception\FifaEntityDeletedException;
use Fifa\ConnectId\Sdk\Exception\FifaEntityNotFoundException;
use Fifa\ConnectId\Sdk\Exception\FifaPersonMergedException;
use Fifa\ConnectId\Sdk\Exception\InvalidClientDataException;
use Fifa\ConnectId\Sdk\ExceptionHandler\ExceptionHandler;
use Fifa\ConnectId\Sdk\ExceptionHandler\Handler\MergeOperations\FifaPersonMergedHandler;
use Fifa\ConnectId\Sdk\Registration\ValidationException;
use Fifa\ConnectId\Sdk\Util\ActorEncoder;
use Fifa\ConnectServiceBus\Sdk\Exception\AuthenticationException;
use Fifa\ConnectServiceBus\Sdk\Exception\UnauthorizedException;
use Psr\Log\LoggerInterface;

class DataHolderApi implements DataHolderApiInterface {

    use HttpResponseLogging;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var ResourceDataHolderApi
     */
    private $dataHolderApi;

    /**
     * @var ActorResolverInterface
     */
    private $actorResolver;

    /**
     * Constructor
     *
     * @param ResourceDataHolderApi $dataHolderApi
     * @param LoggerInterface $logger
     * @param ActorResolverInterface $actorResolver
     */
    public function __construct(ResourceDataHolderApi $dataHolderApi, LoggerInterface $logger, ActorResolverInterface $actorResolver)
    {
        $this->logger = $logger;
        $this->dataHolderApi = $dataHolderApi;
        $this->actorResolver = $actorResolver;
    }


    /**
     * @inheritDoc
     *
     * @throws ValidationException
     * @throws AuthenticationException
     * @throws InvalidClientDataException
     * @throws UnauthorizedException
     * @throws FifaPersonMergedException
     * @throws FifaEntityNotFoundException
     * @throws FifaEntityDeletedException
     * @throws FifaConnectIdException
     */
    public function getDataHoldersOfPerson(string $personFifaId): array
    {
        FifaIdValidator::validate($personFifaId, 'personFifaId');
        $this->logger->info('Getting Data Holders of person with id ' . $personFifaId);
        try {
            list($responseType, $statusCode, $httpHeaders) =
                $this->dataHolderApi->dataHolderGetByPersonfifaidWithHttpInfo($personFifaId);
            $this->logResponse($this->logger, $responseType, $statusCode, $httpHeaders, 'Data Holders received');

            return $responseType;
        }
        catch (Exception $e) {
            $exception = ExceptionHandler::create($e);
            $this->logger->error('Failed to get Data Holders for person with id ' . $personFifaId, array('exception' => $exception->__toString()));
            throw $exception;
        }
    }

    /**
     * @inheritDoc
     *
     * @throws ValidationException
     * @throws AuthenticationException
     * @throws InvalidClientDataException
     * @throws UnauthorizedException
     * @throws FifaPersonMergedException
     * @throws FifaEntityNotFoundException
     * @throws FifaEntityDeletedException
     * @throws FifaConnectIdException
     */
    public function registerAsDataHolderOfPerson(string $personFifaId): void
    {
        FifaIdValidator::validate($personFifaId, 'personFifaId');
        $this->logger->info('Registering as Data Holder for person with fifa id ' . $personFifaId);
        try {
            list($responseType, $statusCode, $httpHeaders) =
                $this->dataHolderApi->dataHolderClaimByPersonfifaidWithHttpInfo($personFifaId, ActorEncoder::encode($this->actorResolver));
            $this->logResponse($this->logger, $responseType, $statusCode, $httpHeaders, 'Registered as Data Holder');
        }
        catch (Exception $e) {
            $exception = ExceptionHandler::create($e, new FifaPersonMergedHandler());
            $this->logger->error('Failed to register as Data Holder for person with id ' . $personFifaId, array('exception' => $exception->__toString()));
            throw $exception;
        }
    }
}