<?php
/**
 * Module Service Provider File
 *
 * @category   ServiceProvider
 * @package    CodexShaper_Framework
 * @author     CodexShaper <info@codexshaper.com>
 * @license    https://www.gnu.org/licenses/gpl-2.0.html
 * @link       https://codexshaper.com
 * @since      1.0.0
 */

namespace CodexShaper\Framework\Providers\Elementor;

use Elementor\Plugin;
use CodexShaper\Framework\Base\BaseModule;
use CodexShaper\Framework\Foundation\ServiceProvider;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 *  Module Service Provider Class
 *
 * @category   Class
 * @package    CodexShaper_Framework
 * @author     CodexShaper <info@codexshaper.com>
 * @license    https://www.gnu.org/licenses/gpl-2.0.html
 * @link       https://codexshaper.com
 * @since      1.0.0
 */
class ModuleServiceProvider extends ServiceProvider {
	/**
	 * @var BaseModule[]
	 */
	private $modules = array();

	/**
	 * Constructor
	 *
	 * Perform some compatibility checks to make sure basic requirements are meet.
	 * If all compatibility checks pass, initialize the functionality.
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @return void
	 */
	public function register() {
		$option_name = csmf_config( 'options.module.option_name' ) ?? 'csmf_module_settings';
		$modules     = get_option( $option_name ) ?? array();

		if ( false === $modules || ! is_array( $modules ) || empty( $modules ) ) {
			$modules = csmf_elementor_modules( CSMF_PATH . 'widgets/elementor/modules/' );
		}

		/**
		 * Elementor modules.
		 *
		 * @param array $modules Elementor modules.
		 */
		$modules = apply_filters( 'csmf/elementor/modules', $modules );

		foreach ( $modules as $module_name => $module_data ) {
			$module_class = $module_data['class'] ?? null;
			if ( ! $module_class ) {
				$words            = str_replace( '-', ' ', $module_name );
				$module_name      = str_replace( ' ', '', ucwords( $words ) );
				$module_namespace = $module_data['namespace'] ?? '\CodexShaper\Framework\Widgets\Elementor\Modules';
				$module_class     = "{$module_namespace}\\{$module_name}\\Module";
			}

			if ( ! class_exists( $module_class ) ) {
				continue;
			}

			/** @var BaseModule $module_class */
			$experimental_data = $module_class::get_experimental_data();

			if ( $experimental_data ) {
				Plugin::instance()->experiments->add_feature( $experimental_data );

				if ( ! Plugin::instance()->experiments->is_feature_active( $experimental_data['name'] ) ) {
					continue;
				}
			}

			$is_active = $module_data['is_active'] ?? $module_class::is_active() ?? false;

			if ( $is_active ) {
				$this->modules[ $module_name ] = $module_class::instance();
			}
		}
	}

	/**
	 * Get modules
	 *
	 * @since 1.0.0
	 * @access public
	 *
	 * @param string|null $module_name The module name.
	 *
	 * @return BaseModule|BaseModule[]
	 */
	public function get_modules( $module_name = null ) {
		if ( $module_name ) {
			if ( isset( $this->modules[ $module_name ] ) ) {
				return $this->modules[ $module_name ];
			}

			return null;
		}

		return $this->modules;
	}
}
