<?php
/**
 * Main class that initializes this plugin.
 */

namespace BoostsiteAIContentGenerator;

/**
 * Main class.
 *
 * @class Main The class that holds initialize this plugin
 */
final class Main {

	/**
	 * A unique plugin prefix/token to use throughout your plugin.
	 * This is also your application domain.
	 *
	 * @var string
	 */
	public const PREFIX = 'boostsite_ai_content_generator';

	/**
	 * Holds various class instances.
	 *
	 * @var array
	 * @since   1.0.0
	 */
	private $container = array();

	/**
	 * The single instance of Main.
	 *
	 * @var     object
	 * @since   1.0.0
	 */
    private static $_instance = null; //phpcs:ignore

	/**
	 * The version number.
	 *
	 * @var     string
	 * @since   1.0.0
	 */
	public $version;

	/**
	 * The plugin filename.
	 *
	 * @var string
	 */
	public static $plugin_file = '';

	/**
	 * The base url, default '.'.
	 *
	 * @var string
	 */
	public static $base_url = '.';

	/**
	 * The plugin dir, default to empty string.
	 *
	 * @var string
	 */
	public static $plugin_dir = '';

	/**
	 * Constructor for the Main class.
	 *
	 * Sets up all the appropriate hooks and actions
	 * within our plugin.
	 *
	 * @param string $filepath the plugin file path.
	 * @param string $version Plugin version.
	 */
	private function __construct( $filepath, $version = '1.0.0' ) {
		self::$plugin_file = $filepath;
		self::$plugin_dir  = dirname( $filepath );
		$this->version     = $version;
	}

	/**
	 * Get a singleton instance of this plugin.
	 *
	 * Usage: Main::get_instance()
	 *
	 * @param string $filepath the plugin file path.
	 * @param string $version Plugin version.
	 *
	 * @return Main the singleton instance
	 */
	public static function get_instance( $filepath, $version = '1.0.0' ) {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self( $filepath, $version );
		}

		return self::$_instance;
	}

	/**
	 * Do stuff during plugin uninstall.
	 */
	public static function uninstall_plugin() {
		flush_rewrite_rules();

		( new \BoostsiteAIContentGenerator\Migrations() )->clean_up( self::PREFIX );
	}

	/**
	 * Activate and initialize the plugin.
	 */
	public function run() {
		// set base url from plugin file name.
		self::$base_url = plugins_url( '', self::$plugin_file );

		register_activation_hook( self::$plugin_file, array( $this, 'activate_plugin' ) );
		register_deactivation_hook( self::$plugin_file, array( $this, 'deactivate_plugin' ) );
		register_uninstall_hook( self::$plugin_file, array( __CLASS__, 'uninstall_plugin' ) );

		add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );

		// setup cli.
		if ( defined( 'WP_CLI' ) && \WP_CLI ) {
			$this->container['cli'] = new \BoostsiteAIContentGenerator\CliLoader( self::PREFIX );
		}

		// this is to register an action link from the Plugin manager page to our settings page.
		$plugin = plugin_basename( self::$plugin_file );
		add_filter( "plugin_action_links_$plugin", array( $this, 'register_settings_link' ) );

		// Additional thing you can do: register post type, taxonomy, etc...
		return $this;
	}

	/**
	 * Magic getter to bypass referencing plugin.
	 *
	 * @param mixed $prop Prop.
	 *
	 * @return mixed
	 */
	public function __get( $prop ) {
		if ( array_key_exists( $prop, $this->container ) ) {
			return $this->container[ $prop ];
		}

		return $this->{$prop};
	}

	/**
	 * Magic isset to bypass referencing plugin.
	 *
	 * @param mixed $prop Prop.
	 *
	 * @return mixed
	 */
	public function __isset( $prop ) {
		return isset( $this->{$prop} ) || isset( $this->container[ $prop ] );
	}

	/**
	 * Register hooks after all plugins are loaded.
	 *
	 * @return void
	 */
	public function plugins_loaded() {
		add_action( 'init', array( $this, 'init_hook_handler' ) );
	}

	/**
	 * Plugin activation function.
	 */
	public function activate_plugin() {
		( new \BoostsiteAIContentGenerator\Migrations() )->run( self::PREFIX, $this->version );

		// set the current version to activate plugin.
		update_option( self::PREFIX . '_version', $this->version );
	}

	/**
	 * Do stuff during plugin deactivation.
	 */
	public function deactivate_plugin() {
		flush_rewrite_rules();

		// do stuff such as: shut off cron tasks, etc...

		// remove version number to deactivate plugin.
		delete_option( self::PREFIX . '_version' );
	}

	/**
	 * Register settings link that display on the plugins listing page.
	 *
	 * @param  array $links Links.
	 * @return array
	 */
	public function register_settings_link( $links ) {
		$settings_link  = '<a href="admin.php?page=' . self::PREFIX . '#/settings">';
		$settings_link .= esc_html( __( 'Settings', 'boostsite-ai-content-generator' ) ) . '</a>';
		array_unshift( $links, $settings_link );

		return $links;
	}

	/**
	 * Handler for init_hook.
	 *
	 * @return void
	 */
	public function init_hook_handler() {
		// initialize assets.
		$this->container['assets'] = new \BoostsiteAIContentGenerator\Assets( self::PREFIX );

		// initialize the various loader classes.
		if ( $this->is_request( 'admin' ) ) {
			$ctx                      = new \BoostsiteAIContentGenerator\AdminLoader( self::PREFIX );
			$this->container['admin'] = $ctx;
		}

		// initialize hooks and actions.
		$this->container['hooks_and_actions'] = new \BoostsiteAIContentGenerator\HooksAndActions( self::PREFIX );

		// finally load api routes.
		$this->container['api'] = new \BoostsiteAIContentGenerator\ApiRoutes( self::PREFIX );
	}

	/**
	 * What type of request is this?
	 *
	 * @param  string $type admin, ajax, cron or frontend.
	 *
	 * @return bool
	 */
	private function is_request( $type ) {
		switch ( $type ) {
			case 'admin':
				return is_admin();

			case 'ajax':
				return defined( 'DOING_AJAX' );

			case 'rest':
				return defined( 'REST_REQUEST' );

			case 'cron':
				return defined( 'DOING_CRON' );

			case 'frontend':
				return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
		}
	}

	/**
	 * Cloning is forbidden.
	 *
	 * @since 1.0.0
	 */
	public function __clone() {
		_doing_it_wrong( __FUNCTION__, esc_html( __( 'Cloning of Main is forbidden', 'boostsite-ai-content-generator' ) ), esc_attr( $this->version ) );
	} // End __clone ()

	/**
	 * Unserializing instances of this class is forbidden.
	 *
	 * @since 1.0.0
	 */
	public function __wakeup() {
		_doing_it_wrong( __FUNCTION__, esc_html( __( 'Unserializing instances of Main is forbidden', 'boostsite-ai-content-generator' ) ), esc_attr( $this->version ) );
	} // End __wakeup ()
}
