<?php

namespace WpieFw\Modules;

use WpieFw\Modules\Iterator\WpieModulesCollection;
use WpieFw\Wpie\WpieGlobals;

if( ! defined( 'ABSPATH' ) ) exit;

final class WpieModuleProcessor
{
	/**
	 * @var WpieGlobals
	 */
	private $globals;

	/**
	 * @var \WpieFw\Settings\WpieSettingsProcessor
	 */
	private $settingsProcessor;

	/**
	 * @var WpieModulesCollection
	 */
	private $collection;

	/**
	 * Array of WpieModulesCollection instances
	 *
	 * Indexed by plugin namespace
	 *
	 * @var array
	 */
	public static $modules;

	/**
	 * Constructor
	 *
	 * @param WpieModulesCollection $collection
	 * @param WpieGlobals $globals
	 */
	public function __construct( WpieModulesCollection $collection, WpieGlobals $globals )
	{
		// Store Plugin globals
		$this->globals = $globals;
		// Store the modules collection
		$this->collection = $collection;
		$this->setCollection( $this->globals->nameSpace, $collection );
	}

	/**
	 * Add Module collection
	 *
	 * @param string $nameSpace
	 * @param WpieModulesCollection $collection
	 */
	public static function setCollection( string $nameSpace, WpieModulesCollection $collection )
	{
		self::$modules[$nameSpace] = $collection;
	}

	/**
	 * Get Module collection
	 *
	 * @param string $nameSpace
	 */
	public static function getCollection( $nameSpace = '' )
	{
		if( isset( self::$modules[$nameSpace] ) ) {
			return self::$modules[$nameSpace];
		} else {
			return false;
		}
	}

	/**
	 * Get Module collection
	 *
	 * @param string $nameSpace
	 * @param string $key
	 *
	 * @uses self::getCollection()
	 * @uses WpieModulesCollection::get()
	 *
	 * @return \WpieFw\Modules\Iterator\WpieModule |boolean
	 */
	public static function getModule( $nameSpace = '', $key = '' )
	{
		$collection = self::getCollection( $nameSpace );

		if( false !== $collection && $collection->offsetExists( $key ) ) {
			return $collection->get( $key );
		} else {
			return false;
		}
	}

	/**
	 *
	 */
	public function init()
	{
		// @todo: sort modules based on priority so that start() method is called according to this prio

		// Loop over all Modules to hook them all
		foreach ( $this->collection as $module ) {
			/**
			 * Let others hook before calling the start method
			 *
			 * @param boolean $isActivating
			 */
			do_action( $this->globals->nameSpace . '_module_before_start', $this->globals->get( 'isActivating' ) );

			// Call start method
			$module->start();

			/**
			 * Let others hook after calling the start method
			 *
			 * @param boolean $active
			 */
			do_action( $this->globals->nameSpace . '_module_after_start', $module->getActive() );

			if( false === $module->getActive() ) {
				continue;
			}

			if( $this->globals->get( 'isActivating' ) ) {
				add_action( $this->globals->nameSpace . '_module_init_activate', [ $module, 'activating' ], $module->getPriority() );
			}

			add_action( $this->globals->nameSpace . '_module_init', [ $module, 'init' ], $module->getPriority() );
		}

		// clear mem for $module param
		unset( $module );
	}

	/**
	 * Hook the modules into the plugin
	 *
	 * @since 0.1
	 */
	public function hook()
	{
		if( $this->globals->get( 'isActivating' ) ) {
			/**
			 * @todo description for hook {$nameSpace}_module_init_activate
			 */
			do_action( $this->globals->nameSpace . '_module_init_activate' );
		}

		/**
		 * @todo description for hook {$nameSpace}_module_init
		 */
		do_action( $this->globals->nameSpace . '_module_init' );

		// remove all attached action to ensure the callbacks are only called ones
		remove_all_actions( $this->globals->nameSpace . '_module_init' );
	}
}