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

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

abstract class AbstractTermsCSVImporter extends AbstractImporter {

	protected $_termTitles = array();

	protected function _getTaxonomyBundle( Field $field ) {
		return $field->getTaxonomyBundle();
	}

	public function csvImporterSettingsForm( Field $field, array $settings, $column, $enclosure, array $parents = array() ) {
		$form     = array(
			'type' => array(
				'#type'          => 'select',
				'#title'         => __( 'Taxonomy term data type', 'directories-pro' ),
				'#description'   => __( 'Select the type of data used to specify terms.', 'directories-pro' ),
				'#options'       => array(
					'id'    => __( 'ID', 'directories-pro' ),
					'slug'  => __( 'Slug', 'directories-pro' ),
					'title' => __( 'Title', 'directories-pro' ),
				),
				'#default_value' => 'slug',
				'#horizontal'    => true,
			),
		);
		$reserved = array();
		if ( ( $taxonomy_bundle = $this->_getTaxonomyBundle( $field ) )
			&& ! empty( $taxonomy_bundle->info['is_hierarchical'] )
		) {
			$form['h_separator'] = array(
				'#type'          => 'textfield',
				'#title'         => __( 'Hierarchy separator', 'directories-pro' ),
				'#description'   => __( 'Specify a character (if any) used to indicate hierarchy in taxonomy term titles.', 'directories-pro' ),
				'#default_value' => '>',
				'#horizontal'    => true,
				'#states'        => array(
					'visible' => array(
						sprintf( 'select[name="%s[type]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array( 'value' => 'title' ),
					),
				),
			);
			$reserved            = array( 'h_separator' => __( 'Hierarchy separator', 'directories-pro' ) );
		}
		return $form + $this->_acceptMultipleValues( $field, $enclosure, $parents, $reserved );
	}

	public function csvImporterDoImport( Field $field, array $settings, $column, $value, &$formStorage, array &$logs ) {
		$value = str_replace( '&amp;', '&', $value );
		if ( ! empty( $settings['_multiple'] ) ) {
			if ( ! $values = explode( $settings['_separator'], $value ) ) {
				return;
			}
		} else {
			$values = array( $value );
		}
		if ( ! $values = array_filter(
			$values,
			function ( $value ) {
				return strlen( trim( $value ) ) > 0; }
		) ) {
			return;
		}
		$ret = array();
		switch ( $settings['type'] ) {
			case 'title':
				if ( ! $bundle = $this->_getTaxonomyBundle( $field ) ) {
					return;
				}

				$values_original = $values;
				$terms_by_title  = array();
				if ( ! empty( $this->_termTitles[ $bundle->name ] ) ) {
					foreach ( array_keys( $values ) as $i ) {
						$title = strtolower( $values[ $i ] );
						if ( $term_id = array_search( $title, $this->_termTitles[ $bundle->name ] ) ) {
							$terms_by_title[ $title ] = $this->_getValueForImportTerm( $term_id );
							unset( $values[ $i ] );
						}
					}
				} else {
					$this->_termTitles[ $bundle->name ] = array();
				}
				if ( ! empty( $values ) ) {
					$values_with_parents = array();
					if ( isset( $settings['h_separator'] )
						&& strlen( $settings['h_separator'] )
					) {
						foreach ( array_keys( $values ) as $i ) {
							if ( strpos( $values[ $i ], $settings['h_separator'] ) > 0 ) {
								$values_with_parents[ $i ] = $values[ $i ];
								unset( $values[ $i ] );
							}
						}
					}
					if ( ! empty( $values ) ) {
						$terms = $this->_application->Entity_Types_impl( $bundle->entitytype_name )->entityTypeEntitiesByTitles( $bundle->name, $values );
						foreach ( $terms as $term ) {
							$title = strtolower( $term->getTitle() );
							$this->_termTitles[ $bundle->name ][ $term->getId() ] = $title;
							$terms_by_title[ $title ]                             = $this->_getValueForImportTerm( $term->getId() );
						}
						foreach ( $values as $title ) {
							if ( ! in_array( strtolower( $title ), $this->_termTitles[ $bundle->name ] ) ) {
								try {
									$term = $this->_application->Entity_Save(
										$bundle,
										array(
											'title'  => $title,
											'parent' => 0,
										)
									);
								} catch ( Exception\IException $e ) {
									$logs['error'][] = $e->getMessage();
									continue;
								}
								$title = strtolower( $term->getTitle() );
								$this->_termTitles[ $bundle->name ][ $term->getId() ] = $title;
								$terms_by_title[ $title ]                             = $this->_getValueForImportTerm( $term->getId() );
							}
						}
					}
					foreach ( array_keys( $values_with_parents ) as $i ) {
						$values_with_parents_arr = explode( $settings['h_separator'], $values_with_parents[ $i ] );
						$parent_term_id          = 0;
						foreach ( array_keys( $values_with_parents_arr ) as $j ) {
							$values_with_parents_arr[ $j ] = trim( $values_with_parents_arr[ $j ] );
							if ( empty( $parent_term_id ) ) {
								$term = $this->_application->Entity_Types_impl( $bundle->entitytype_name )->entityTypeEntityByTitle( $bundle->name, $values_with_parents_arr[ $j ] );
							} else {
								$terms = $this->_application->Entity_Query( $bundle->entitytype_name, $bundle->name )
									->fieldIs( 'parent', $parent_term_id )
									->fieldIs( 'title', $values_with_parents_arr[ $j ] )
									->fetch( 1 );
								$term  = array_shift( $terms );
							}
							if ( ! $term ) {
								try {
									$term = $this->_application->Entity_Save(
										$bundle,
										array(
											'title'  => $values_with_parents_arr[ $j ],
											'parent' => $parent_term_id,
										)
									);
								} catch ( Exception\IException $e ) {
									$logs['error'][] = sprintf( 'Failed importing %s. Error: %s', $values_with_parents_arr[ $j ], $e->getMessage() );
									continue 2;
								}
							}
							$parent_term_id = $term->getId();
						}
						$title = strtolower( $values_with_parents[ $i ] );
						$this->_termTitles[ $bundle->name ][ $term->getId() ] = $title;
						$terms_by_title[ $title ]                             = $this->_getValueForImportTerm( $term->getId() );
					}
				}
				foreach ( $values_original as $title ) {
					$title = strtolower( $title );
					$ret[] = isset( $terms_by_title[ $title ] ) ? $terms_by_title[ $title ] : null;
				}
				break;
			case 'slug':
				if ( ! $bundle = $this->_getTaxonomyBundle( $field ) ) {
					return;
				}

				$terms         = $this->_application->Entity_Types_impl( $bundle->entitytype_name )->entityTypeEntitiesBySlugs( $bundle->name, $values );
				$terms_by_slug = array();
				foreach ( $terms as $term ) {
					$terms_by_slug[ $term->getSlug() ] = $this->_getValueForImportTerm( $term->getId() );
				}
				foreach ( $values as $slug ) {
					$ret[] = isset( $terms_by_slug[ $slug ] ) ? $terms_by_slug[ $slug ] : null;
				}
				break;
			case 'id':
				foreach ( $values as $term_id ) {
					$ret[] = $this->_getValueForImportTerm( $term_id );
				}
				break;
		}
		return $ret;
	}

	protected function _getValueForImportTerm( $termId ) {
		return $termId;
	}
}
