<?php

namespace CouponsPlus\App\Coupon\Tree\Factories;

use Closure;
use InvalidArgumentException;
use CouponsPlus\App\Conditions\Card;
use CouponsPlus\App\Coupon\CardData;
use CouponsPlus\App\Coupon\TestableData;
use CouponsPlus\App\Coupon\Tree\Abilities;
use CouponsPlus\App\Coupon\Tree\TestableGroupData;
use CouponsPlus\Original\Collections\Collection;
use stdClass;
use CouponsPlus\App\Coupon\Tree\RawTestableDataInspector;

class TestableGroupDataFromStandardObjectFactory
{
    /**
     * @return Abilities\TestableGroupData|Abilities\TestableData
     */
    public function create(object $testableDataOrGroupRawData)
    {
        $testableInspector = new RawTestableDataInspector($testableDataOrGroupRawData);

        if ($testableInspector->isGroup($testableDataOrGroupRawData)) {
            return $this->createTestableGroupData($testableDataOrGroupRawData);
        }

        return $this->createTestableData($testableDataOrGroupRawData);
    }

    /**
     * This method is set to be extracted at some point cause it dont belong here...
     */
    protected function createTestableData($rawTestableData) : Abilities\TestableData    
    {
        return new TestableData(
            $testableType = $rawTestableData->testableType,
            new CardData(
                $rawTestableData->type, 
                Card::createOptions($testableType, $rawTestableData),
                $rawTestableData->id ?? null
            )
        );
    }

    protected function createTestableGroupData($testableGroupRawData): TestableGroupData
    {
    return new TestableGroupData(
            $testableGroupRawData->type,
            $testableGroupRawData->mode,
            Collection::create($testableGroupRawData->children)->map(
                Closure::bind(function (stdClass $innerTestableGroupRawData) use ($testableGroupRawData) {
                    if ($testableGroupRawData->type === 'context') {
                        return $this->createTestableData($innerTestableGroupRawData);
                    }

                    return $this->create($innerTestableGroupRawData);
                }, $this)
            )->asArray(),
        $testableGroupRawData->id ?? null
        );
    }

}