<?php

/** @noinspection PhpMissingParamTypeInspection */

/** @noinspection PhpMissingFieldTypeInspection */

namespace DefStudio\GameEngine\Decorators;

use ArrayAccess;
use Illuminate\Database\Eloquent\Model;

/**
 * @template TModel of Model|ModelDecorator
 *
 * @mixin TModel
 */
abstract class ModelDecorator implements ArrayAccess
{
    /** @var TModel */
    public $model;

    /**
     * @param  TModel|ModelDecorator<TModel>  $model
     */
    final public function __construct($model)
    {
        $this->model = $model instanceof static ? $model->model : $model;
        $this->setup_decorator();
    }

    /**
     * @param  TModel|ModelDecorator<TModel>  $model
     */
    final public static function build($model): static
    {
        return new static($model);
    }

    protected function setup_decorator(): void
    {
        // nothing by default...
    }

    public function __call(string $name, array $arguments): mixed
    {
        return $this->model->{$name}(...$arguments);
    }

    public function __set(string $name, mixed $value): void
    {
        $this->model->{$name} = $value;
    }

    public function __get(string $name): mixed
    {
        return $this->model->{$name};
    }

    public function offsetExists($offset): bool
    {
        return $this->model->offsetExists($offset);
    }

    public function offsetGet($offset): mixed
    {
        return $this->model->offsetGet($offset);
    }

    public function offsetSet($offset, $value): void
    {
        $this->model->offsetSet($offset, $value);
    }

    public function offsetUnset($offset): void
    {
        $this->model->offsetUnset($offset);
    }
}
