<?php

namespace CouponsPlus\App\Conditions;

use CouponsPlus\App\Conditions\CardExportableData;
use CouponsPlus\App\Coupon\Abilities\DashboardCard;
use CouponsPlus\App\Coupon\ComponentOptionsRegistry;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\JSONMapper;
use CouponsPlus\Original\Collections\MappedObject;
use WC_Coupon;

#[\AllowDynamicProperties]
Abstract Class Condition implements DashboardCard
{
    protected $options;
    protected string $id;
    /**
     * @var WC_Coupon
     */
    protected  $coupon;
    abstract public static function getOptions() : Collection;
    abstract protected function test() : bool;
    #: Extended by classes that need it, variable number of args and called in the constructor
    #abstract protected function setExtraData() : void;
    #abstract protected function onOptionsLoaded() : void;
    /*abstract*/ public static function getUseCases() : Collection { return new Collection([]); }
    /*abstract*/ public static function getNotes() : array { return []; }

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

    public static function exportDefault() : MappedObject
    {
        (object) $condition = new static([], new \WC_Coupon());

        return $condition->options;
    }

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

    public function __construct(/*array|string*/ $options, ...$extraData)
    {
        $this->options = ComponentOptionsRegistry::getInstance()->getOrCreate(
            static::class,
            $options,
            array_merge(
                static::getOptions()->asArray(),
                $this->getDefaultOptions()->asArray()
            )
        );


        if (is_array($this->options)) {
            $this->options = new MappedObject;
        }

        if ($extraData && $extraData[0] instanceof WC_Coupon) {
            $this->coupon = $extraData[0];
        }

        if (method_exists($this, 'setExtraData')) {
            $this->setExtraData(...$extraData);
        }

        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 getDefaultOptions() : Collection
    {
        return new Collection([]);   
    }

    public function hasPassed()
    {
        return $this->test();   
    }

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