<?php

namespace CouponsPlus\App\Coupon;

use CouponsPlus\App\Coupon\Tree\Abilities;
use CouponsPlus\App\Coupon\Tree\Abilities\Branch;
use CouponsPlus\Original\Characters\StringManager;
use CouponsPlus\Original\Collections\MappedObject;
use JsonSerializable;
use CouponsPlus\App\Coupon\Tree\Abilities\NodeData;
use CouponsPlus\App\Coupon\Tree\Abilities\TestableGroupData;

class TestableData implements Abilities\TestableData, JsonSerializable
{
    /**
     * @var Abilities\TestableData|Abilities\TestableGroupData|null
     */
    protected $parent;
    protected ?NodeData $node = null;
    private $innerTestableData;
    private $testableType;

    /**
     * @param string   $testableType      filter|condition
     * @param CardData $innerTestableData The filter or condition data, like: type:InCategories, options:[...]
     */
    public function __construct(string $testableType, CardData $innerTestableData)
    {
        $this->innerTestableData = $innerTestableData;
        $this->testableType = new StringManager($testableType);
    }

    public function setParent($parent): void
    {
        $this->parent = $parent;
    }

    /**
     * @return Abilities\TestableGroupData|Abilities\TestableData|null
     */
    public function getParent()
    {
        return $this->parent;
    }

    public function setNode(NodeData $nodeData): void
    {
        $this->node = $nodeData;
    }

    public function getNode(): ?NodeData
    {
        return $this->node;
    }

    public function setBranch(Branch $branch): void
    {
        $this->branch = $branch;
    }

    public function getBranch(): ?Branch
    {
        return $this->branch;
    }

    public function getID(): string
    {
        return $this->innerTestableData->getID();
    }

    public function getTestableType(): StringManager
    {
        return $this->testableType;
    }

    public function getType(): StringManager
    {
        return $this->innerTestableData->getType();
    }

    public function getOptions(): MappedObject
    {
        /**
         * Here's where we'll merge the base option with the partial options if this is a testable partial.
         *
         */
        if ($this->isPartial()) {
            $parentBranch = $this->getNode()->getParent();
            $baseTestable = $parentBranch->getExtraData()->baseTestable;
            // here's where we merge the base testable with the current data
        }
        return $this->innerTestableData->getOptions();
    }

    public function isPartial() : bool
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        return StringManager::create($this->getID())->contains('testable-partial');
    }

    #[\ReturnTypeWillChange]
    public function jsonSerialize() : array
    {
        return get_object_vars($this);
    }

    public function canFilterItems(): bool
    {
        return $this->getTestableType()->is('filter');
    }
}