<?php
namespace SabaiApps\Directories\Component\Calendar\FieldWidget;

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

class SlotFieldWidget extends AbstractWidget {

	protected function _fieldWidgetInfo() {
		return array(
			'field_types'           => array( $this->_name ),
			'repeatable'            => true,
			'default_max_num_items' => 0,
			'default_settings'      => array(
				'require_end_time' => true,
			),
		);
	}

	public function fieldWidgetSettingsForm( $fieldType, Bundle $bundle, array $settings, array $parents = array(), array $rootParents = array() ) {
		return array(
			'require_end_time' => array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Require end time', 'directories-pro' ),
				'#default_value' => ! empty( $settings['require_end_time'] ),
				'#description'   => __( 'If checked, end time is required when adding a calendar slot. 23:59 is used as the default end time if not specified.', 'directories-pro' ),
			),
		);
	}

	public function fieldWidgetForm( IField $field, array $settings, $value = null, ?IEntity $entity = null, array $parents = array(), $language = null ) {
		$field_settings   = $field->getFieldSettings();
		$enable_recurring = ! empty( $field_settings['enable_recurring'] );
		$enable_title     = ! empty( $field_settings['enable_title'] );
		if ( isset( $value ) ) {
			$value['start'] = array(
				'date'    => $value['start_date'],
				'all_day' => ! empty( $value['all_day'] ),
			);
			$value['time']  = array(
				'start_time' => $value['start_time'],
				'end_time'   => $value['end_time'],
			);
			if ( ! empty( $value['repeat_end_date'] ) ) {
				$value['end_repeat'] = array(
					'type' => 'on',
					'on'   => $value['repeat_end_date'],
				);
			}
			if ( ! empty( $value['exclude_dates'] ) ) {
				$value['exclude_dates'] = explode( ',', $value['exclude_dates'] );
			}
			if ( ! empty( $value['rrule'] )
				&& ( $rrule = $this->_parseRrule( $value['rrule'] ) )
				&& ! empty( $rrule['FREQ'] )
			) {
				switch ( $value['repeat'] = strtolower( $rrule['FREQ'] ) ) {
					case 'daily':
						break;
					case 'weekly':
						if ( ! empty( $rrule['BYDAY'] ) ) {
							foreach ( (array) $rrule['BYDAY'] as $i => $day ) {
								$rrule['BYDAY'][ $i ] = $this->_getDayNum( $day );
							}
							$value['weekly']['days'] = $rrule['BYDAY'];
						}
						break;
					case 'monthly':
						if ( ! empty( $rrule['BYMONTHDAY'] ) ) {
							$value['monthly']['pattern']    = 'bymonthday';
							$value['monthly']['bymonthday'] = $rrule['BYMONTHDAY'];
						} elseif ( ! empty( $rrule['BYDAY'] ) && ! empty( $rrule['BYSETPOS'] ) ) {
							$value['monthly']['pattern']         = 'byday';
							$value['monthly']['week']['day_pos'] = $rrule['BYSETPOS'];
							$value['monthly']['week']['day']     = $this->_getDayNum( is_array( $rrule['BYDAY'] ) ? $rrule['BYDAY'][0] : $rrule['BYDAY'] );
						}
						break;
					case 'yearly':
						break;
					default:
						$value['repeat'] = '';
				}
			} else {
				$value['repeat'] = '';
			}
		}

		return array(
			'#type'             => 'calendar_slot',
			'#default_value'    => $value,
			'#require_end_time' => ! empty( $settings['require_end_time'] ),
			'#enable_recurring' => $enable_recurring,
			'#enable_title'     => $enable_title,
			'#enable_booking'   => ! empty( $field_settings['enable_booking'] ) && ! empty( $field->Bundle->info['booking_enable'] ),
		);
	}

	protected function _parseRrule( $rruleStr ) {
		$parsed     = array();
		$properties = explode( ';', $rruleStr );
		foreach ( $properties as $property ) {
			$parts = explode( '=', $property, 2 );
			if ( count( $parts ) === 2 ) {
				$key       = trim( $parts[0] );
				$value_str = trim( $parts[1] );
				if ( strpos( $value_str, ',' ) !== false ) {
					$value = explode( ',', $value_str );
				} else {
					$value = $value_str;
				}
				$parsed[ $key ] = $value;
			}
		}
		return $parsed;
	}

	protected function _getDayNum( $day ) {
		switch ( strtoupper( $day ) ) {
			case 'MO':
				return 1;
			case 'TU':
				return 2;
			case 'WE':
				return 3;
			case 'TH':
				return 4;
			case 'FR':
				return 5;
			case 'SA':
				return 6;
			case 'SU':
				return 7;
			default:
				return null;
		}
	}
}
