<?php

namespace WordpressModels;

use WordpressModels\DependencyInjection\Metabox\AbstractMetabox;
use WordpressModels\DependencyInjection\Metabox\Attributes\AsMetabox;
use WordpressModels\Traits\AbstractSingletonTrait;
use WP_Post;

/**
 * @deprecated 0.5.0 Use Dependency Injection instead, using {@see AsMetabox} attribute and {@see AbstractMetabox} class.
 */
abstract class PostMetaBox
{

    use AbstractSingletonTrait;

    protected const CONTEXTS = ['normal', 'side', 'advanced'];
    protected const PRIORITIES = ['high', 'core', 'default', 'low'];

    /**
     * @param string $id The metabox identifier
     * @param string $title This metabox title
     * @param string|null $postType The posttype for which to diplay this meta-box
     * @param value-of<static::CONTEXTS> $context Section in which the metabox is displayed ('normal', 'side', or 'advanced')
     * @param value-of<static::PRIORITIES> $priority 'high', 'core', 'default', or 'low'
     * @param string[] $enqueueScripts list of to enqueue scripts (via Assets util)
     */
    public function __construct(
        public readonly string  $id,
        private readonly string  $title,
        public readonly ?string $postType = null,
        private readonly string  $context = 'advanced',
        private readonly string  $priority = 'default',
        private readonly array   $enqueueScripts = [],
        private readonly ?Assets $assets = null
    )
    {
        add_action('add_meta_boxes' . ($postType ? "_$postType" : ''), $this->registerMetaBox(...));

        add_action('load-post.php', $this->enqueueScriptAction(...));
        add_action('load-post-new.php', $this->enqueueScriptAction(...));

        add_filter('wpm_should_render_metabox_' . $id, $this->shouldRender(...), 10, 2);

        _deprecated_class(__CLASS__, '0.5.0', 'Use Dependency Injection instead.');
    }

    /**
     * Add the enqueue_admin_script action for 'load-post[-new].php' action on 'shop_order' post types.
     * @return void
     */
    public function enqueueScriptAction(): void
    {
        global $typenow;
        if ($typenow === $this->postType) {
            add_action('admin_enqueue_scripts', $this->enqueueScripts(...), 10, 1);
        }
    }

    /**
     * Enqueue $this->enqueueScripts via Assets util (compiled via webpack)
     * @return void
     */
    public function enqueueScripts(): void
    {
        if (!$this->assets) {
            return;
        }
        foreach ($this->enqueueScripts as $script) {
            $this->assets->enqueueCompiledScript($script);
        }
    }

    /**
     * Add the additional order info meta box.
     * @param WP_Post $post
     * @return void
     */
    public function registerMetaBox(WP_Post $post): void
    {
        if (apply_filters('wpm_should_render_metabox_' . $this->id, true, $post)) {
            add_meta_box(
                $this->id,
                $this->title,
                $this->renderMetaBox(...),
                $this->postType,
                $this->context,
                $this->priority
            );
        }
    }

    /**
     * Whether the metabox should be rendered.
     *
     * @param bool $value
     * @param WP_Post $post
     * @return bool
     */
    public function shouldRender(bool $value, WP_Post $post): bool
    {
        return $value;
    }

    /**
     * Render function.
     *
     * Should echo the contents of the metabox.
     *
     * @param WP_Post $post
     *
     * @return void
     */
    public abstract function renderMetaBox(WP_Post $post): void;

}
