<?php

namespace NoahVet\Reef\Domain\Tool;

class ArrayTool implements ArrayToolInterface
{
    /**
     * @psalm-param mixed $data
     *
     * @psalm-param-out mixed $data
     */
    #[\Override]
    public static function applyTrimRecursive(mixed &$data): void
    {
        if (null === $data) {
            return;
        }

        if (\is_array($data)) {
            \array_walk(
                $data,
                static function (mixed &$value): void {
                    self::applyTrimRecursive($value);
                },
            );

            return;
        }

        if (\is_string($data)) {
            $data = \trim($data);
        }
    }

    /**
     * @param array<string, mixed> $array
     * @param array<string>        $whitelist
     *
     * @return array<string, mixed>
     */
    #[\Override]
    public static function applyWhitelistedKeys(array $array, array $whitelist): array
    {
        return \array_intersect_key(
            $array,
            \array_flip($whitelist),
        );
    }

    #[\Override]
    public static function isArrayExist(array $array, string $key): bool
    {
        return isset($array[$key]) && \is_array($array[$key]);
    }

    /**
     * @param array<int<0, max>, mixed> $array
     *
     * @return array<int<0, max>, mixed>
     */
    #[\Override]
    public static function removeDeepDuplicateValues(array $array, string $key): array
    {
        $i = 0;
        $tempArray = [];
        $keyArray = [];

        foreach ($array as $val) {
            if (!\in_array($val[$key], $keyArray)) {
                $keyArray[$i] = $val[$key];
                $tempArray[$i] = $val;
            }
            ++$i;
        }

        return $tempArray;
    }

    /**
     * @param array<string|int, mixed> $array
     *
     * @return \Generator<int, non-empty-array<string, mixed>, mixed, void>
     */
    #[\Override]
    public static function removeDuplicates(array $array, string $key): iterable
    {
        foreach (\array_unique(\array_column($array, $key)) as $datum) {
            yield [$key => $datum];
        }
    }

    /**
     * @param array<string|int, mixed> $array
     *
     * @return list<mixed>
     */
    #[\Override]
    public static function removeDuplicateValues(array $array): array
    {
        return \array_values(\array_unique($array));
    }

    #[\Override]
    public static function removeKeyRecursive(array &$array, string ...$keys): void
    {
        foreach ($keys as $key) {
            unset($array[$key]);
            foreach ($array as &$v) {
                if (\is_array($v)) {
                    self::removeKeyRecursive($v, $key);
                }
            }
        }
    }

    #[\Override]
    public static function sortMultiDimensionalByKey(array &$array): array
    {
        foreach ($array as &$value) {
            if (\is_array($value)) {
                $value = self::sortMultiDimensionalByKey($value);
            }
        }
        \ksort($array);

        return $array;
    }
}
