<?php
namespace SabaiApps\Directories\Component\Field\Filter;

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Field\IField;
use SabaiApps\Directories\Component\Field\Query;

class RangeListFilter extends AbstractOptionFilter {

	protected $_minMaxSeparator = ',';

	public function __construct( Application $application, $name ) {
		parent::__construct( $application, $name );
		$this->_label           = __( 'Range list', 'directories-pro' );
		$this->_fieldTypes      = array( 'number', 'price', 'range' );
		$this->_defaultSettings = array( 'ranges' => null );
	}

	public function fieldFilterSettingsForm( IField $field, array $settings, array $parents = array() ) {
		$field_settings = $field->getFieldSettings();
		return array(
			'ranges' => array(
				'#type'          => 'rangelist',
				'#title'         => __( 'Ranges', 'directories-pro' ),
				'#default_value' => $settings['ranges'],
				'#min_value'     => isset( $field_settings['min'] ) ? $field_settings['min'] : null,
				'#max_value'     => isset( $field_settings['max'] ) ? $field_settings['max'] : null,
				'#weight'        => 1,
			),
		) + parent::fieldFilterSettingsForm( $field, $settings, $parents );
	}

	protected function _getOptions( IField $field, array $settings, &$noEscape = false ) {
		$options = array();
		foreach ( $settings['ranges'] as $range ) {
			$key             = $range['min'] . $this->_minMaxSeparator . $range['max'];
			$options[ $key ] = $range['label'];
		}
		$noEscape = true;
		return $options;
	}

	protected function _getFacetOptions( IField $field, array $settings ) {
		$ranges = array();
		foreach ( $settings['ranges'] as $range ) {
			$key            = $range['min'] . $this->_minMaxSeparator . $range['max'];
			$ranges[ $key ] = $range;
		}
		return array(
			'facet_type' => 'range',
			'column'     => $this->_getValueColumn( $field, $settings ),
			'ranges'     => $ranges,
		);
	}

	protected function _getValueColumn( IField $field, array $settings ) {
		return $field->getFieldType() === 'range' ? 'average' : $this->_valueColumn;
	}

	public function fieldFilterDoFilter( Query $query, IField $field, array $settings, $value, array &$sorts ) {
		if ( ! $ranges = $this->_getRangeValues( $field, $value ) ) {
			return;
		}

		$value_column = $this->_getValueColumn( $field, $settings );
		if ( $settings['type'] !== 'checkboxes'
			|| count( $ranges ) === 1
		) {
			$range = array_shift( $ranges );
			$query->fieldIsOrGreaterThan( $field, $range['min'], $value_column )
				->fieldIsOrSmallerThan( $field, $range['max'], $value_column );
			return;
		}

		if ( $settings['andor'] === 'OR' ) {
			$query->startCriteriaGroup( 'OR' );
			foreach ( $ranges as $range ) {
				$query->startCriteriaGroup()
					->fieldIsOrGreaterThan( $field, $range['min'], $value_column )
					->fieldIsOrSmallerThan( $field, $range['max'], $value_column )
					->finishCriteriaGroup();
			}
			$query->finishCriteriaGroup();
		} else {
			foreach ( $ranges as $range ) {
				$query->fieldIsOrGreaterThan( $field, $range['min'], $value_column )
					->fieldIsOrSmallerThan( $field, $range['max'], $value_column );
			}
		}
	}

	protected function _getRangeValues( IField $field, $value ) {
		$field_settings = $field->getFieldSettings();
		$ret            = array();
		foreach ( (array) $value as $_value ) {
			$_value = explode( $this->_minMaxSeparator, $_value );

			if ( ! isset( $_value[0] )
				|| ! strlen( $_value[0] = trim( $_value[0] ) )
				|| ! is_numeric( $_value[0] )
			) {
				$_value[0] = isset( $field_settings['min'] ) ? $field_settings['min'] : 0;
			}
			if ( ! isset( $_value[1] )
				|| ! strlen( $_value[1] = trim( $_value[1] ) )
				|| ! is_numeric( $_value[1] )
			) {
				$_value[1] = isset( $field_settings['max'] ) ? $field_settings['max'] : 100;
			}

			$ret[] = array(
				'min' => $_value[0],
				'max' => $_value[1],
			);
		}

		return $ret;
	}
}
