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

use SabaiApps\Directories\Component\CSV\Importer\AbstractImporter;
use SabaiApps\Directories\Component\CSV\Importer\IWpAllImportImporter;
use SabaiApps\Directories\Component\Entity\Model\Field;

class FieldCSVImporter extends AbstractImporter implements IWpAllImportImporter {

	protected function _csvImporterInfo() {
		$info = array(
			'field_types' => array( substr( $this->_name, 6 ) ), // remove field_ part
		);
		switch ( $this->_name ) {
			case 'field_time':
				$info['field_types'][] = 'directory_opening_hours';
				break;
			case 'field_name':
				$info['field_types'][] = 'user_name';
				break;
			default:
		}
		return $info;
	}

	public function csvImporterColumns( Field $field ) {
		switch ( $this->_name ) {
			case 'field_name':
				return array(
					'prefix'      => _x( 'Prefix', 'name salutation', 'directories-pro' ),
					'first_name'  => __( 'First Name', 'directories-pro' ),
					'middle_name' => __( 'Middle Name', 'directories-pro' ),
					'last_name'   => __( 'Last Name', 'directories-pro' ),
					'suffix'      => _x( 'Suffix', 'name suffix', 'directories-pro' ),
				);
		}
		return parent::csvImporterColumns( $field );
	}

	public function csvImporterSettingsForm( Field $field, array $settings, $column, $enclosure, array $parents = array() ) {
		if ( $this->_name === 'field_boolean' ) {
			return;
		}

		$form = $reserved_separator = array();

		switch ( $this->_name ) {
			case 'field_video':
				$form                           += array(
					'separator' => array(
						'#type'          => 'textfield',
						'#title'         => __( 'Video provider/ID separator', 'directories-pro' ),
						'#description'   => __( 'Enter the character used to separate the video provider and ID.', 'directories-pro' ),
						'#default_value' => '|',
						'#horizontal'    => true,
						'#min_length'    => 1,
						'#required'      => true,
						'#weight'        => 1,
					),
				);
				$reserved_separator['separator'] = $form['separator']['#title'];
				break;
			case 'field_price':
				$form                           += array(
					'separator' => array(
						'#type'          => 'textfield',
						'#title'         => __( 'Price value/currency separator', 'directories-pro' ),
						'#description'   => __( 'Enter the character used to separate the price value and currency.', 'directories-pro' ),
						'#default_value' => '|',
						'#horizontal'    => true,
						'#min_length'    => 1,
						'#required'      => true,
						'#weight'        => 1,
					),
					'dec_point' => array(
						'#type'          => 'textfield',
						'#title'         => __( 'Decimal point', 'directories-pro' ),
						'#description'   => __( 'Enter the character used as the decimal point.', 'directories-pro' ),
						'#default_value' => '.',
						'#horizontal'    => true,
						'#min_length'    => 1,
						'#max_length'    => 1,
						'#required'      => true,
						'#weight'        => 2,
					),
				);
				$reserved_separator['separator'] = $form['separator']['#title'];
				$reserved_separator['dec_point'] = $form['dec_point']['#title'];
				break;
			case 'field_number':
				$form                           += array(
					'dec_point' => array(
						'#type'          => 'textfield',
						'#title'         => __( 'Decimal point', 'directories-pro' ),
						'#description'   => __( 'Enter the character used as the decimal point.', 'directories-pro' ),
						'#default_value' => '.',
						'#horizontal'    => true,
						'#min_length'    => 1,
						'#max_length'    => 1,
						'#required'      => true,
						'#weight'        => 2,
					),
				);
				$reserved_separator['dec_point'] = $form['dec_point']['#title'];
				break;
			case 'field_range':
				$form                           += array(
					'separator' => array(
						'#type'          => 'textfield',
						'#title'         => __( 'Field min/max separator', 'directories-pro' ),
						'#description'   => __( 'Enter the character used to separate the minimum and maximum values.', 'directories-pro' ),
						'#default_value' => '|',
						'#horizontal'    => true,
						'#min_length'    => 1,
						'#required'      => true,
						'#weight'        => 1,
					),
				);
				$reserved_separator['separator'] = $form['separator']['#title'];
				break;
			case 'field_date':
				$form += $this->_getDateFormatSettingsForm( $parents );
				break;
			case 'field_time':
				$form                           += array(
					'separator'   => array(
						'#type'          => 'textfield',
						'#title'         => __( 'Start/End/Day separator', 'directories-pro' ),
						'#description'   => __( 'Enter the character used to separate the starting time, ending time, and day of week.', 'directories-pro' ),
						'#default_value' => '|',
						'#horizontal'    => true,
						'#min_length'    => 1,
						'#required'      => true,
					),
					'date_format' => array(
						'#type'          => 'select',
						'#title'         => __( 'Time format', 'directories-pro' ),
						'#description'   => __( 'Select the format used to represent time values in CSV.', 'directories-pro' ),
						'#options'       => array(
							'string'    => __( 'HH:MM', 'directories-pro' ),
							'timestamp' => __( 'Timestamp', 'directories-pro' ),
						),
						'#default_value' => 'string',
					),
				);
				$reserved_separator['separator'] = $form['separator']['#title'];
				break;
			default:
		}

		if ( $field->isCustomField() ) {
			$form += $this->_acceptMultipleValues( $field, $enclosure, $parents, $reserved_separator );
		}

		return $form;
	}

	public function csvImporterDoImport( Field $field, array $settings, $column, $value, &$formStorage, array &$logs ) {
		if ( $this->_name === 'field_boolean' ) {
			return array( array( 'value' => $value ) );
		}

		if ( ! empty( $settings['_multiple'] ) ) {
			if ( ! $values = explode( $settings['_separator'], $value ) ) {
				return;
			}
		} else {
			$values = array( $value );
		}

		$ret = array();
		switch ( $this->_name ) {
			case 'field_video':
				foreach ( $values as $value ) {
					if ( $value = explode( $settings['separator'], $value ) ) {
						$ret[] = array(
							'id'       => $value[1],
							'provider' => $value[0],
						);
					}
				}
				break;
			case 'field_price':
				foreach ( $values as $value ) {
					if ( $value = explode( $settings['separator'], $value ) ) {
						if ( strlen( $settings['dec_point'] )
							&& $settings['dec_point'] !== '.'
						) {
							$value[0] = strtr( $value[0], array( $settings['dec_point'] => '.' ) );
						}
						$ret[] = array(
							'value'    => $value[0],
							'currency' => isset( $value[1] ) ? $value[1] : null,
						);
					}
				}
				break;
			case 'field_range':
				foreach ( $values as $value ) {
					if ( $value = explode( $settings['separator'], $value ) ) {
						$ret[] = array(
							'min' => $value[0],
							'max' => $value[1],
						);
					}
				}
				break;
			case 'field_name':
				foreach ( $values as $value ) {
					$ret[] = array( $column => $value );
				}
				break;
			case 'field_date':
				foreach ( $values as $value ) {
					if ( false !== $value = $this->_strToTime( $value, $settings ) ) {
						$ret[] = $value;
					}
				}
				break;
			case 'field_time':
				if ( $settings['date_format'] === 'string' ) {
					foreach ( $values as $value ) {
						if ( ! $value = $this->_getTimeRange( $value, $settings['separator'] ) ) {
							continue;
						}

						$ret[] = $value;
					}
				} else {
					foreach ( $values as $value ) {
						$value = explode( $settings['separator'], $value );
						if ( ! $value[0] ) {
							continue;
						}

						$ret[] = array(
							'start'   => $value[0],
							'end'     => isset( $value[1] ) && strlen( $value[1] ) ? $value[1] : null,
							'day'     => isset( $value[2] ) ? (string) $value[2] : '',
							'all_day' => isset( $value[3] ) ? (string) $value[3] : '',
						);
					}
				}
				break;
			case 'field_number':
				if ( strlen( $settings['dec_point'] )
					&& $settings['dec_point'] !== '.'
				) {
					foreach ( $values as $value ) {
						$ret[] = array( 'value' => strtr( $value, array( $settings['dec_point'] => '.' ) ) );
					}
				} else {
					foreach ( $values as $value ) {
						$ret[] = array( 'value' => $value );
					}
				}
				break;
			default:
				foreach ( $values as $value ) {
					$ret[] = array( 'value' => $value );
				}
		}

		return $ret;
	}

	public function csvWpAllImportImporterAddField( \RapidAddon $addon, Field $field ) {
		switch ( $this->_name ) {
			case 'field_boolean':
				$addon->add_title( $field->getFieldLabel() );
				$settings = $field->getFieldSettings();
				$addon->add_field(
					$field->getFieldName(),
					'',
					'radio',
					array(
						1 => __( 'Yes', 'directories-pro' ),
						0 => __( 'No', 'directories-pro' ),
					),
					'',
					true,
					0
				);
				return true;
			case 'field_video':
				$addon->add_title( $field->getFieldLabel() );
				$options = array(
					$addon->add_field(
						$field->getFieldName() . '-provider',
						__( 'Video provider', 'directories-pro' ),
						'radio',
						array(
							'youtube' => __( 'YouTube', 'directories-pro' ),
							'vimeo'   => __( 'Vimeo', 'directories-pro' ),
						)
					),
				);
				if ( $field->isCustomField()
					&& $field->getFieldMaxNumItems() !== 1
				) {
					$options[] = $addon->add_field(
						$field->getFieldName() . '-separator',
						__( 'Separator', 'directories-pro' ),
						'text',
						null,
						'',
						true,
						','
					);
				}
				$addon->add_options(
					$addon->add_field( $field->getFieldName(), __( 'Video ID', 'directories-pro' ), 'text', null, '' ),
					__( 'Field Options', 'directories-pro' ),
					$options
				);
				return true;
			case 'field_price':
				$addon->add_title( $field->getFieldLabel() );
				$addon->add_field(
					$field->getFieldName() . '-currency',
					__( 'Currency', 'directories-pro' ),
					'text',
					null,
					'',
					true,
					''
				);
				$addon->add_field(
					$field->getFieldName() . '-value',
					__( 'Price', 'directories-pro' ),
					'text',
					null,
					'',
					true,
					''
				);
				return true;
			case 'field_range':
				$addon->add_title( $field->getFieldLabel() );
				$addon->add_field(
					$field->getFieldName() . '-min',
					__( 'Minimum value', 'directories-pro' ),
					'text',
					null,
					'',
					true,
					''
				);
				$addon->add_field(
					$field->getFieldName() . '-max',
					__( 'Maximum value', 'directories-pro' ),
					'text',
					null,
					'',
					true,
					''
				);
				return true;
			case 'field_time':
				$addon->add_title( $field->getFieldLabel() );
				$settings = $field->getFieldSettings();
				if ( ! empty( $settings['enable_day'] ) ) {
					foreach ( $this->_application->System_Days() as $key => $day ) {
						$addon->add_field(
							$field->getFieldName() . '-' . $key,
							$day,
							'text',
							null,
							'HH:MM|HH:MM'
						);
					}
				} elseif ( $field->isCustomField()
						&& $field->getFieldMaxNumItems() !== 1
					) {

						$addon->add_options(
							$addon->add_field( $field->getFieldName(), '', 'text', null, 'HH:MM - HH:MM' ),
							__( 'Field Options', 'directories-pro' ),
							array(
								$addon->add_field(
									$field->getFieldName() . '-separator',
									__( 'Separator', 'directories-pro' ),
									'text',
									null,
									'',
									true,
									';'
								),
								$addon->add_field(
									$field->getFieldName() . '-separator2',
									__( 'Start/End/Day separator', 'directories-pro' ),
									'text',
									null,
									__( 'Enter the character used to separate the starting time, ending time, and day of week.', 'directories-pro' ),
									true,
									'|'
								),
							)
						);
				} else {
					$addon->add_field( $field->getFieldName(), '', 'text', null, '' );
				}
				return true;
			case 'field_string':
			case 'field_text':
			case 'field_url':
			case 'field_email':
			case 'field_phone':
			case 'field_number':
			case 'field_color':
			case 'field_icon':
			case 'field_choice':
			case 'field_date':
			default:
				$addon->add_title( $field->getFieldLabel() );
				if ( $field->isCustomField()
					&& $field->getFieldMaxNumItems() !== 1
				) {
					$addon->add_options(
						$addon->add_field( $field->getFieldName(), '', 'text', null, '' ),
						__( 'Field Options', 'directories-pro' ),
						array(
							$addon->add_field(
								$field->getFieldName() . '-separator',
								__( 'Separator', 'directories-pro' ),
								'text',
								null,
								'',
								true,
								','
							),
						)
					);
				} else {
					$addon->add_field( $field->getFieldName(), '', 'text', null, '' );
				}
				return true;
		}
	}

	public function csvWpAllImportImporterDoImport( \RapidAddon $addon, Field $field, array $data, $options, array $article ) {
		switch ( $this->_name ) {
			case 'field_boolean':
				if ( ! isset( $data[ $field->getFieldName() ] ) ) {
					return;
				}

				return array( $data[ $field->getFieldName() ] );
			case 'field_video':
				if ( ! isset( $data[ $field->getFieldName() ] ) ) {
					return;
				}

				if ( isset( $data[ $field->getFieldName() . '-separator' ] )
					&& ( $separator = trim( $data[ $field->getFieldName() . '-separator' ] ) )
				) {
					if ( ! $values = explode( $separator, $data[ $field->getFieldName() ] ) ) {
						return;
					}
					$values = array_map( 'trim', $values );
				} else {
					$values = array( trim( $data[ $field->getFieldName() ] ) );
				}
				if ( isset( $data[ $field->getFieldName() . '-provider' ] ) && in_array( $data[ $field->getFieldName() . '-provider' ], array( 'vimeo' ) ) ) {
					$provider = $data[ $field->getFieldName() . '-provider' ];
				} else {
					$provider = 'youtube';
				}
				foreach ( array_keys( $values ) as $key ) {
					$values[ $key ] = array(
						'id'       => $values[ $key ],
						'provider' => $provider,
					);
				}
				return array_values( $values );
			case 'field_price':
				if ( ! isset( $data[ $field->getFieldName() . '-currency' ] )
					|| ! isset( $data[ $field->getFieldName() . '-value' ] )
				) {
					return;
				}

				return array(
					'value'    => $data[ $field->getFieldName() . '-value' ],
					'currency' => $data[ $field->getFieldName() . '-currency' ],
				);
			case 'field_range':
				if ( ! isset( $data[ $field->getFieldName() . '-min' ] )
					|| ! isset( $data[ $field->getFieldName() . '-max' ] )
					|| $data[ $field->getFieldName() . '-max' ] < $data[ $field->getFieldName() . '-min' ]
				) {
					return;
				}

				return array(
					'min' => $data[ $field->getFieldName() . '-min' ],
					'max' => $data[ $field->getFieldName() . '-max' ],
				);
			case 'field_time':
				$values   = array();
				$settings = $field->getFieldSettings();
				if ( ! empty( $settings['enable_day'] ) ) {
					foreach ( $this->_application->System_Days() as $key => $day ) {
						if ( empty( $data[ $field->getFieldName() . '-' . $key ] )
							|| ( ! $value = $this->_getTimeRange( $data[ $field->getFieldName() . '-' . $key ] ) )
						) {
							continue;
						}

						$value['day'] = $key;
						$values[]     = $value;
					}
				} else {
					if ( ! isset( $data[ $field->getFieldName() ] ) ) {
						return;
					}

					if ( isset( $data[ $field->getFieldName() . '-separator' ] )
						&& ( $separator = trim( $data[ $field->getFieldName() . '-separator' ] ) )
					) {
						if ( ! $values = explode( $separator, $data[ $field->getFieldName() ] ) ) {
							return;
						}
					} else {
						$values = array( $data[ $field->getFieldName() ] );
					}
					if ( ! isset( $data[ $field->getFieldName() . '-separator2' ] )
						|| ( ! $separator2 = trim( $data[ $field->getFieldName() . '-separator2' ] ) )
					) {
						$separator2 = '|';
					}
					foreach ( array_keys( $values ) as $key ) {
						if ( ! $values[ $key ] = $this->_getTimeRange( $values[ $key ], $separator2 ) ) {
							unset( $values[ $key ] );
						}
					}
					$values = array_values( $values );
				}
				return $values;
			case 'field_string':
			case 'field_text':
			case 'field_url':
			case 'field_email':
			case 'field_phone':
			case 'field_number':
			case 'field_color':
			case 'field_icon':
			case 'field_choice':
			case 'field_date':
			default:
				if ( ! isset( $data[ $field->getFieldName() ] ) ) {
					return;
				}

				if ( isset( $data[ $field->getFieldName() . '-separator' ] )
					&& ( $separator = trim( $data[ $field->getFieldName() . '-separator' ] ) )
				) {
					if ( ! $values = explode( $separator, $data[ $field->getFieldName() ] ) ) {
						return;
					}
				} else {
					$values = array( $data[ $field->getFieldName() ] );
				}
				return array_map( 'trim', $values );
		}
	}

	protected function _getTimeRange( $str, $separator = '-' ) {
		if ( ! $range = explode( $separator, $str ) ) {
			return;
		}

		$range = array_map( 'trim', $range );
		if ( ! $range[0]
			|| false === ( $range[0] = $this->_application->Form_Validate_time( $range[0] ) )
		) {
			return;
		}

		$end = null;
		if ( isset( $range[1] )
			&& strlen( $range[1] )
			&& false !== ( $range[1] = $this->_application->Form_Validate_time( $range[1] ) )
		) {
			$end = mktime( $range[1][0], $range[1][1], 0 );
		}

		return array(
			'start'   => mktime( $range[0][0], $range[0][1], 0 ),
			'end'     => $end,
			'day'     => isset( $range[2] ) ? $range[2] : null,
			'all_day' => isset( $range[3] ) ? $range[3] : null,
		);
	}
}
