<?php

declare(strict_types=1);

namespace apexl\Io\modules\tabulator\Collections;

use apexl\Io\collections\LoaderConditionCollection;
use apexl\Io\exceptions\LoaderConditionResolutionException;
use apexl\Io\exceptions\TabulatorFilterConditionCannotBeConvertedToWhereException;
use apexl\Io\includes\System;
use apexl\Io\modules\tabulator\Dto\TabulatorFilter;
use apexl\Io\modules\tabulator\Interfaces\HasTabulatorViewInterface;
use apexl\Io\modules\tabulator\Services\TabulatorFieldRenamer;
use Arrayy\Arrayy;
use Arrayy\Collection\AbstractCollection;

/**
 * @extends AbstractCollection<array-key, TabulatorFilter>
 */
class TabulatorFilterCollection extends AbstractCollection
{

    public static function blank(): self
    {
        return new self([]);
    }

    public static function createFromArray(array $array): TabulatorFilterCollection
    {
        $array = array_map(
            fn(array|TabulatorFilter $filter) => $filter instanceof TabulatorFilter ? $filter : TabulatorFilter::fromArray(
                $filter
            ),
            $array
        );

        return parent::createFromArray($array);
    }

    public function getType(): string
    {
        return TabulatorFilter::class;
    }

    public function containsGeneralSearch(): bool
    {
        return $this->exists(
            fn(TabulatorFilter $filter) => $filter->field === '_general'
        );
    }

    /**
     * @throws LoaderConditionResolutionException
     * @throws TabulatorFilterConditionCannotBeConvertedToWhereException
     */
    public function toLoaderConditions(HasTabulatorViewInterface $entity): LoaderConditionCollection
    {
        $collection = new LoaderConditionCollection();
        Arrayy::createFromObject($this)->each(
            fn(TabulatorFilter $filter) => $collection->append($filter->toLoaderCondition($entity))
        );

        return $collection;
    }

    protected function internalSet($key, &$value, bool $checkProperties = true): bool
    {
        assert($value instanceof TabulatorFilter);

        $value = $value->with(
            'field',
            System::getRegisteredService(TabulatorFieldRenamer::class)->rename($value->field)
        );

        return parent::internalSet($key, $value, $checkProperties);
    }
}
