<?php

namespace Hecate\Components;


use Hecate\Components\Button\ButtonComponent;
use Hecate\Components\Heading\HeadingComponent;
use Hecate\Components\Text\TextComponent;
use Hecate\Lodash;
use Hecate\Components\Footer\FooterComponent;
use Hecate\Components\Section\SectionComponent;
use Hecate\Components\Hero\HeroComponent;
use Hecate\Components\Navigation\NavigationComponent;
use Hecate\Components\Header\HeaderComponent;
use Hecate\Components\Logo\LogoComponent;
use Hecate\Components\Menu\MenuComponent;
use Hecate\Components\Shortcode\ShortcodeComponent;
use Hecate\Components\Row\RowComponent;
use Hecate\Components\Column\ColumnComponent;

use Hecate\Customizer\CustomizerManager;
use Hecate\PageRender;


class ComponentsRepository {


	private static $instance         = null;
	private $componentsById          = array();
	private static $activeComponent  = null;
	private $componentSettings       = array();
	private $componentsClassesByType = array();
	private $cachedComponents        = array();
	private $rootComponents          = array();


    private function __construct() {
        self::$instance                = $this;
        $this->componentsClassesByType = static::getComponentsClasses();
        //add_action('init', array($this, 'boot'));
        $this->boot();
    }

	private static function getComponentsClasses() {
		$components       = array(
			FooterComponent::class,
            SectionComponent::class,
			HeroComponent::class,
			HeaderComponent::class,
			RowComponent::class,
			ColumnComponent::class,
			NavigationComponent::class,
			LogoComponent::class,
			MenuComponent::class,
			TextComponent::class,
            HeadingComponent::class,
            ShortcodeComponent::class,
			ButtonComponent::class,
		);
		$componentsByType = array();
		foreach ( $components as $componentClass ) {
			$componentsByType[ $componentClass::$type ] = $componentClass;
		}

		return $componentsByType;
	}

	public function getComponentClassByType( $type ) {
		return Lodash::get( $this->componentsClassesByType, $type );
	}

    public function getComponentsTypes() {
        return array_keys($this->componentsClassesByType);
    }



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

		return self::$instance;
	}


	public function boot() {

		$this->initRootComponentsByPageType();
		$this->initComponents();

		//	add_action( 'customize_register', array( $this, 'initCustomSettings' ), 20, 1 );

		if ( is_customize_preview() ) {
			$this->registerWordpressSettings();
		}

		return $this;
	}

	//  public function bootCustomizerSettings() {
	//      //$this->loadComponentMapping();
	//  }

	//  public function loadComponentMapping() {
	//      $fileName = hecate_dir( 'settings.json' );
	//      if ( file_exists( $fileName ) ) {
	//          $mapping                = file_get_contents( $fileName );
	//          $this->componentMapping = json_decode( $mapping, true );
	//      }
	//  }

	public function getRootComponents() {
		return $this->rootComponents;
	}

	public function initRootComponentsByPageType() {

		$rootComponents = array( PageRender::getHeaderComponentId(), PageRender::getFooterComponentId());

		$this->rootComponents = $rootComponents;

	}
	/**
	 * Get used components in current page type. This is needed for settings registration.
	 *
	 * @return array
	 */
	public function getUsedComponents() {
		$components = array();
		foreach ( $this->rootComponents as $rootComponentId ) {
			$childrenComponents = $this->getUsedComponentsFromRoot( $rootComponentId );
			$components         = array_merge( $components, $childrenComponents );
		}

		return $components;
	}

	public function getUsedComponentsFromRoot( $componentId ) {
		$components    = array();
		$componentName = ComponentMods::getComponentName( $componentId );
		$childrenIds   = ComponentMods::getChildrenIds( $componentId );

		$data = array(
			'id'        => $componentId,
			'component' => $componentName,
		);

		$components[] = $data;
		foreach ( $childrenIds as $childId ) {
			$childrenComponents = $this->getUsedComponentsFromRoot( $childId );
			$components         = array_merge( $components, $childrenComponents );
		}

		return $components;
	}

	//used to initiate the components used to register the settings
	public function initComponents() {
		$usedComponents = $this->getUsedComponents();
		foreach ( $usedComponents as $data ) {
			$id                          = Lodash::get( $data, 'id' );
			$this->componentsById[ $id ] = $this->generateComponentClassFromData( $data );
		}

	}

	public function registerWordpressSettings() {
		$this->registerPanels();

		foreach ( $this->componentsById as $component ) {
			$this->registerSections( $component->getSections() );
			$this->registerControlsAndSettings( $component );
		}

	}


	public function generateComponentClassFromData( $data ) {

		$componentId = Lodash::get( $data, 'id' );
		if ( isset( $this->componentsById[ $componentId ] ) ) {
			return $this->componentsById[ $componentId ];
		}
		$componentType  = Lodash::get( $data, 'component' );
		$componentClass = Lodash::get( $this->componentsClassesByType, $componentType );
		$data           = array(
			'componentId' => $componentId,
		);
		//        if(!class_exists ($componentClass)) {
		//            return null;
		//        }
		$component = new $componentClass( $data );
		return $component;
	}


//
//	public function initCustomSettings( $wp_customize ) {
//		$logoComponent    = null;
//		$componentClasses = self::getComponentsClasses();
//
//		foreach ( $this->componentMapping as $data ) {
//			if ( $data['component'] === $componentClasses['logo'] ) {
//				$logoComponent = $this->generateComponentClassFromData( $data );
//			}
//		}
//		if ( ! $logoComponent ) {
//			return;
//		}
//		$wp_customize->selective_refresh->add_partial(
//			'custom_logo',
//			array(
//				'selector'         => $logoComponent->getPartialRefreshSelector(),
//				'render_callback'  => array( $logoComponent, 'getPartialRefreshContent' ),
//				'fallback_refresh' => false,
//				// Prevents refresh loop when document does not contain .cta-wrap selector. This should be fixed in WP 4.7.
//			)
//		);
//	}

	public static function setActiveComponent( $component ) {
		static::$activeComponent = $component;
	}

	public static function getActiveComponent() {
		return static::$activeComponent;
	}

	public static function render( $componentId, $componentType = null ) {
		$component = self::getComponent( $componentId, $componentType );
		if ( ! ! $component ) {
			return $component->render();
		}
	}

	public static function getComponent( $componentId, $componentType = null ) {
		$instance  = static::getInstance();
		$component = Lodash::get( $instance->componentsById, $componentId );
		if ( ! ! $component ) {
			return $component;
		}
		if ( ! $componentType ) {
			return null;
		}
		$componentClasses = self::getComponentsClasses();

		$componentClass = Lodash::get( $componentClasses, $componentType );
		$data           = array(
			'componentId' => $componentId,
		);
		if ( ! class_exists( $componentClass ) ) {
			return null;
		}

		$newComponent = new $componentClass( $data );
		Lodash::set( $instance->componentsById, $componentId, $newComponent );
		return $newComponent;
	}

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


	private function registerControlsAndSettings( $component ) {
		$controls = $component->getControls();

		foreach ( $controls as $control ) {

			CustomizerManager::addControl( $control );

		}
	}


	public function registerSections( $sections ) {

		foreach ( $sections as $section ) {
			CustomizerManager::addSection( $section );
		}
	}




	public function getPanels() {
		return array(
			array(
				'id'          => 'navigation',
				'title'       => __( 'Navigation', 'hecate' ),
				'description' => __( 'Navigation section', 'hecate' ),
				'priority'    => 1,
			),
			array(
				'id'          => 'hero',
				'title'       => __( 'Hero', 'hecate' ),
				'description' => __( 'Hero section', 'hecate' ),
				'priority'    => 2,
			),
			array(
				'id'          => 'footer',
				'title'       => __( 'Footer', 'hecate' ),
				'description' => __( 'Footer section', 'hecate' ),
				'priority'    => 3,
			),
		);
	}

	public function registerPanels() {
		$panels = $this->getPanels();
		foreach ( $panels as $panel ) {
			CustomizerManager::addPanel( $panel );
		}
	}


}
