<?php
namespace Fifa\ConnectId\Sdk\Util\Builder\Person;

use DateTime;
use Fifa\ConnectId\Sdk\Api\Model\MatchOfficialRegistrationType;
use Fifa\ConnectId\Sdk\Api\Model\OrganisationOfficialRegistrationType;
use Fifa\ConnectId\Sdk\Api\Model\PersonType;
use Fifa\ConnectId\Sdk\Api\Model\PlayerRegistrationType;
use Fifa\ConnectId\Sdk\Api\Model\TeamOfficialRegistrationType;
use Fifa\ConnectId\Sdk\Model\PersonData;
use Fifa\ConnectId\Sdk\Model\PersonName;
use Fifa\ConnectId\Sdk\Util\DateUtils\TimezoneChecker;
use Psr\Log\InvalidArgumentException;

/**
 * Class PersonBuilder
 * @package Fifa\ConnectId\Sdk\Util\Builder\Person
 */
class PersonBuilder implements PersonBuilderInterface
{
    /**
     * @var PersonType
     */
    private $personType;

    /**
     * @var PersonName[]
     */
    private $personNames = array();

    /**
     * Static way of creating instance of PersonBuilder
     *
     * @return PersonBuilder
     */
    public static function create(): PersonBuilder
    {
        return new PersonBuilder();
    }

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->personType = new PersonType();
    }

    /**
     * Gets person data
     *
     * @return PersonData
     */
    public function getPersonData(): PersonData
    {
        return new PersonData(
            $this->personType,
            $this->personNames
        );
    }

    /**
     * Sets date of birth
     *
     * @param DateTime $dateOfBirth
     * @return PersonBuilderInterface
     */
    public function setDateOfBirth(DateTime $dateOfBirth): PersonBuilderInterface
    {
        TimezoneChecker::checkIsUTC($dateOfBirth, 'Date of birth must be specified in UTC');
        $this->personType->setDateOfBirth($dateOfBirth);

        return $this;
    }

    /**
     * Sets person gender
     *
     * @param string|null $gender
     * @return PersonBuilderInterface
     */
    public function setGender(?string $gender): PersonBuilderInterface
    {
        $this->personType->setGender($gender);
        return $this;
    }

    /**
     * Adds a name to a person as two strings ($firstName and $lastName)
     *
     * @param string|null $lastName
     * @param string $firstName
     * @return PersonBuilderInterface
     */
    public function addName(string $firstName, string $lastName = null): PersonBuilderInterface
    {
        return $this->addPersonName(new PersonName($firstName, $lastName));
    }

    /**
     * Adds a name to a person by giving PersonName instance
     *
     * @param PersonName $personName
     * @return PersonBuilderInterface
     */
    public function addPersonName(PersonName $personName): PersonBuilderInterface
    {
        $this->personNames[] = $personName;

        return $this;
    }

    /**
     * Adds player registration to a person
     *
     * @param string $level
     * @param string $discipline
     * @param string $status
     * @param string $organisationFifaId
     * @param string|null $registrationNature
     * @return PersonBuilderInterface
     */
    public function addPlayerRegistration(string $level, string $discipline, string $status, string $organisationFifaId, string $registrationNature = null): PersonBuilderInterface
    {
        $playerRegistration = new PlayerRegistrationType();
        $playerRegistration->setLevel($level);
        $playerRegistration->setDiscipline($discipline);
        $playerRegistration->setOrganisationFifaId($organisationFifaId);
        $playerRegistration->setStatus($status);
        $playerRegistration->setRegistrationNature($registrationNature);

        $this->personType->setPlayerRegistrations(array_merge(
            $this->personType->getPlayerRegistrations() ?: [],
            array($playerRegistration)
        ));

        return $this;
    }

    /**
     * Adds match official registration to a person
     *
     * @param string $matchOfficialRole
     * @param string $discipline
     * @param string $status
     * @param string $organisationFifaId
     * @return PersonBuilderInterface
     */
    public function addMatchOfficialRegistration(string $matchOfficialRole, string $discipline, string $status, string $organisationFifaId): PersonBuilderInterface
    {
        $matchOfficialRegistration = new MatchOfficialRegistrationType();
        $matchOfficialRegistration->setMatchOfficialRole($matchOfficialRole);
        $matchOfficialRegistration->setDiscipline($discipline);
        $matchOfficialRegistration->setOrganisationFifaId($organisationFifaId);
        $matchOfficialRegistration->setStatus($status);

        $this->personType->setMatchOfficialRegistrations(array_merge(
            $this->personType->getMatchOfficialRegistrations() ?: [],
            array($matchOfficialRegistration)
        ));

        return $this;
    }

    /**
     * Adds team official registration to a person
     *
     * @param string $teamOfficialRole
     * @param string $discipline
     * @param string $status
     * @param string $organisationFifaId
     * @return PersonBuilderInterface
     */
    public function addTeamOfficialRegistration(string $teamOfficialRole, string $discipline, string $status, string $organisationFifaId): PersonBuilderInterface
    {
        $teamOfficialRegistration = new TeamOfficialRegistrationType();
        $teamOfficialRegistration->setTeamOfficialRole($teamOfficialRole);
        $teamOfficialRegistration->setDiscipline($discipline);
        $teamOfficialRegistration->setOrganisationFifaId($organisationFifaId);
        $teamOfficialRegistration->setStatus($status);

        $this->personType->setTeamOfficialRegistrations(array_merge(
            $this->personType->getTeamOfficialRegistrations() ?: [],
            array($teamOfficialRegistration)
        ));

        return $this;
    }

    /**
     * Adds organisation official registration to a person
     *
     * @param string $organisationOfficialRole
     * @param string $status
     * @param string $organisationFifaId
     * @return PersonBuilderInterface
     */
    public function addOrganisationOfficialRegistration(string $organisationOfficialRole, string $status, string $organisationFifaId): PersonBuilderInterface
    {
        $organisationOfficialRegistration = new OrganisationOfficialRegistrationType();
        $organisationOfficialRegistration->setOrganisationOfficialRole($organisationOfficialRole);
        $organisationOfficialRegistration->setOrganisationFifaId($organisationFifaId);
        $organisationOfficialRegistration->setStatus($status);

        $this->personType->setOrganisationOfficialRegistrations(array_merge(
            $this->personType->getOrganisationOfficialRegistrations() ?: [],
            array($organisationOfficialRegistration)
        ));

        return $this;
    }
}