<?php

declare(strict_types=1);

namespace App\Modules\Shared\Domain\ValueObject;

use App\Modules\Shared\Domain\GenerateActionException;
use Stringable;

abstract class EnumValueObject implements Stringable
{

    protected static array $cache = [];
    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
        $this->ensureIsBetweenAcceptedValues($value);
    }

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

    public function __toString(): string
    {
        return $this->value() . '';
    }

    private function ensureIsBetweenAcceptedValues($value): void
    {
        if (!in_array($value, static::values(), true)) {
            (new GenerateActionException)("Invalid value for enum: $value in " . static::class);
        }
    }

    public static function __callStatic($name, $args)
    {
        return new static(self::values()[$name]);
    }

    public static function fromValue($value): EnumValueObject
    {
        return new static($value);
    }

    public static function randomValue()
    {
        return static::values()[array_rand(static::values())];
    }

    public static function random()
    {
        return new static(self::randomValue());
    }
    abstract public static function values();
}
