<?php

namespace WordpressModels\DependencyInjection\Metabox;

use WordpressModels\Assets;
use WP_Post;

/**
 * Abstract metabox service class.
 *
 * Extend this class and attribute it with the {@see AsMetabox} attribute to create a metabox service.
 */
abstract class AbstractMetabox implements MetaboxInterface
{

    /**
     * @var string The metabox identifier -- Only internal use
     */
    protected string $id;

    /**
     * @var array|string|null The posttype for which to diplay this meta-box. -- Only internal use
     */
    protected array|string|null $postType = null;

    /**
     * Construct the metabox service.
     *
     * @param Assets|null $assets -- The assets service, use an alias to inject the assets service, e.g. #[Autowire(service: 'assets.my-plugin')]
     * @param array $scripts
     */
    public function __construct(protected ?Assets $assets = null,
                                protected array   $scripts = [])
    {
    }

    /**
     * Enqueue the metabox script and additional scripts.
     *
     * @return void
     */
    public function enqueueScript()
    {
        if (!$this->assets) {
            return;
        }

        $assetId = $this->postType ? "metabox-{$this->postType}-{$this->id}" : "metabox-{$this->id}";
        $this->assets->enqueueCompiledScript($assetId);

        foreach ($this->scripts as $script) {
            $this->assets->enqueueCompiledScript($script);
        }
    }

    /**
     * Whether the metabox should be rendered.
     *
     * @param bool $value -- Whether the metabox should be rendered
     * @param WP_Post|null $post -- The post object, can be null on new post
     * @return bool -- Whether the metabox should be rendered
     * @hooked wpm_should_render_metabox_{id}
     */
    public function shouldRender(bool $value, ?WP_Post $post): bool
    {
        return $value;
    }

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @return array|string|null
     */
    public function getPostType(): array|string|null
    {
        return $this->postType;
    }

    /* Dependency Injection -- mutable setters, should be safe enough */

    /**
     * @param string $id
     * @return AbstractMetabox
     */
    public function withId(string $id): static
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @param array|string|null $postType
     * @return AbstractMetabox
     */
    public function withPostType(array|string|null $postType): static
    {
        $this->postType = $postType;

        return $this;
    }

}