<?php

/*
 * This file is part of the Fancy Bricks package.
 *
 * (c) Joshua Gugun Siagian <suabahasa@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace Fancy\Animations;

use Exception;
use Fancy\Animations\Admin\AdminPage;
use Fancy\Animations\Api\Router as ApiRouter;
use Fancy\Animations\Core\Cache;
use Fancy\Animations\Core\Runtime;
use Fancy\Animations\Utils\BricksHelper;
use Fancy\Animations\Utils\Debug;
use Fancy\Animations\Utils\Notice;
use Fancy\Animations\Utils\Updater;
use _FancyAnimations\FANCY_ANIMATIONS;
use WP_Upgrader;
/**
 * Manage the plugin lifecycle and provides a single point of entry to the plugin.
 *
 * @since 1.0.0
 */
final class Plugin
{
    /**
     * Stores the instance, implementing a Singleton pattern.
     */
    private static self $instance;
    /**
     * Lemon Squeezy licensing integration.
     */
    private static ?Updater $updater = null;
    /**
     * The Singleton's constructor should always be private to prevent direct
     * construction calls with the `new` operator.
     */
    private function __construct()
    {
    }
    /**
     * Singletons should not be cloneable.
     */
    private function __clone()
    {
    }
    /**
     * Singletons should not be restorable from strings.
     *
     * @throws Exception Cannot unserialize a singleton.
     */
    public function __wakeup()
    {
        throw new Exception('Cannot unserialize a singleton.');
    }
    /**
     * This is the static method that controls the access to the singleton
     * instance. On the first run, it creates a singleton object and places it
     * into the static property. On subsequent runs, it returns the client existing
     * object stored in the static property.
     */
    public static function get_instance() : self
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    public function boot_debug()
    {
        if (!\WP_DEBUG) {
            return;
        }
        // when php exits, call the shutdown function.
        \register_shutdown_function(static fn() => Debug::shutdown());
    }
    /**
     * Boot the plugin.
     *
     * @link https://codex.wordpress.org/Plugin_API/Action_Reference
     */
    public function boot() : void
    {
        \do_action('a!fancy/animations/plugin:boot.start');
        // (de)activation hooks.
        \register_activation_hook(FANCY_ANIMATIONS::FILE, fn() => $this->activate_plugin());
        \register_deactivation_hook(FANCY_ANIMATIONS::FILE, fn() => $this->deactivate_plugin());
        // register_uninstall_hook(FANCY_ANIMATIONS::FILE, 'fancy_animations_uninstall_plugin');
        // upgrade hooks.
        \add_action('upgrader_process_complete', function (WP_Upgrader $wpUpgrader, array $options) : void {
            if ($options['action'] === 'update' && $options['type'] === 'plugin') {
                foreach ($options['plugins'] as $plugin) {
                    if ($plugin === \plugin_basename(FANCY_ANIMATIONS::FILE)) {
                        $this->upgrade_plugin();
                    }
                }
            }
        }, 10, 2);
        $this->maybe_update_plugin();
        new Runtime();
        \add_action('plugins_loaded', fn() => $this->plugins_loaded());
        \add_action('init', fn() => $this->init_plugin());
        \do_action('a!fancy/animations/plugin:boot.end');
    }
    /**
     * Initialize and hold the plugin updater instance.
     */
    public function maybe_update_plugin()
    {
        if (!isset(self::$updater)) {
            self::$updater = new Updater(\plugin_basename(FANCY_ANIMATIONS::FILE), \plugin_basename(\dirname(FANCY_ANIMATIONS::FILE)), FANCY_ANIMATIONS::VERSION, FANCY_ANIMATIONS::LEMONSQUEEZY_URL);
        }
        return self::$updater;
    }
    /**
     * Handle the plugin's deactivation by (maybe) running database migrations
     * and initializing the plugin configuration.
     */
    public function uninstall_plugin() : void
    {
        \do_action('a!fancy/animations/plugin:uninstall_plugin.start');
        \delete_option(FANCY_ANIMATIONS::WP_OPTION . '_version');
        \delete_option(FANCY_ANIMATIONS::WP_OPTION . '_options');
        \delete_option(FANCY_ANIMATIONS::WP_OPTION . '_settings');
        \delete_option(FANCY_ANIMATIONS::WP_OPTION . '_license');
        \delete_option(FANCY_ANIMATIONS::WP_OPTION . '_license_message');
        BricksHelper::deregister_selectors();
        \do_action('a!fancy/animations/plugin:uninstall_plugin.end');
    }
    /**
     * Handle the plugin's activation by (maybe) running database migrations
     * and initializing the plugin configuration.
     */
    private function activate_plugin() : void
    {
        \do_action('a!fancy/animations/plugin:activate_plugin.start');
        \update_option(FANCY_ANIMATIONS::WP_OPTION . '_version', FANCY_ANIMATIONS::VERSION);
        \add_option(FANCY_ANIMATIONS::WP_OPTION . '_options', \json_encode((object) FANCY_ANIMATIONS::DEFAULT_SETTINGS, \JSON_THROW_ON_ERROR));
        BricksHelper::register_selectors();
        Cache::schedule_cache(1);
        \do_action('a!fancy/animations/plugin:activate_plugin.end');
    }
    /**
     * Handle plugin's deactivation by (maybe) cleaning up after ourselves.
     */
    private function deactivate_plugin() : void
    {
        \do_action('a!fancy/animations/plugin:deactivate_plugin.start');
        \do_action('a!fancy/animations/plugin:deactivate_plugin.end');
    }
    /**
     * Handle the plugin's upgrade by (maybe) running database migrations.
     */
    private function upgrade_plugin() : void
    {
        \do_action('a!fancy/animations/plugin:upgrade_plugin.start');
        BricksHelper::register_selectors();
        Cache::schedule_cache(1);
        \do_action('a!fancy/animations/plugin:upgrade_plugin.end');
    }
    /**
     * Initialize the plugin on WordPress' `init` hook.
     */
    private function init_plugin() : void
    {
        \do_action('a!fancy/animations/plugin:init_plugin.start');
        // Load translations.
        \load_plugin_textdomain(FANCY_ANIMATIONS::TEXT_DOMAIN, \false, \dirname(\plugin_basename(FANCY_ANIMATIONS::FILE)) . '/languages/');
        // Instantiate the AdminPage class.
        new AdminPage();
        \do_action('a!fancy/animations/plugin:init_plugin.end');
    }
    /**
     * Initialize the plugin on WordPress' `plugins_loaded` hook.
     */
    private function plugins_loaded() : void
    {
        \do_action('a!fancy/animations/plugin:plugins_loaded.start');
        new ApiRouter();
        if (\is_admin()) {
            \add_action('admin_notices', static fn() => Notice::admin_notices());
            \add_filter('plugin_action_links_' . \plugin_basename(FANCY_ANIMATIONS::FILE), fn($links) => $this->plugin_action_links($links));
        }
        \do_action('a!fancy/animations/plugin:plugins_loaded.end');
    }
    /**
     * Add plugin action links.
     *
     * @param array $links Plugin action links.
     * @return array Plugin action links.
     *
     * @todo Add settings link when the settings page is implemented.
     */
    private function plugin_action_links(array $links) : array
    {
        $base_url = AdminPage::get_page_url();
        \array_unshift($links, \sprintf('<a href="%s">%s</a>', \esc_url(\sprintf('%s#/', $base_url)), \esc_html__('Dashboard', 'fancy-animations')));
        return $links;
    }
}
