<?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 screen for which to diplay this meta-box. -- Only internal use
     */
    protected array|string|null $screen = 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->screen ? "metabox-{$this->screen}-{$this->id}" : "metabox-{$this->id}";
        $this->assets->enqueueCompiledScript($assetId);
        // localize the script with the metabox data
        wp_localize_script($assetId, 'metaboxData', $this->addMetaboxData());

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

    /**
     * @since 0.6.0 -- added standardized method to add metabox script data
     * @return array
     */
    public function addMetaboxData(): array
    {
        return [];
    }

    /**
     * Whether the metabox should be rendered.
     *
     * @param bool $value -- Whether the metabox should be rendered
     * @return bool -- Whether the metabox should be rendered
     * @hooked wpm_should_render_metabox_{id}
     */
    public function shouldRender(bool $value): bool
    {
        return $value;
    }

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

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

    /* 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 $screen
     * @return AbstractMetabox
     */
    public function withScreen(array|string|null $screen): static
    {
        $this->screen = $screen;

        return $this;
    }

}