<?php

/**
 * Plugin bootstrap / orchestrator.
 *
 * @package Vanquish\MultipleAddresses
 */
namespace Vanquish\MultipleAddresses;

if ( !defined( 'ABSPATH' ) ) {
    exit;
    // Exit if accessed directly.
}
/**
 * Wires up the plugin components.
 */
final class Plugin {
    /**
     * Singleton instance.
     *
     * @var Plugin|null
     */
    private static $instance = null;

    /**
     * Whether run() has already executed.
     *
     * @var bool
     */
    private $booted = false;

    /**
     * Get the singleton instance.
     *
     * @return Plugin
     */
    public static function instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Private constructor (singleton).
     */
    private function __construct() {
    }

    /**
     * Boot the plugin.
     */
    public function run() {
        if ( $this->booted ) {
            return;
        }
        $this->booted = true;
        // Translations are loaded just-in-time by WordPress (since 4.6) from the
        // plugin's languages/ folder — no load_plugin_textdomain call is needed.
        $this->load_free();
        $this->load_premium();
    }

    /**
     * Instantiate the free (always-on) components.
     */
    private function load_free() {
        // Frontend. AddressAjax owns the CRUD endpoints shared by the My Account
        // book and the checkout selector, so it is registered once here.
        new Frontend\Assets();
        new Frontend\AddressAjax();
        new Frontend\MyAccountPage();
        // The two checkouts are mutually exclusive per store: the classic hooks
        // never fire on the block checkout, and the additional checkout field
        // only renders there, so both can be registered unconditionally.
        new Frontend\CheckoutPage();
        new Frontend\BlockCheckout();
        // Admin.
        if ( is_admin() ) {
            new Admin\AdminMenu();
            new Admin\OrderListColumn();
            // Describes the premium features where they would have been. It
            // decides whether to show anything at render time, not here — the
            // premium modules have not been loaded yet at this point.
            new Admin\Upsell();
            // Tells a buyer how to actually get Premium. Free build only: it
            // decides that itself, since the answer depends on which package is
            // running.
            new Admin\PremiumActivation();
            // The explicit way to clear the settings, since uninstalling keeps
            // them. Registers an admin-post handler, so it must be constructed
            // on every admin request, not only when the settings page renders.
            new Admin\ResetSettings();
        }
    }

    /**
     * Whether the premium features are available to this install.
     *
     * Answered by the SDK's `can_use_premium_code()` — the variant WITHOUT the
     * premium-only postfix, which therefore survives into the free build and can
     * be called from free code. It returns false in the free build, true on a
     * licensed premium build, and false again when that licence lapses, which is
     * exactly the three-way answer the upsell panels need.
     *
     * Asking the SDK rather than reading our own flag also removes an ordering
     * trap: load_free() runs before load_premium(), so a flag set during boot is
     * still false while the free components are being constructed.
     *
     * The local flag survives only for the development escape hatch, which no
     * licence check knows about.
     *
     * @return bool
     */
    public static function premium_active() {
        if ( self::$premium_active ) {
            return true;
        }
        if ( !function_exists( 'vanmuad_fs' ) ) {
            return false;
        }
        return vanmuad_fs()->can_use_premium_code();
    }

    /**
     * Whether load_premium() booted the premium modules.
     *
     * @var bool
     */
    private static $premium_active = false;

    /**
     * Instantiate the premium components.
     *
     * The whole includes/Premium/ folder is physically removed from the free build
     * by Freemius (see the premium-only file list in the main plugin file header),
     * so this code never ships in the free zip. The early return keeps local
     * development safe before the Freemius SDK is wired.
     *
     * @return void
     */
    private function load_premium() {
        // The premium folder is physically absent from the free build, so its
        // presence is the real gate — checking it first means the free build can
        // never fatal on a missing class, whatever the conditions below say.
        if ( !class_exists( Premium\Loader::class ) ) {
            return;
        }
        // Development escape hatch: run the premium modules on a staging site
        // before the Freemius product exists. It requires editing wp-config.php,
        // and is meaningless in the free build (see the class check above).
        if ( defined( 'VANMUAD_DEV_PREMIUM' ) && VANMUAD_DEV_PREMIUM ) {
            self::$premium_active = true;
            new Premium\Loader();
            return;
        }
        if ( !function_exists( 'vanmuad_fs' ) ) {
            return;
        }
    }

}
