<?php

namespace CouponsPlus\App\Validators;

use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\Mapper\Types;
use CouponsPlus\Original\Characters\StringManager;

#[\AllowDynamicProperties]
Class InclusionValueValidator extends Validator
{
    protected $valueToValidate;

    public static function getOptions() : Collection
    {
        // we have to use func_get_args since PHP won't allow this 
        // class to change the interface from Validator
        (array) $expectedValuesData = func_get_args()[0] ?? [];
        (array) $inclusionTypeData = func_get_args()[1] ?? [];
        (array) $excludedSubsetValuesData = func_get_args()[2] ?? [];

        return new Collection([
            'expectedValues' => Types::COLLECTION()->meta(
                array_merge(
                    [
                        'name' => __('Values', 'coupons-plus-for-woocommerce')
                    ],
                    $expectedValuesData['meta'] ?? [],
                    [
                        '__allowed' => $expectedValuesData['allowed'] ?? []
                    ]
                )
            ),
            'enableExcludedSubsetValues' => Types::BOOLEAN()->withDefault(false), // only if supported 'supportsExcludingSubset' => true
            'excludedSubsetValues' => Types::COLLECTION()->meta(
                array_merge(
                    ['supportsExcludingSubset' => false],
                    array_merge(
                        [
                            'name' => __('Values', 'coupons-plus-for-woocommerce')
                        ],
                        $excludedSubsetValuesData['meta'] ?? [],
                        [
                            '__allowed' => $excludedSubsetValuesData['allowed'] ?? []
                        ]
                    )

                )
            ),
            'inclusionType' => Types::STRING()->allowed(Collection::create([
                ($inclusionTypeData['meta']['labels']['allowed'] ?? __( 'Eligible'/*'Allowed'*/, 'coupons-plus-for-woocommerce')) => 'allowed',
                ($inclusionTypeData['meta']['labels']['forbidden'] ?? __( 'Not Eligible'/*'Forbidden'*/, 'coupons-plus-for-woocommerce')) => 'forbidden',
                                                ])->sort(function (string $key) use($inclusionTypeData) {
                                                    if ($inclusionTypeData['forbiddenFirst'] ?? false) {
                                                        return StringManager::create($key)->contains('forbidden', false)? -1 : 1;
                                                    }
                                                })->asArray())
                                              ->withDefault($inclusionTypeData['default'] ?? 'allowed')
                                              ->meta(
                                                    array_merge(
                                                        [
                                                            'alternativeLabels' => [
                                                                /*'allowed' => __('Allowed', 'coupons-plus-for-woocommerce'),
                                                                'forbidden' => __('Not Allowed', 'coupons-plus-for-woocommerce'),*/
                                                                'allowed-except-forbidden' => __('Allowed except...', 'coupons-plus-for-woocommerce'),
                                                            ],
                                                        ],
                                                        ['display' => ['allowed', 'forbidden']],
                                                        ($inclusionTypeData['meta'] ?? []),
                                                    )
                                                )
        ]); 
    }

    public function setValueToValidate(/*mixed*/ $valueToValidate)
    {
        if (is_array($valueToValidate)) {
            $valueToValidate = new Collection($valueToValidate);
        } elseif (!($valueToValidate instanceof Collection)) {
            $valueToValidate = new Collection([$valueToValidate]);
        }

        $this->valueToValidate = $valueToValidate;
    }

    public function isValid() : bool
    {
        (boolean) $valueExists = (boolean) count(array_intersect(
            $this->options->expectedValues->asArray(), 
            $this->valueToValidate->asArray()
        ));

        return $this->options->inclusionType->is('allowed')? $valueExists : !$valueExists;
    }
}