<?php
namespace SabaiApps\Directories\Component\View\FieldFilter;

use SabaiApps\Directories\Component\Field;
use SabaiApps\Directories\Component\Entity;

class GlossaryFieldFilter extends Field\Filter\AbstractFilter {

	protected function _fieldFilterInfo() {
		return array(
			'field_types'      => array( 'entity_title', 'string' ),
			'label'            => __( 'A to Z', 'directories-pro' ),
			'default_settings' => array(
				'type'       => 'buttons',
				'columns'    => 3,
				'btn_size'   => 'sm',
				'btn_color'  => 'outline-primary',
				'hide_empty' => false,
				'hide_count' => false,
			),
			'facetable'        => true,
		);
	}

	public function fieldFilterSettingsForm( Field\IField $field, array $settings, array $parents = array() ) {
		return array(
			'type'       => array(
				'#type'          => 'select',
				'#title'         => __( 'Form field type', 'directories-pro' ),
				'#options'       => array(
					'buttons' => __( 'Buttons', 'directories-pro' ),
					'select'  => __( 'Select list', 'directories-pro' ),
					'radios'  => __( 'Radio buttons', 'directories-pro' ),
				),
				'#default_value' => $settings['type'],
				'#weight'        => 4,
			),
			'columns'    => array(
				'#type'          => 'select',
				'#title'         => __( 'Number of columns', 'directories-pro' ),
				'#options'       => array(
					1  => 1,
					2  => 2,
					3  => 3,
					4  => 4,
					6  => 6,
					12 => 12,
				),
				'#default_value' => $settings['columns'],
				'#states'        => array(
					'visible' => array(
						sprintf( '[name="%s"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( 'type' ) ) ) ) => array( 'value' => 'radios' ),
					),
				),
				'#weight'        => 5,
			),
			'btn_size'   => array(
				'#type'          => 'select',
				'#title'         => __( 'Button size', 'directories-pro' ),
				'#options'       => array(
					'sm' => __( 'Small', 'directories-pro' ),
					'md' => __( 'Medium', 'directories-pro' ),
					'lg' => __( 'Large', 'directories-pro' ),
				),
				'#default_value' => $settings['btn_size'],
				'#states'        => array(
					'visible' => array(
						sprintf( '[name="%s"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( 'type' ) ) ) ) => array( 'value' => 'buttons' ),
					),
				),
				'#weight'        => 6,
			),
			'btn_color'  => array(
				'#type'             => 'radios',
				'#title'            => __( 'Button color', 'directories-pro' ),
				'#options'          => $this->_application->System_Color_options( array( 'as_buttons' => true ) ),
				'#option_no_escape' => true,
				'#columns'          => 6,
				'#default_value'    => $settings['btn_color'],
				'#states'           => array(
					'visible' => array(
						sprintf( '[name="%s"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( 'type' ) ) ) ) => array( 'value' => 'buttons' ),
					),
				),
				'#weight'           => 7,
			),
			'hide_empty' => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Hide empty', 'directories-pro' ),
				'#default_value' => ! empty( $settings['hide_empty'] ),
				'#weight'        => 9,
			),
			'hide_count' => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Hide count', 'directories-pro' ),
				'#default_value' => ! empty( $settings['hide_count'] ),
				'#weight'        => 10,
			),
		);
	}

	public function fieldFilterIsFilterable( Field\IField $field, array $settings, &$value, ?array $requests = null ) {
		return ! empty( $value );
	}

	public function fieldFilterDoFilter( Field\Query $query, Field\IField $field, array $settings, $value, array &$sorts ) {
		$query->fieldStartsWith( ( $property = $field->isPropertyField() ) ? $property : $field->getFieldName(), $value, $this->_getFacetColumn( $field, $settings ) );
	}

	public function fieldFilterForm( Field\IField $field, $filterName, array $settings, $request = null, ?Entity\Type\Query $query = null, ?array $current = null, $autoSubmit = true, $enableFacetCount = false, array $parents = array() ) {
		if ( false === $facets = $this->_getFacets( $field, $settings, $query, $enableFacetCount ) ) {
			return;
		}

		if ( ! isset( $current ) ) {
			$current = array(
				'#type'                    => $settings['type'],
				'#options'                 => array(
					'' => array( '#title' => __( 'All', 'directories-pro' ) ),
				) + $this->_getOptions( $field, $settings ),
				'#entity_filter_form_type' => $settings['type'] === 'buttons' ? 'radios' : $settings['type'],
				'#empty_value'             => '',
				'#columns'                 => $settings['columns'],
				'#btn_size'                => $settings['btn_size'],
				'#btn_color'               => $settings['btn_color'],
			);
		}

		if ( isset( $facets ) ) {
			$this->_loadFacetCounts( $current, $facets, $settings, $request );
		}

		return empty( $current['#options'] ) ? null : $current;
	}

	protected function _getMatchAndOr( Field\IField $field, array $settings ) {
		return 'OR';
	}

	protected function _getFacets( Field\IField $field, array $settings, ?Entity\Type\Query $query = null, $enableFacetCount = false ) {
		if ( ! $enableFacetCount
			|| ! empty( $settings['hide_count'] )
		) {
			return;
		}

		$field_query = $query->getFieldQuery();
		if ( $this->_getMatchAndOr( $field, $settings ) === 'OR' ) {
			// Clone field query and exclude queries for the taxonomy field and use it to fetch facets
			$field_query = clone $field_query;
			$field_query->removeNamedCriteria( ( $property = $field->isPropertyField() ) ? $property : $field->getFieldName() );
		}
		$facets = $this->_application->Entity_Facets(
			$field,
			$field_query,
			array(
				'facet_type' => 'first_letter',
				'letters'    => array_keys( $this->_getOptions( $field, $settings ) ),
				'column'     => $this->_getFacetColumn( $field, $settings ),
			)
		);

		if ( ! $facets ) {
			return empty( $settings['hide_empty'] ) ? array() : false;
		}

		return $facets;
	}

	protected function _getFacetColumn( Field\IField $field, array $settings ) {
		return $field->isPropertyField() ? null : 'value';
	}

	protected function _loadFacetCounts( array &$form, array $facets, array $settings, $request = null ) {
		if ( empty( $form['#options'] ) ) {
			return;
		}

		$_request = isset( $request ) ? (array) $request : array();
		foreach ( array_keys( $form['#options'] ) as $value ) {
			if ( $value === '' ) {
				continue;
			}

			if ( empty( $facets[ $value ] ) ) {
				if ( ! empty( $settings['hide_empty'] ) ) {
					unset( $form['#options'][ $value ] );
				} else {
					if ( ! is_array( $form['#options'][ $value ] ) ) {
						$form['#options'][ $value ] = $form['#options'][ $value ] . '(0)';
					} else {
						$form['#options'][ $value ]['#count'] = 0;
					}
					if ( ! in_array( $value, $_request ) ) {
						// Disable only when the option is currently not selected
						$form['#options_disabled'][] = $value;
					}
				}
			} else {
				if ( ! is_array( $form['#options'][ $value ] ) ) {
					$form['#options'][ $value ] = array( '#title' => $form['#options'][ $value ] );
				}
				$form['#options'][ $value ]['#count'] = $facets[ $value ];
			}
		}
	}

	protected function _getOptions( Field\IField $field, array $settings ) {
		$ret   = array();
		$chars = range( 'A', 'Z' );
		foreach ( $chars as $char ) {
			$ret[ strtolower( $char ) ] = array( '#title' => $char );
		}
		return $ret;
	}

	public function fieldFilterLabels( Field\IField $field, array $settings, $value, $form, $defaultLabel ) {
		$ret = array();
		foreach ( (array) $value as $_value ) {
			if ( is_array( $form['#options'][ $_value ] ) ) {
				$label = $form['#options'][ $_value ]['#title'];
			} else {
				$label = $form['#options'][ $_value ];
			}
			$ret[ $_value ] = $this->_application->H( $defaultLabel . ': ' . $label );
		}

		return $ret;
	}
}
