<?php
namespace SabaiApps\Directories\Component\Display\Controller\Admin;

use SabaiApps\Directories\Component\Display\Model\Display as DisplayModel;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Component\Form;
use SabaiApps\Directories\Component\System;
use SabaiApps\Directories\Component\Entity\Model\Bundle;

abstract class AbstractDisplays extends System\Controller\Admin\AbstractSettings {

	protected static $_jsForTab2Added = false;
	protected $_displayType           = 'entity', $_enableCSS = false, $_hideTabsIfSingle = true;

	abstract protected function _getDisplays( Context $context );

	protected function _getDisplay( Context $context, $displayName ) {
		return $this->Display_Display( $context->bundle->name, $displayName, $this->_displayType, true, true );
	}

	protected function _getSettingsForm( Context $context, array &$formStorage ) {
		$form = array(
			'#tabs'      => array(),
			'#tab_style' => 'pill_less_margin',
			'#displays'  => array(),
			'#token_id'  => 'display_admin_displays',
		);
		foreach ( $this->_getDisplays( $context ) as $display_name => $display_label ) {
			$this->_addDisplays( $context, $display_name, $display_label, $form );
		}
		if ( $this->_hideTabsIfSingle
			&& count( $form['#tabs'] ) <= 1
		) {
			$form['#tabs'] = array();
		}

		return $form;
	}

	protected function _addDisplays( Context $context, $name, $label, array &$form ) {
		if ( ! $display = $this->_getDisplay( $context, $name ) ) {
			return;
		}

		$form['#displays'][ $name ] = array( $display['name'] );
		$form['#tabs'][ $name ]     = array(
			'#title'  => $label,
			'#weight' => count( $form['#tabs'] ),
		);
		$form[ $name ]              = array(
			'#tree' => true,
			'#tab'  => $name,
		);
		$is_creatable               = $this->Display_Create_isCreatable( $context->bundle->type, $this->_displayType, $name );
		$this->_addDisplay( $context->bundle, $display, $form[ $name ], array( $name ), $is_creatable, true );
		if ( $is_creatable ) {
			$display_names = array();
			$displays      = $this->getModel( 'Display', 'Display' )
				->bundleName_is( $context->bundle->name )
				->type_is( $this->_displayType );
			if ( $this->_displayType === 'entity' ) {
				$displays->name_startsWith( $name . '-' );
			}
			foreach ( $displays->fetch() as $_display ) {
				if ( $_display->name === 'default' ) {
					continue;
				}

				$display_names[] = $_display->name;
			}

			$navs = array(
				'<a class="drts-content-tab ' . DRTS_BS_PREFIX . 'nav-link drts-display-tab2-link drts-display-tab2-link-default ' . DRTS_BS_PREFIX . 'active" data-bs-toggle="pill" href="#" data-bs-target="#drts-display-tab2-' . $name . '" title="' . $name . '">'
					. $this->H( __( 'Default', 'directories-pro' ) )
					. '</a>',
			);
			foreach ( $display_names as $display_name ) {
				if ( ( ! $display_name = trim( $display_name ) )
					|| ( ! $display = $this->_getDisplay( $context, $display_name ) )
				) {
					continue;
				}

				if ( isset( $display['label'] ) ) {
					$display_label = $display['label'];
				} else {
					$display_label = ( $pos = strpos( $display['name'], '-' ) ) ? substr( $display['name'], $pos + 1 ) : $display['name'];
				}
				$form['#displays'][ $name ][] = $display['name'];
				$this->_addDisplay( $context->bundle, $display, $form[ $name ], array( $name ), true, false );
				$navs[] = '<a class="drts-content-tab ' . DRTS_BS_PREFIX . 'nav-link drts-display-tab2-link" data-bs-toggle="pill" href="#" data-bs-target="#drts-display-tab2-' . $this->H( $display['name'] ) . '" data-display-type="' . $this->_displayType . '" data-display-name="' . $this->H( $display['name'] ) . '" title="' . $this->H( $display_label ) . '">'
					. $this->H( $display_label )
					. ' <i class="drts-display-delete-display fas fa-times-circle drts-clear ' . DRTS_BS_PREFIX . 'text-danger"></i></a>';
			}

			$add_display_title        = $this->H( $this->_getAddDisplayTitle() );
			$form[ $name ]['#prefix'] = '<div class="' . DRTS_BS_PREFIX . 'row">'
				. '<div class="' . DRTS_BS_PREFIX . 'col-sm-2">'
				. '<div class="' . DRTS_BS_PREFIX . 'nav ' . DRTS_BS_PREFIX . 'flex-sm-column ' . DRTS_BS_PREFIX . 'nav-pills" role="tablist">' . implode( PHP_EOL, $navs ) . '</div>'
				. '<div class="' . DRTS_BS_PREFIX . 'd-grid ' . DRTS_BS_PREFIX . 'gap-2">'
				. '<a class="' . DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-outline-primary ' . DRTS_BS_PREFIX . 'btn-sm ' . DRTS_BS_PREFIX . 'my-3 drts-display-add-display" title="' . $add_display_title . '" data-modal-title="' . $add_display_title . ( isset( $label ) ? ' - ' . $this->H( $label ) : '' ) . '" rel="sabaitooltip" data-display-type="' . $display['type'] . '" data-display-name="' . $name . '"><i class="fas fa-plus"></i></a>'
				. '</div></div>'
				. '<div class="' . DRTS_BS_PREFIX . 'col-sm-10"><div class="' . DRTS_BS_PREFIX . 'tab-content">';
			$form[ $name ]['#suffix'] = '</div></div></div>';

			if ( ! self::$_jsForTab2Added ) {
				self::$_jsForTab2Added = true;
				// Save current tab name as hidden value
				$form['#js_ready'][] = sprintf(
					'$(\'#__FORM_ID__ .drts-display-tab2-link\').on(\'shown.bs.tab\', function (event) {       
    $(\'#__FORM_ID__\').find(\'input.drts-form-current-tab2\').val(event.target.getAttribute(\'data-display-name\'));
});',
					DRTS_BS_PREFIX
				);
				if ( $tab = $context->getRequest()->asStr( '_drts_form_current_tab2' ) ) {
					$form['#js_ready'][] = 'bootstrap.Tab.getOrCreateInstance(\'#__FORM_ID__ .drts-display-tab2-link[data-display-name="' . $this->H( $tab ) . '"]\').show();';
				}
				$form['_drts_form_current_tab2'] = array(
					'#class'         => 'drts-form-current-tab2',
					'#type'          => 'hidden',
					'#default_value' => empty( $tab ) ? null : $tab,
				);
			}
		}
	}

	protected function _getSuccessUrlParams( Context $context ) {
		$params = parent::_getSuccessUrlParams( $context );
		// Pass current selected tab if any
		if ( $tab = $context->getRequest()->asStr( '_drts_form_current_tab2' ) ) {
			$params['_drts_form_current_tab2'] = $tab;
		}
		return $params;
	}

	protected function _getAddDisplayTitle() {
		return __( 'Add Display', 'directories-pro' );
	}

	protected function _addDisplay( Bundle $bundle, $display, array &$form, array $parents = array(), $addPrefixSuffix = false, $active = false, $configureInline = false ) {
		$form[ $display['name'] ] = array(
			'elements' => array(
				'#type'                => 'display_elements',
				'#display'             => $display,
				'#clear_display_cache' => false,
				'#configure_inline'    => $configureInline,
				'#weight'              => 1,
				'#class'               => DRTS_BS_PREFIX . 'mb-4',
			),
		);
		if ( $addPrefixSuffix ) {
			$form[ $display['name'] ]['_prefix'] = array(
				'#type'   => 'markup',
				'#markup' => '<div id="drts-display-tab2-' . $display['name'] . '" class="' . DRTS_BS_PREFIX . 'tab-pane ' . DRTS_BS_PREFIX . 'fade ' . DRTS_BS_PREFIX . 'show ' . ( $active ? DRTS_BS_PREFIX . 'active' : '' ) . '">',
				'#weight' => -1,
			);
			$form[ $display['name'] ]['_suffix'] = array(
				'#type'   => 'markup',
				'#markup' => '</div>',
				'#weight' => 99999,
			);
		}
		if ( $this->_enableCSS ) {
			$form[ $display['name'] ]['css'] = array(
				'#title'                 => __( 'Custom CSS', 'directories-pro' ),
				'#description'           => sprintf(
					$this->H( __( 'Enter custom CSS for the display above. You can use %s to target the display with a CSS class.', 'directories-pro' ) ),
					'<code class="' . DRTS_BS_PREFIX . 'user-select-all">.' . DisplayModel::cssClass( $display['name'], $display['type'] ) . '</code>'
				),
				'#description_no_escape' => true,
				'#type'                  => 'editor',
				'#language'              => 'css',
				'#default_value'         => $display['css'],
				'#weight'                => 10,
				'#horizontal'            => true,
			);
		}
		$parents[]                = $display['name'];
		$form[ $display['name'] ] = $this->Filter( 'display_admin_elements_form', $form[ $display['name'] ], array( $bundle, $display, $parents ) );
	}

	protected function _saveConfig( Context $context, array $config, Form\Form $form ) {
		foreach ( array_keys( $form->settings['#displays'] ) as $default_display_name ) {
			$displays = $this->getModel( 'Display', 'Display' )
				->bundleName_is( $context->bundle->name )
				->type_is( $this->_displayType )
				->name_in( $form->settings['#displays'][ $default_display_name ] )
				->fetch();
			foreach ( $displays as $display ) {
				$data_keys = $this->_getDisplayDataKeys( $context->bundle, $display );
				$data      = $display->data ?: array();
				foreach ( $data_keys as $data_key ) {
					if ( isset( $config[ $default_display_name ][ $display->name ][ $data_key ] ) ) {
						$data[ $data_key ] = $config[ $default_display_name ][ $display->name ][ $data_key ];
					} else {
						unset( $data[ $data_key ] );
					}
				}

				$display->data = $data;
				// Clear display cache
				$this->Display_Display_clearCache( $context->bundle->name, $this->_displayType, $display->name );
			}
		}
		$this->getModel( null, 'Display' )->commit();

		// Clear elements cache
		$this->getPlatform()->deleteCache( 'display_elements_' . $context->bundle->name );
	}

	protected function _getDisplayDataKeys( Bundle $bundle, DisplayModel $display ) {
		$keys = $this->Filter( 'display_admin_display_data_keys', array(), array( $bundle, $display ) );
		if ( $this->_enableCSS ) {
			$keys[] = 'css';
		}
		return $keys;
	}
}
