<?php

namespace Hecate\Customizer;


use Hecate\Customizer\Repositories\PanelsRepository;
use Hecate\Customizer\Repositories\SectionsRepository;
use Hecate\Customizer\Repositories\ControlsRepository;
use Hecate\Controls\Components\BaseControl;

use Hecate\Lodash;

/**
 * The CustomizerManager class is used to register  custom panels, sections and control and to load them inside
 * the customizer.
 * There is file containing all the components used in the project, we load all the components in order and get
 * the controls, sections and panels used inside them.
 *
 *
 */
class CustomizerManager {

	private static $instance = null;


	/**
	 * @var string[] List of panels options
	 */
	public $panels = array();

	/**
	 * @var string[] List of section options
	 */
	public $sections = array();

	/**
	 * @var BaseControl[] List of controls objects
	 */
	public $controls = array();


	private function __construct() {
		add_action( 'customize_register', array( $this, 'registerCustomizeSettings' ), 10, 1 );

		DynamicComponentsTemplate::init();
	}


	/**
	 * @param $wp_customize
	 */
	public function registerCustomizeSettings( $wp_customize ) {
		PanelsRepository::registerTypes( $wp_customize );
		SectionsRepository::registerTypes( $wp_customize );
		ControlsRepository::registerTypes( $wp_customize );

		$this->registerPanels( $wp_customize );
		$this->registerSections( $wp_customize );
		$this->registerControlsAndSettings( $wp_customize, $this->controls );
		$this->addPartialRefreshToControls( $wp_customize );
	}

	/**
	 * Searches the panel type in the Custom panels repository from PanelsRepository, or use the default WordPress class
	 *
	 * @param string $type
	 * @return string
	 */
	public static function gePanelClassByType( $type = 'default' ) {

		$classesByType = PanelsRepository::getMergedClassesByType();
		return Lodash::get( $classesByType, $type, PanelsRepository::$defaultClass );
	}
	/**
	 * Searches the section type in the Custom sections repository from SectionsRepository, or use the default WordPress class
	 *
	 * @param string $type
	 * @return string
	 */
	public static function getSectionClassByType( $type = 'default' ) {

		$classesByType = SectionsRepository::getMergedClassesByType();
		return Lodash::get( $classesByType, $type, SectionsRepository::$defaultClass );
	}

	/**
	 * Searches the control type in the Custom controls repository from ControlsRepository, or use the default WordPress class
	 *
	 * @param string $type
	 * @return string
	 */
	public static function getControlClassByType( $type = 'default' ) {
		$classesByType = ControlsRepository::getMergedClassesByType();
		return Lodash::get( $classesByType, $type, ControlsRepository::$defaultClass );
	}


	/**
	 * @param $section string[]
	 */
	public static function addSection( $section ) {
		static::getInstance()->sections[] = $section;
	}

	/**
	 * @param $panel string[]
	 */
	public static function addPanel( $panel ) {
		static::getInstance()->panels[] = $panel;
	}

	/**
	 * @param $control BaseControl[]
	 */
	public static function addControl( $control ) {
		static::getInstance()->controls[] = $control;
	}

	/**
	 * Adds panels to WordPress
	 *
	 * @param $wp_customize
	 */
	public function registerPanels( $wp_customize ) {
		$panels = $this->panels;
		foreach ( $panels as $panel ) {
			$type     = Lodash::get( $panel, 'type' );
			$class    = CustomizerManager::gePanelClassByType( $type );
			$panelObj = new $class( $wp_customize, $panel['id'], $panel );
			$wp_customize->add_panel( $panelObj );
		}
	}

	/**
	 * Adds sections to WordPress
	 *
	 * @param $wp_customize
	 */
	public function registerSections( $wp_customize ) {
		$sections = $this->sections;
		foreach ( $sections as $section ) {
			$type         = Lodash::get( $section, 'type' );
			$sectionClass = CustomizerManager::getSectionClassByType( $type );
			$sectionObj   = new $sectionClass( $wp_customize, $section['id'], $section );
			$wp_customize->add_section( $sectionObj );
		}
	}

	/**
	 * Adds settings and controls to WordPress
	 *
	 * @param $wp_customize
	 */
	public function registerControlsAndSettings( $wp_customize, $controls ) {
		foreach ( $controls as $control ) {

			$settingOptions = $control->getWordpressSettingParams();

			$wp_customize->add_setting(
				$control->settingId,
				array(
					'type'              => $settingOptions['type'],
					'sanitize_callback' => $settingOptions['sanitize_callback'],
					'transport'         => $settingOptions['transport'],
					'default'           => $settingOptions['default'],
				)
			);

			$type            = $control->type;
			$controlClass    = CustomizerManager::getControlClassByType( $type );
			$controlSettings = $control->getWordpressControlSettings();
			$sectionObj      = new $controlClass( $wp_customize, $control->settingId, $controlSettings );
			$wp_customize->add_control( $sectionObj );

		}
	}

	/**
	 * Adds partial refresh to the controls so the page doesn't need to refresh when a setting change
	 *
	 * @param $wp_customize
	 */
	public function addPartialRefreshToControls( $wp_customize ) {
		$controls           = $this->controls;
		$partialRefreshData = BaseControl::getWordpressPartialParams( $controls );

		foreach ( $partialRefreshData as $item ) {
			$setting = $item['settings'][0];
			$wp_customize->selective_refresh->add_partial( $setting, $item );
		}
	}




	public static function getInstance() {
		if ( ! self::$instance ) {
			self::$instance = new static();
		}

		return self::$instance;
	}

	public static function init() {
		self::getInstance();
	}
}
