<?php

namespace CouponsPlus\App\Conditions;

use CouponsPlus\App\Conditions\Abilities\ItemsSetFilter;
use CouponsPlus\App\Conditions\CardExportableData;
use CouponsPlus\App\Conditions\FiltersRegistrator;
use CouponsPlus\App\Conditions\SubsetSumFilter;
use CouponsPlus\App\Coupon\Abilities\DashboardCard;
use CouponsPlus\App\Coupon\ComponentOptionsRegistry;
use CouponsPlus\App\Export\Abilities\ExportableData;
use CouponsPlus\Original\Cache\MemoryCache;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\JSONMapper;
use CouponsPlus\Original\Collections\MappedObject;
use WC_Coupon;

#[\AllowDynamicProperties]
Abstract Class Filter implements ItemsSetFilter, DashboardCard
{
    const TYPE = 'MUSTBEOVERRIDDEN';

    protected $localSet;
    protected $options;
    protected string $id;

    abstract public static function getOptions() : Collection;
    public static function getNotes() : array { return []; }
    public static function getUseCases() : Collection { return new Collection([]); }
    #abstract protected function onOptionsLoaded() : void;

    public function getType() : string
    {
        return static::TYPE;
    }

    public static function createFromOptions($options, WC_Coupon $coupon) : Filter
    {
        return FiltersRegistrator::createFromOptions($options, $coupon);
    }

    public static function exportDefault() : MappedObject
    {
        (object) $filter = new static([]);

        return $filter->options ?: new MappedObject;
    }

    public function __construct(/*array|string*/ $options)
    {
        $this->cache = new MemoryCache;

        $this->options = ComponentOptionsRegistry::getInstance()->getOrCreate(
            static::class,
            $options,
            array_merge(
                static::getOptions()->asArray(), 
                $this->getDefaultOptions()->asArray()
            )
        );


        if (method_exists($this, 'onOptionsLoaded')) {
            $this->onOptionsLoaded();
        }
    }

    /**
     * Only on 3.0 and up
     */
    public function setID(string $id)
    {
        $this->id = $id;
    }

    /**
     * Only on 3.0 and up.
     *
     * On 2 and below, this is not used.
     */
    public function getID() : string
    {
        return $this->id ?? '';
    }
    
    public function isIntersected() : bool
    {
        return static::SET === IntersectionFilter::class;
    }

    public function isSubsetSum() : bool
    {
        return static::SET === SubsetSumFilter::class;
    }

    public function isSubset() : bool
    {
        return static::SET === SubsetFilter::class;
    }

    public function getDefaultOptions() : Collection
    {
        return new Collection([]);
    }

    public function getLoadedOptions() : MappedObject
    {
        return $this->options;   
    }
    
    public function getDataToExport()
    {
        return new CardExportableData($this);
    }
}