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

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

class RangeType extends AbstractType implements IQueryable, ISchemable, IHumanReadable, ICopiable, IConditionable, IComparable {

	use ConditionableRangeTrait;
	use QueryableRangeTrait;
	use ComparableStringTrait;

	protected function _fieldTypeInfo() {
		return array(
			'label'            => __( 'Range', 'directories-pro' ),
			'default_settings' => array(
				'min'      => null,
				'max'      => null,
				'decimals' => 0,
				'prefix'   => null,
				'suffix'   => null,
			),
			'icon'             => 'fas fa-sliders',
		);
	}

	public function fieldTypeSettingsForm( $fieldType, Bundle $bundle, array $settings, array $parents = array(), array $rootParents = array() ) {
		return array(
			'#element_validate' => array( array( array( $this, 'validateMinMaxSettings' ), array( 'decimals' ) ) ),
			'min'               => array(
				'#type'          => 'number',
				'#title'         => __( 'Minimum', 'directories-pro' ),
				'#description'   => __( 'The minimum value allowed in this field.', 'directories-pro' ),
				'#size'          => 10,
				'#default_value' => $settings['min'],
				'#numeric'       => true,
				'#step'          => 0.01,
			),
			'max'               => array(
				'#type'          => 'number',
				'#title'         => __( 'Maximum', 'directories-pro' ),
				'#description'   => __( 'The maximum value allowed in this field.', 'directories-pro' ),
				'#size'          => 10,
				'#default_value' => $settings['max'],
				'#numeric'       => true,
				'#step'          => 0.01,
			),
			'decimals'          => array(
				'#type'          => 'select',
				'#title'         => __( 'Decimals', 'directories-pro' ),
				'#description'   => __( 'The number of digits to the right of the decimal point.', 'directories-pro' ),
				'#options'       => array(
					0 => __( '0 (no decimals)', 'directories-pro' ),
					1 => 1,
					2 => 2,
				),
				'#default_value' => $settings['decimals'],
			),
			'prefix'            => array(
				'#type'          => 'textfield',
				'#title'         => __( 'Field prefix', 'directories-pro' ),
				'#description'   => __( 'Example: $, #, -', 'directories-pro' ),
				'#size'          => 20,
				'#default_value' => $settings['prefix'],
				'#no_trim'       => true,
			),
			'suffix'            => array(
				'#type'          => 'textfield',
				'#title'         => __( 'Field suffix', 'directories-pro' ),
				'#description'   => __( 'Example: km, %, g', 'directories-pro' ),
				'#size'          => 20,
				'#default_value' => $settings['suffix'],
				'#no_trim'       => true,
			),
		);
	}

	public function fieldTypeSchema( array $settings = array() ) {
		return array(
			'columns' => array(
				'min'     => array(
					'type'     => Application::COLUMN_DECIMAL,
					'notnull'  => true,
					'length'   => 18,
					'scale'    => 2,
					'unsigned' => false,
					'was'      => 'min',
					'default'  => 0,
				),
				'max'     => array(
					'type'     => Application::COLUMN_DECIMAL,
					'notnull'  => true,
					'length'   => 18,
					'scale'    => 2,
					'unsigned' => false,
					'was'      => 'max',
					'default'  => 0,
				),
				'average' => array(
					'type'     => Application::COLUMN_DECIMAL,
					'notnull'  => true,
					'length'   => 18,
					'scale'    => 2,
					'unsigned' => false,
					'was'      => 'average',
					'default'  => 0,
				),
			),
			'indexes' => array(
				'min'     => array(
					'fields' => array( 'min' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'min',
				),
				'max'     => array(
					'fields' => array( 'max' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'max',
				),
				'average' => array(
					'fields' => array( 'average' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'average',
				),
			),
		);
	}

	public function fieldTypeOnLoadValues( IField $field, array &$values, IEntity $entity, array $allValues ) {
		foreach ( array_keys( $values ) as $key ) {
			$values[ $key ]['min'] = (float) $values[ $key ]['min'];
			$values[ $key ]['max'] = (float) $values[ $key ]['max'];
		}
	}

	public function fieldTypeOnSaveValues( IField $field, array $values, ?array $currentValues = null, array &$extraArgs = array() ) {
		$settings = $field->getFieldSettings();
		$ret      = array();
		foreach ( $values as $weight => $value ) {
			if ( ! is_array( $value )
				|| ! is_numeric( @$value['min'] )
				|| ! is_numeric( @$value['max'] )
			) {
				continue;
			}

			$ret[] = array(
				'min'     => $min = round( $value['min'], $settings['decimals'] ),
				'max'     => $max = round( $value['max'], $settings['decimals'] ),
				'average' => $min + ( $max - $min ) / 2,
			);
		}

		return $ret;
	}

	protected function _getConditionableRuleValue( $value ) {
		return is_numeric( $value ) ? $value : false;
	}

	protected function _getQueryableQueryValue( $value ) {
		return is_numeric( $value ) ? $value : false;
	}

	public function fieldSchemaProperties( IField $field ) {
		return array( 'priceRange' );
	}

	public function fieldSchemaRenderProperty( IField $field, $property, IEntity $entity ) {
		if ( ! $value = $entity->getSingleFieldValue( $field->getFieldName() ) ) {
			return;
		}

		return $this->_getFormattedValues( $field, $entity, array( $value ) );
	}

	public function fieldHumanReadableText( IField $field, IEntity $entity, $separator = null, $key = null ) {
		if ( ! $values = $this->_getFormattedValues( $field, $entity, null, $key ) ) {
			return '';
		}

		return implode( isset( $separator ) ? $separator : ', ', $values );
	}

	protected function _getFormattedValues( IField $field, IEntity $entity, ?array $values = null, $key = null ) {
		if ( ! isset( $values )
			&& ( ! $values = $entity->getFieldValue( $field->getFieldName() ) )
		) {
			return;
		}

		$settings = $field->getFieldSettings();
		$decimals = empty( $settings['decimals'] ) ? 0 : $settings['decimals'];
		$prefix   = isset( $settings['prefix'] ) ? $settings['prefix'] : '';
		$suffix   = isset( $settings['suffix'] ) ? $settings['suffix'] : '';
		if ( isset( $key )
			&& ( $key === 'min' || $key === 'max' )
		) {
			foreach ( array_keys( $values ) as $i ) {
				$value        = $this->_application->getPlatform()->numberFormat( $values[ $i ][ $key ], $decimals );
				$values[ $i ] = $prefix . $value . $suffix;
			}
		} else {
			foreach ( array_keys( $values ) as $i ) {
				$min          = $this->_application->getPlatform()->numberFormat( $values[ $i ]['min'], $decimals );
				$max          = $this->_application->getPlatform()->numberFormat( $values[ $i ]['max'], $decimals );
				$values[ $i ] = $prefix . $min . $suffix . ' - ' . $prefix . $max . $suffix;
			}
		}
		return $values;
	}

	public function fieldCopyValues( IField $field, array $values, array &$allValue, $lang = null ) {
		return $values;
	}
}
