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

use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Field\IField;
use SabaiApps\Directories\Component\Field\Query;

class ChoiceType extends AbstractValueType implements ISortable, IQueryable, IConditionable, IHumanReadable, ILabellable, ISchemable, IWpRestApi, IComparable {

	use ChoiceTrait;

	protected function _fieldTypeInfo() {
		return array(
			'label'            => __( 'Choice', 'directories-pro' ),
			'default_widget'   => 'checkboxes',
			'default_settings' => array(
				'options' => null,
			),
			'icon'             => 'far fa-check-square',
			'schema_type'      => 'string',
		);
	}

	public function fieldTypeSettingsForm( $fieldType, Bundle $bundle, array $settings, array $parents = array(), array $rootParents = array() ) {
		return array(
			'options' => array(
				'#type'              => 'options',
				'#title'             => __( 'Options', 'directories-pro' ),
				'#default_value'     => $settings['options'],
				'#multiple'          => true,
				'#default_unchecked' => true,
				'#value_max_length'  => 255,
				'#enable_color'      => true,
			),
		);
	}

	public function fieldSortableOptions( IField $field ) {
		return array(
			array(),
			array(
				'args'  => array( 'desc' ),
				'label' => __( '%s (desc)', 'directories-pro' ),
			),
		);
	}

	public function fieldSortableSort( Query $query, $fieldName, ?array $args = null ) {
		$query->sortByField( $fieldName, isset( $args ) && $args[0] === 'desc' ? 'DESC' : 'ASC' );
	}

	public function fieldQueryableQuery( Query $query, $fieldName, $paramStr, Bundle $bundle ) {
		if ( $params = $this->_queryableParams( $paramStr ) ) {
			if ( false !== $key = array_search( '_current_', $params ) ) {
				unset( $params[ $key ] );
				if ( ( $entity = $this->_getCurrentEntity() )
					&& ( $values = $entity->getFieldValue( $fieldName ) )
				) {
					foreach ( $values as $value ) {
						$params[] = $value;
					}
				}
			}
			$query->fieldIsIn( $fieldName, $params );
		}
	}

	public function fieldConditionableMatch( IField $field, array $rule, array $values, IEntity $entity ) {
		switch ( $rule['type'] ) {
			case 'value':
			case '!value':
			case 'one':
				if ( empty( $values ) ) {
					return $rule['type'] === '!value';
				}

				foreach ( (array) $rule['value'] as $rule_value ) {
					foreach ( $values as $input ) {
						if ( is_array( $input ) ) {
							$input = $input[ $this->_valueColumn ];
						}
						if ( $input == $rule_value ) {
							if ( $rule['type'] === '!value' ) {
								return false;
							}
							if ( $rule['type'] === 'one' ) {
								return true;
							}
							continue 2;
						}
					}
					// One of rules did not match
					if ( $rule['type'] === 'value' ) {
						return false;
					}
				}
				// All rules matched or did not match.
				return $rule['type'] !== 'one' ? true : false;
			case 'empty':
				return empty( $values ) === $rule['value'];
			case 'filled':
				return ! empty( $values ) === $rule['value'];
			default:
				return false;
		}
	}

	public function fieldComparableItemLabels( IField $field ) {
		$labels  = array();
		$options = $this->_application->Field_ChoiceOptions( $field );
		if ( ! empty( $options['options'] ) ) {
			foreach ( $options['options'] as $key => $label ) {
				$labels[ $key ] = $label;
			}
		}
		return $labels;
	}

	public function fieldComparableItemValues( IField $field, IEntity $entity, $html = true ) {
		$values         = array();
		$field_settings = $field->getFieldSettings();
		if ( ! empty( $field_settings['options']['options'] ) ) {
			$field_values = (array) $entity->getFieldValue( $field->getFieldName() );
			foreach ( array_keys( $field_settings['options']['options'] ) as $key ) {
				$values[ $key ] = in_array( $key, $field_values, true )
					? ( $html ? '<i class="fas fa-check ' . DRTS_BS_PREFIX . 'text-success"></i>' : true )
					: ( $html ? '<i class="fas fa-times ' . DRTS_BS_PREFIX . 'text-danger"></i>' : false );
			}
		}
		return $values;
	}
}
