<?php
/**
 * BitForgeNet Guest Tickets - Plugin container and bootstrap.
 *
 * @package BitForgeNet_Guest_Tickets
 * @since   1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Main plugin singleton.
 */
final class BFNET_Plugin {

	/**
	 * Singleton instance.
	 *
	 * @var BFNET_Plugin|null
	 */
	private static $instance = null;

	/**
	 * Instantiated service objects.
	 *
	 * @var array
	 */
	private $services = array();

	/**
	 * Retrieve the singleton.
	 *
	 * @return BFNET_Plugin
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
			self::$instance->init();
		}
		return self::$instance;
	}

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

	/**
	 * Prevent cloning.
	 *
	 * @return void
	 */
	private function __clone() {}

	/**
	 * Prevent unserialising.
	 *
	 * @throws Exception Always.
	 * @return void
	 */
	public function __wakeup() {
		throw new Exception( 'BFNET_Plugin cannot be unserialised.' );
	}

	/**
	 * Wire everything up.
	 *
	 * @return void
	 */
	private function init() {
		add_action( 'init', array( $this, 'load_textdomain' ), 1 );
		add_action( 'admin_init', array( 'BFNET_Install', 'maybe_upgrade' ) );

		$this->services['security']   = new BFNET_Security();
		$this->services['shortcodes'] = new BFNET_Shortcodes();
		// The door station answers before anything else, straight off REQUEST_URI.
		$this->services['door']       = new BFNET_Door();
		$this->services['rest']       = new BFNET_Rest();
		$this->services['cron']       = new BFNET_Cron();

		if ( is_admin() ) {
			$this->services['admin'] = new BFNET_Admin();
		}

		$this->services['public'] = new BFNET_Frontend();

		add_action( 'bfnet_order_marked_paid', array( 'BFNET_Fulfilment', 'on_order_paid' ), 10, 2 );

		// A page that gains or loses the booking shortcode changes where direct links go.
		add_action( 'save_post_page', array( 'BFNET_Util', 'flush_page_cache' ) );
		add_action( 'save_post_post', array( 'BFNET_Util', 'flush_page_cache' ) );
		add_action( 'deleted_post', array( 'BFNET_Util', 'flush_page_cache' ) );

		do_action( 'bfnet_loaded', $this );
	}

	/**
	 * Load translations.
	 *
	 * @return void
	 */
	public function load_textdomain() {
		// Nothing to do. WordPress has loaded translations for the plugins it
		// hosts since 4.6, and asking for them again here would only have it
		// repeat work it has already done.
	}

	/**
	 * Fetch a registered service.
	 *
	 * @param string $key Service key.
	 * @return object|null
	 */
	public function get( $key ) {
		return isset( $this->services[ $key ] ) ? $this->services[ $key ] : null;
	}
}
