<?php
namespace SabaiApps\Directories\Component\Entity\FieldType;

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

class FeaturedFieldType extends AbstractType implements
	Field\Type\ISortable,
	Field\Type\IQueryable,
	Field\Type\ICopiable,
	Field\Type\IRestrictable,
	Field\Type\IConditionable {

	use Field\Type\ConditionableNumberTrait {
		fieldConditionableInfo as traitFieldConditionableInfo;
	}

	protected $_valueColumn = 'value';

	protected function _fieldTypeInfo() {
		return array(
			'label'      => __( 'Featured', 'directories-pro' ),
			'admin_only' => true,
			'icon'       => 'fas fa-star',
		);
	}

	public function fieldTypeSchema( array $settings = array() ) {
		return array(
			'columns' => array(
				'value'       => array(
					'type'     => Application::COLUMN_INTEGER,
					'notnull'  => true,
					'unsigned' => true,
					'was'      => 'value',
					'default'  => 1,
					'length'   => 1,
				),
				'featured_at' => array(
					'type'     => Application::COLUMN_INTEGER,
					'notnull'  => true,
					'unsigned' => true,
					'was'      => 'featured_at',
					'default'  => 0,
					'length'   => 10,
				),
				'expires_at'  => array(
					'type'     => Application::COLUMN_INTEGER,
					'notnull'  => true,
					'unsigned' => true,
					'was'      => 'expires_at',
					'default'  => 0,
					'length'   => 10,
				),
			),
			'indexes' => array(
				'value_featured_at' => array(
					'fields' => array(
						'value'       => array( 'sorting' => 'ascending' ),
						'featured_at' => array( 'sorting' => 'ascending' ),
					),
					'was'    => 'value_featured_at',
				),
				'expires_at'        => array(
					'fields' => array(
						'expires_at' => array( 'sorting' => 'ascending' ),
					),
					'was'    => 'expires_at',
				),
			),
		);
	}

	public function fieldTypeOnSaveValues( IField $field, array $values, ?array $currentValues = null, array &$extraArgs = array() ) {
		$value = array_shift( $values ); // single entry allowed for this field
		if ( ! is_array( $value )
			|| empty( $value['value'] )
		) {
			if ( empty( $currentValues ) ) {
				return;
			}

			$value = false; // delete
		} else {
			unset( $value['enable'] );
			$value['value'] = (int) $value['value'];
			if ( empty( $value['featured_at'] ) ) {
				$value['featured_at'] = time();
				if ( ! empty( $currentValues ) ) {
					$current_value = array_shift( $currentValues );
					if ( ! empty( $current_value['featured_at'] ) ) {
						$value['featured_at'] = $current_value['featured_at'];
					}
				}
			}
		}
		return array( $value );
	}

	public function fieldTypeIsModified( IField $field, $valueToSave, $currentLoadedValue ) {
		if ( count( $currentLoadedValue ) !== count( $valueToSave )
			|| empty( $valueToSave[0] ) // may be false if removing
		) {
			return true;
		}

		return count( $currentLoadedValue[0] ) !== count( $valueToSave[0] )
			|| array_diff_assoc( $currentLoadedValue[0], $valueToSave[0] );
	}

	public function fieldSortableOptions( IField $field ) {
		return array(
			array( 'label' => __( 'Featured First', 'directories-pro' ) ),
		);
	}

	public function fieldSortableSort( Query $query, $fieldName, ?array $args = null ) {
		$query->sortByField( $fieldName, 'DESC' );
	}

	public function fieldQueryableInfo( IField $field, $inAdmin = false ) {
		return array(
			'example' => 1,
			'tip'     => __( 'Enter 0 for non-featured items, 1 for all featured items, 5 for items with normal priority or higher, 9 for items with highest priority.', 'directories-pro' ),
		);
	}

	public function fieldQueryableQuery( Query $query, $fieldName, $paramStr, Bundle $bundle ) {
		if ( $priority = (int) $paramStr ) {
			$query->fieldIsOrGreaterThan( $fieldName, $priority );
		} else {
			$query->fieldIsNull( $fieldName );
		}
	}

	public static function priorities() {
		return array(
			9 => _x( 'High', 'priority', 'directories-pro' ),
			5 => _x( 'Normal', 'priority', 'directories-pro' ),
			1 => _x( 'Low', 'priority', 'directories-pro' ),
		);
	}

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

	public function fieldRestrictableOptions( IField $field ) {
		$options = array(
			'' => __( 'Featured/Non-Featured', 'directories-pro' ),
			-1 => __( 'Show all featured', 'directories-pro' ),
			-2 => __( 'Show all non-featured', 'directories-pro' ),
		);
		foreach ( self::priorities() as $key => $label ) {
			$options[ $key ] = __( 'Priority', 'directories-pro' ) . ': ' . $label;
		}
		return array( 'featured' => $options );
	}

	public function fieldRestrictableRestrict( IField $field, $value, $name ) {
		if ( $value == -1 ) {
			return array(
				'compare' => '>=',
				'value'   => 1,
			);
		}
		if ( $value == -2 ) {
			return array( 'compare' => 'NULL' );
		}
		return array();
	}

	public function fieldConditionableInfo( IField $field, $isServerSide = false ) {
		if ( ! $isServerSide ) {
			return;
		}

		$tips = array();
		foreach ( self::priorities() as $priority => $priority_label ) {
			$tips[] = $priority . ' = ' . $priority_label;
		}
		$info                = $this->traitFieldConditionableInfo( $field, $isServerSide );
		$info['']['tip']     = __( 'Enter one or two priority level values separated with a comma.', 'directories-pro' ) . ' ' . implode( ', ', $tips );
		$info['']['example'] = '5,9';

		return $info;
	}
}
