<?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;
use SabaiApps\Directories\Application;

class DateType extends AbstractType implements ISortable, IQueryable, IOpenGraph, IHumanReadable, ISchemable, ICopiable, IConditionable, IColumnable, IDateRange, IWpRestApi, IComparable {

	use QueryableDateTrait;
	use ConditionableDateTrait;
	use ComparableStringTrait;

	protected function _fieldTypeInfo() {
		return array(
			'label'            => __( 'Date', 'directories-pro' ),
			'default_settings' => array(
				'date_range_enable' => false,
				'date_range'        => null,
				'enable_time'       => true,
				'month_only'        => false,
			),
			'icon'             => 'fas fa-calendar-day',
		);
	}

	public function fieldTypeSettingsForm( $fieldType, Bundle $bundle, array $settings, array $parents = array(), array $rootParents = array() ) {
		return array(
			'month_only'        => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Month and year only', 'directories-pro' ),
				'#default_value' => ! empty( $settings['month_only'] ),
			),
			'enable_time'       => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Enable time (hour and minute)', 'directories-pro' ),
				'#default_value' => ! empty( $settings['enable_time'] ),
				'#states'        => array(
					'visible' => array(
						sprintf( 'input[name="%s[month_only]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'checked',
							'value' => false,
						),
					),
				),
			),
			'date_range_enable' => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Restrict dates', 'directories-pro' ),
				'#default_value' => ! empty( $settings['date_range_enable'] ),
				'#states'        => array(
					'visible' => array(
						sprintf( 'input[name="%s[month_only]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'checked',
							'value' => false,
						),
					),
				),
			),
			'date_range'        => array(
				'#type'          => 'daterangepicker',
				'#default_value' => is_array( $settings['date_range'] ) ? $settings['date_range'] : null,
				'#states'        => array(
					'visible' => array(
						sprintf( 'input[name="%s[month_only]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'checked',
							'value' => false,
						),
						sprintf( 'input[name="%s[date_range_enable]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'checked',
							'value' => true,
						),
					),
				),
			),
		);
	}

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

	public function fieldTypeOnSaveValues( IField $field, array $values, ?array $currentValues = null, array &$extraArgs = array() ) {
		$ret = array();
		foreach ( $values as $weight => $value ) {
			if ( is_null( $value ) ) {
				continue;
			}

			if ( ! is_numeric( $value )
				&& ( ! $value = $this->_application->System_Date_strToTime( $value ) )
			) {
				continue;
			} else {
				$value = intval( $value );
			}
			$ret[]['value'] = $value;
		}

		return $ret;
	}

	public function fieldTypeOnLoadValues( IField $field, array &$values, IEntity $entity, array $allValues ) {
		foreach ( $values as $key => $value ) {
			$values[ $key ] = (int) $value['value'];
		}
	}

	public function fieldTypeIsModified( IField $field, $valueToSave, $currentLoadedValue ) {
		$new = array();
		foreach ( $valueToSave as $value ) {
			$new[] = (int) $value['value'];
		}
		return $currentLoadedValue !== $new;
	}

	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 fieldOpenGraphProperties() {
		return array( 'books:release_date', 'music:release_date', 'video:release_date' );
	}

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

		return array( date( 'c', $value ) );
	}

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

		$ret            = array();
		$field_settings = $field->getFieldSettings();
		foreach ( $values as $value ) {
			$ret[] = ! empty( $field_settings['enable_time'] )
				? $this->_application->System_Date_datetime( $value )
				: $this->_application->System_Date( $value );
		}
		return implode( isset( $separator ) ? $separator : PHP_EOL, $ret );
	}

	public function fieldSchemaProperties( IField $field ) {
		return array( 'datePublished', 'dateModified', 'dateCreated', 'startDate', 'endDate', 'datePosted', 'validThrough' );
	}

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

		return array( date( 'Y-m-d', $value ) );
	}

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

	public function fieldColumnableInfo( IField $field ) {
		if ( ! $field->isCustomField() ) {
			return;
		}

		return array(
			'' => array(
				'label'  => $field->getFieldLabel(),
				'sortby' => 'value',
				'hidden' => true,
			),
		);
	}

	public function fieldColumnableColumn( IField $field, IEntity $entity, $column = '' ) {
		if ( ! $values = $entity->getFieldValue( $field->getFieldName() ) ) {
			return;
		}

		foreach ( array_keys( $values ) as $key ) {
			$values[ $key ] = $this->_application->System_Date( $values[ $key ], true );
		}
		return implode( ', ', $values );
	}

	public function fieldDateRangeInfo( IField $field ) {
		return array(
			'start_column' => 'value',
			'end_column'   => null,
		);
	}

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

		return array( $value, null );
	}

	public function fieldWpRestApiSchema( IField $field ) {
		return array(
			'type'  => 'array',
			'items' => array(
				'type'   => 'string',
				'format' => 'date-time',
			),
		);
	}

	public function fieldWpRestApiGetValue( IField $field, IEntity $entity, $request ) {
		$ret = array();
		if ( $values = $entity->getFieldValue( $field->getFieldName() ) ) {
			foreach ( $values as $value ) {
				$ret[] = $this->_application->System_Date( $value, false, 'c' );
			}
		}
		return $ret;
	}
}
