<?php

namespace Fifa\ConnectId\Sdk\Util\ArrayUtils\DuplicatesFilter;

use Fifa\ConnectId\Sdk\Model\PersonName;
use Fifa\ConnectId\Sdk\Util\ArrayUtils\ArrayParser;
use Fifa\ConnectId\Sdk\Util\ArrayUtils\DuplicatesFilterInterface;

/**
 * Class PersonNameDuplicatesFilter
 * @package Fifa\ConnectId\Sdk\Util\ArrayUtils\DuplicatesFilter
 */
class PersonNameDuplicatesFilter implements DuplicatesFilterInterface
{
    /**
     * Method filters the duplicates and returns the results as an array
     *
     * @param array $personNames
     * @return array
     */
    public function filterDuplicates(array $personNames): array
    {
        $filtered = array();
        $personNames = ArrayParser::create($personNames)->checkContainsOnlyInstancesOf(PersonName::class)->getData();

        foreach ($personNames as $personName) {
            if (!$this->containsPersonName($filtered, $personName)) {
                $filtered[] = $personName;
            }
        }

        return $filtered;
    }

    /**
     * @param PersonName[] $personNames
     * @param PersonName $personName
     * @return bool
     */
    private function containsPersonName(array $personNames, PersonName $personName): bool
    {
        foreach ($personNames as $pn) {
            if ($this->equals($pn, $personName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param PersonName $p1
     * @param PersonName $p2
     * @return bool
     */
    private function equals(PersonName $p1, PersonName $p2): bool
    {
        return
            $this->stringsEqual($p1->getFirstName(), $p2->getFirstName())
            &&
            $this->stringsEqual($p1->getLastName(), $p2->getLastName());
    }

    /**
     * @param string|null $string1
     * @param string|null $string2
     * @return bool
     */
    private function stringsEqual(?string $string1, ?string $string2): bool
    {
        if ($string1 == null && $string2 == null) {
            return true;
        }

        if ($string1 == null || $string2 == null) {
            return false;
        }

        return $string1 === $string2;
    }
}