<?php

namespace Fifa\ConnectId\Sdk;

use Fifa\ConnectId\Sdk\ActorResolver\ActorResolverInterface;
use Fifa\ConnectId\Sdk\ActorResolver\SimpleActorResolver;
use Fifa\ConnectId\Sdk\ApiClient\DataHolder\DataHolderApi;
use Fifa\ConnectId\Sdk\ApiClient\DataHolder\DataHolderApiInterface;
use Fifa\ConnectId\Sdk\ApiClient\Facility\FacilityApi;
use Fifa\ConnectId\Sdk\ApiClient\Facility\FacilityApiInterface;
use Fifa\ConnectId\Sdk\ApiClient\Hashing\HashingApi;
use Fifa\ConnectId\Sdk\ApiClient\Hashing\HashingApiInterface;
use Fifa\ConnectId\Sdk\ApiClient\Organisation\OrganisationApi;
use Fifa\ConnectId\Sdk\ApiClient\Organisation\OrganisationApiInterface;
use Fifa\ConnectId\Sdk\ApiClient\Person\PersonApi;
use Fifa\ConnectId\Sdk\ApiClient\Person\PersonApiInterface;
use Fifa\ConnectId\Sdk\Environment\EnvironmentInterface;
use Fifa\ConnectId\Sdk\HashedPersonProcessor\HashedPersonProcessorInterface;
use Fifa\ConnectServiceBus\Sdk\Authentication\Model\ClientCredentials;
use Psr\Log\LoggerInterface;

/**
 * Class FifaConnectIdClient
 * @package Fifa\ConnectId\Sdk
 */
class FifaConnectIdClient implements FifaConnectIdClientInterface
{
    /**
     * @var EnvironmentInterface
     */
    private $environment;

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

    /**
     * @var HashingApiInterface
     */
    private $hashingApi;

    /**
     * @var PersonApiInterface
     */
    private $personApi;

    /**
     * @var OrganisationApiInterface
     */
    private $organisationApi;

    /**
     * @var FacilityApiInterface
     */
    private $facilityApi;

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

    /**
     * @var ClientCredentials
     */
    private $clientCredentials;

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

    /**
     * @var HashedPersonProcessorInterface|null
     */
    private $hashedPersonProcessor;

    /**
     * Constructor
     * @param EnvironmentInterface $environment
     * @param ClientCredentials $clientCredentials
     * @param LoggerInterface $logger
     * @param ActorResolverInterface|null $actorResolver
     * @param HashedPersonProcessorInterface|null $hashedPersonProcessor
     */
    public function __construct(EnvironmentInterface   $environment, ClientCredentials $clientCredentials, LoggerInterface $logger,
                                ActorResolverInterface $actorResolver = null, HashedPersonProcessorInterface $hashedPersonProcessor = null)
    {
        $this->environment = $environment;
        $this->logger = $logger;
        $this->clientCredentials = $clientCredentials;
        $this->actorResolver = is_null($actorResolver) ? SimpleActorResolver::emptyActor() : $actorResolver;
        $this->hashedPersonProcessor = $hashedPersonProcessor;
    }

    /**
     * Gets person Api
     *
     * @return PersonApiInterface
     */
    public function getPersonApi(): PersonApiInterface
    {
        if (!$this->personApi instanceof PersonApiInterface) {
            $this->personApi = new PersonApi(
                $this->environment->getPersonApiResource($this->clientCredentials),
                $this->getHashingApi(), $this->logger, $this->actorResolver, $this->hashedPersonProcessor
            );
        }

        return $this->personApi;
    }

    /**
     * Gets organisation Api
     *
     * @return OrganisationApiInterface
     */
    public function getOrganisationApi(): OrganisationApiInterface
    {
        if (!$this->organisationApi instanceof OrganisationApiInterface) {
            $this->organisationApi = new OrganisationApi(
                $this->environment->getOrganisationApiResource($this->clientCredentials),
                $this->logger, $this->actorResolver
            );
        }

        return $this->organisationApi;
    }

    /**
     * Gets FacilityApi
     *
     * @return FacilityApiInterface
     */
    public function getFacilityApi(): FacilityApiInterface
    {
        if (!$this->facilityApi instanceof FacilityApiInterface) {
            $this->facilityApi = new FacilityApi(
                $this->environment->getFacilityApiResource($this->clientCredentials),
                $this->logger, $this->actorResolver
            );
        }

        return $this->facilityApi;
    }

    /**
     * Gets Data Holder Api
     *
     * @return DataHolderApiInterface
     */
    public function getDataHolderApi(): DataHolderApiInterface
    {
        if (!$this->dataHolderApi instanceof DataHolderApiInterface) {
            $this->dataHolderApi = new DataHolderApi(
                $this->environment->getDataHolderApiResource($this->clientCredentials),
                $this->logger, $this->actorResolver
            );
        }

        return $this->dataHolderApi;
    }

    /**
     * Gets hashing api
     *
     * @return HashingApiInterface
     */
    private function getHashingApi(): HashingApiInterface
    {
        if (!$this->hashingApi instanceof HashingApiInterface) {
            $this->hashingApi = new HashingApi(
                $this->environment->getHashingApiResource($this->clientCredentials),
                $this->logger
            );
        }

        return $this->hashingApi;
    }
}