<?php
// Stop here if the API was already loaded.
if ( defined( 'FANCIFY_API' ) ) {
	return;
}
/**
 *
 * Load the API components.
 *
 * @since 1.0.0
 *
 * @package SplendorStudio\Framework\API
*/
class Fancify_Lite_Loader {
	
	/**
	 * instance variable
	 *
	 * @since    1.0.0
	 */
	private static $instance;

	function __construct() {
		// Load 
		$this->load();
		//Initialize API components support global.
		global $fancify_lite_api_components_support;

		if ( ! isset( $fancify_lite_api_components_support ) ) {
			$fancify_lite_api_components_support = array();
		}
	}

	/**
	 * Provides access to a single instance of a module using the singleton pattern
	 *
	 * @since    1.0.0
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		
		return self::$instance;
	}

	/**
	 * Declare some constant
	 *
	 * @since    1.0.0
	 */
	public function load() {
		// Declare FANCIFY API.
		define( 'FANCIFY_API', true );

		// Mode.
		if ( ! defined( 'SCRIPT_DEBUG' ) ) {
			define( 'SCRIPT_DEBUG', false ); // Valid use case as we need it defined.
		}

		// Assets.
		define( 'FANCIFY_MIN_CSS', SCRIPT_DEBUG ? '' : '.min' );
		define( 'FANCIFY_MIN_JS', SCRIPT_DEBUG ? '' : '.min' );

		// Path.
		if ( ! defined( 'FANCIFY_API_PATH' ) ) {
			define( 'FANCIFY_API_PATH', wp_normalize_path( trailingslashit( get_template_directory() ) ) . 'lib/api/' );
		}

		// Load dependencies here, as these are used further down.
		require_once FANCIFY_API_PATH . 'utilities/functions.php';// phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound -- valid usecase

		// Url.
		if ( ! defined( 'FANCIFY_API_URL' ) ) {
			define( 'FANCIFY_API_URL', get_template_directory_uri() . '/lib/api/' );
		}
	}

	/**
	 * Load FANCIFY API components.
	 *
	 * @since    1.0.0
	 * @return bool Will always return true.
	 */
	public static function fancify_lite_load_api_components( $components ) {
		static $loaded = array();

		$root 		= FANCIFY_API_PATH;
		$admin_root = FANCIFY_ADMIN_PATH;

		$common = array(
			'template_trait'=> $root . 'trait/template.php',
			'model'			=> $root . 'class-fancify-model.php',
			'controller'	=> $root . 'class-fancify-controller.php',
			'html'          => array(
				$root . 'html/functions.php',
				$root . 'html/class-fancify-attribute.php',
				$root . 'html/accessibility.php',
			),
			'actions'      => $root . 'actions/class-fancify-actions.php',
			'filters'      => $root . 'filters/class-fancify-filters.php',
			'image'        => $root . 'image/class-fancify-image.php',
			'layout'       => $root . 'layout/functions.php',
			'custom_field' => $root . 'custom-fields/class-fancify-acf.php',
			'template'     => $root . 'template/class-fancify-templates.php',
			'nav_menu'	   => $root . 'nav-menu/class-fancify-navmenu.php',
			'widget'       => array (
				$root . 'widget/functions.php',
			),
		);

		// Only load admin fragments if is_admin() is true.
		if ( is_admin() ) {
			$admin = array(
				'admin'     	=> $admin_root . 'admin.php',
				'custom_field'	=> $root . 'custom-fields/class-fancify-acf.php',
				'nav_menu'		=> $root . 'nav-menu/class-fancify-navmenu.php',
			);
		} else {
			$admin = array();
		}

		// Set dependencies.
		$dependencies = array(
			'html'    	 => array(
				'filters'
			),
			'model'   	 => array(
				'template_trait'
			),
			'controller' => array(
				'template_trait'
			),
		);

		foreach ( (array) $components as $component ) {

			// Stop here if the component is already loaded or doesn't exist.
			if ( in_array( $component, $loaded, true ) || ( ! isset( $common[ $component ] ) && ! isset( $admin[ $component ] ) ) ) {
				continue;
			}

			// Cache loaded component before calling dependencies.
			$loaded[] = $component;

			// Load dependencies.
			if ( array_key_exists( $component, $dependencies ) ) {
				self::fancify_lite_load_api_components( $dependencies[ $component ] );
			}

			$_components = array();

			// Add common components.
			if ( isset( $common[ $component ] ) ) {
				$_components = (array) $common[ $component ];
			}

			// Add admin components.
			if ( isset( $admin[ $component ] ) ) {
				$_components = array_merge( (array) $_components, (array) $admin[ $component ] );
			}

			// Load components.
			foreach ( $_components as $component_path ) {
				require_once $component_path;// phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound -- valid usecase
			}

			do_action( 'fancify_lite_loaded_api_component_' . $component );
		}

		return true;
	}

	/**
	 * Load the fragment file.
	 *
	 * This function can be short-circuited using the filter event "fancify_lite_pre_load_fragment_".
	 *
	 * @since 1.0.0
	 *
	 * @param string $fragment The fragment to load. This is its filename without the extension.
	 *
	 * @return bool True on success, false on failure.
	 */
	function fancify_lite_load_fragment_file($fragment) {
		/**
		 * Filter to allow the child theme or plugin to short-circuit this function by passing back a `true` or
		 * truthy value.
		 *
		 * The hook's name is "fancify_lite_pre_load_fragment_" + the fragment's filename (without its extension).  For example,
		 * the header fragment's hook name is "fancify_lite_pre_load_fragment_header".
		 *
		 * @since 1.0.0
		 *
		 * @param bool Set to `true` to short-circuit this function. The default is `false`.
		 */
		if (apply_filters('fancify_lite_pre_load_fragment_' . $fragment, false)) {
			return false;
		}

		// If fragment file does not exist, bail out.
		if (!file_exists(FANCIFY_FRAGMENTS_PATH . $fragment . '.php')) {
			return false;
		}

		require_once FANCIFY_FRAGMENTS_PATH . $fragment . '.php';// phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound -- valid usecase

		return true;
	}

	/**
	 * Register API component support.
	 *
	 * @since    1.0.0
	 * @return bool Will always return true.
	 */
	public static function fancify_lite_add_api_component_support( $feature ) {
		global $fancify_lite_api_components_support;

		$args = func_get_args();

		if ( 1 === func_num_args() ) {
			$args = true;
		} else {
			$args = array_slice( $args, 1 );
		}

		$fancify_lite_api_components_support[ $feature ] = $args;

		return true;
	}

	/**
	 * Gets the API component support argument(s).
	 *
	 * @since    1.0.0
	 * @return mixed The argument(s) passed.
	 */
	public static function fancify_lite_get_component_support( $feature ) {
		global $fancify_lite_api_components_support;

		if ( ! isset( $fancify_lite_api_components_support[ $feature ] ) ) {
			return false;
		}

		return $fancify_lite_api_components_support[ $feature ];
	}

	/**
	 * Remove API component support.
	 *
	 * @since    1.0.0
	 * @return bool Will always return true.
	 */
	public static function fancify_lite_remove_api_component_support( $feature ) {
		global $fancify_lite_api_components_support;
		unset( $fancify_lite_api_components_support[ $feature ] );
		return true;
	}

}