<?php

class RHC_CSV_Import {
	public $id;
	public $open;
	public $capability;

	public function __construct( $plugin_id = 'rhc', $capability = 'manage_options', $open = false ) {
		if ( ! current_user_can( $capability ) ) {
			return false;
		}

		$this->id = $plugin_id;
		$this->capability = $capability;
		$this->open = $open;

		add_filter( "pop-options_{$this->id}", array( $this, 'options' ), 9999, 1 );
		add_action( "pop_admin_head_{$this->id}", array( $this, 'admin_head'), 10, 1 );
		add_action( 'wp_ajax_rhci_column_mapping', array( $this, 'wp_ajax_column_mapping' ) );
		add_action( 'wp_ajax_rhci_import', array( $this, 'wp_ajax_import' ) );
	}

	public function options( $t ) {
		$i                      = count( $t );
		$t[ $i ]                = (object) array();
		$t[ $i ]->id            = 'rhci-csv'; 
		$t[ $i ]->open          = $this->open;
		$t[ $i ]->label         = __( 'CSV', 'rhci' );
		$t[ $i ]->right_label   = __( 'CSV', 'rhci' );
		$t[ $i ]->page_title    = __( 'CSV', 'rhci' );
		$t[ $i ]->theme_option  = true;
		$t[ $i ]->priority      = 10;
		$t[ $i ]->plugin_option = true;
		$t[ $i ]->options       = array();

		$t[ $i ]->options[] = (object) array(
			'id'   => 'rhci_container',
			'type' => 'div_start',
		);

		$t[ $i ]->options[] = (object) array(
			'id'   => 'rhci_main',
			'type' => 'div_start',
		);

		$t[ $i ]->options[] = (object) array(
			'id'            => 'rhci_csv_interface',
			'label'         => 'Choose what to import',
			'type'          => 'select',
			'default'		=> 'events',
			'options'       => array(
				'events'              => __( 'Events', 'rhci' ),
				'taxonomy_terms_data' => __( 'Taxonomy Terms Data', 'rhci' ),
			),
			'el_properties' => array(),
			'save_option'   => false,
			'load_option'   => true
		);

		$t[ $i ]->options[] = (object) array(
			'type'  => 'subtitle',
			'label' => __( 'CSV File Uploading', 'rhci' ),
		);

		$t[ $i ]->options[] = (object) array(
			'id'          => 'rhci_upload_file',
			'type'        => 'button',
			'label'       => __( 'Upload', 'rhci' ),
			'class'       => 'button-secondary',
			'description' => __( 'Choose the import file.', '' ),
		);

		$t[ $i ]->options[] = (object) array(
			'id'   => 'rhci_events',
			'type' => 'div_start',
		);

		$t[ $i ]->options[] = (object) array(
			'id'            => 'rhci_post_type',
			'name'          => 'rhci_options[post_type]',
			'type'          => 'select',
			'label'         => __( 'Post Type', 'rhci' ),
			'options'       => $this->get_post_types(),
			'default'       => RHC_EVENTS,
			'el_properties' => array( 'class' => 'widefat' ),
			'save_option'   => false,
			'load_option'   => true,
		);

		$t[ $i ]->options[] = (object) array(
			'id'            => 'rhci_post_status',
			'name'          => 'rhci_options[post_status]',
			'type'          => 'select',
			'label'         => __( 'Events Status', 'rhci' ),
			'options'       => get_post_statuses(),
			'default'       => 'publish',
			'el_properties' => array( 'class' => 'widefat' ),
			'save_option'   => false,
			'load_option'   => true,
		);

		$t[ $i ]->options[] = (object) array(
			'id'            => 'rhci_post_author',
			'name'          => 'rhci_options[post_author]',
			'type'          => 'select',
			'label'         => __( 'Events Author', 'rhci' ),
			'options'       => $this->get_users(),
			'default'       => get_current_user_id(),
			'el_properties' => array( 'class' => 'widefat' ),
			'save_option'   => false,
			'load_option'   => true,
		);

		$t[ $i ]->options[] = (object) array(
			'type' => 'div_end',
		);

		$t[ $i ]->options[] = (object) array(
			'id'   => 'rhci_taxonomy_terms_data',
			'type' => 'div_start',
		);

		$t[ $i ]->options[] = (object) array(
			'id'            => 'rhci_taxonomy',
			'name'          => 'rhci_options[taxonomy]',
			'type'          => 'select',
			'label'         => __( 'Taxonomy', 'rhci' ),
			'options'       => $this->taxonomies_to_options_args( $this->get_taxonomies( RHC_EVENTS ) ),
			'el_properties' => array( 'class' => 'widefat' ),
			'save_option'   => false,
			'load_option'   => true,
		);

		$t[ $i ]->options[] = (object) array(
			'type' => 'div_end',
		);

		$t[ $i ]->options[] = (object) array(
			'id'            => 'rhci_col_mapping',
			'name'          => 'rhci_options[has_col_names]',
			'type'          => 'yesno',
			'label'         => __( 'First row has column names', 'rhci' ),
			'default'       => '1',
			'el_properties' => array(),
			'save_option'   => false,
			'load_option'   => true,
		);

		$t[ $i ]->options[] = (object) array(
			'type' => 'div_end',
		);

		$t[ $i ]->options[] = (object) array(
			'id'   => 'rhci_col_map',
			'type' => 'div_start'
		);

		$t[ $i ]->options[] = (object) array(
			'type'  => 'subtitle',
			'label' => __( 'Column Mapping', 'rhci' ),
		);

		$t[ $i ]->options[] = (object) array(
			'type' => 'div_end',
		);

		$t[ $i ]->options[] = (object) array(
			'type' => 'div_end',
		);

		$t[ $i ]->options[] = (object) array(
			'id'    => 'rhci_import',
			'type'  => 'button',
			'label' => __( 'Next', 'rhci' ),
			'class' => 'button-primary rhci_import',
		);

		$t[ $i ]->options[] = (object) array(
			'type' => 'clear',
		);

		return $t;
	}

	public function admin_head() {
		wp_localize_script( 'rhci-import', 'RHCI', array(
			'upload_button' => array(
				'upload' => __( 'Upload', 'rhci' ),
				'change' => __( 'Change', 'rhci' ),
			),
			'no_file'       => __( 'Please, upload the import file.', 'rhci' ),
		) );
		wp_enqueue_media();
		wp_enqueue_style( 'rhci-import' );
		wp_enqueue_script( 'rhci-import' );
	}

	public function get_post_types() {
		$post_types = array();
		foreach ( get_post_types( array(), 'objects', 'and' ) as $post_type => $post_type_obj ) {
			if ( in_array( $post_type, array( 'attachment', 'revision', 'nav_menu_item' ) ) )
				continue;
			
			$post_types[ $post_type ] = $post_type_obj->labels->name;
		}
		
		return $post_types;
	}

	public function get_users() {
		$users = array();
		foreach ( get_users( array( 'fields' => array( 'ID', 'user_login' ) ) ) as $user ) {
			$users[ $user->ID ] = $user->user_login;
		}
		
		return $users;
	}

	public function wp_ajax_column_mapping() {
		if ( ! $this->ajax_security_check( $_POST['_nonce'], $this->id ) ) {
			return false;
		}

		$data = $this->get_import_data( $_POST );
		$file_handle = fopen( $data->file->path, 'r' );
		$first_row = fgetcsv( $file_handle );
		fclose( $file_handle );

		$column_names = array();
		if ( $data->options->has_col_names ) {
			$column_names = $first_row;
		} else {
			$column_count = count( $first_row );
			$i = 0;

			while ( $i < $column_count ) {
				$column_names[] = $this->get_name_from_number( $i );
				$i++;
			}
		}

		$output = $this->get_html_col_map( $column_names, $data );

		$response = (object) array(
			'MSG'  => 'OK',
			'html' => $output,
		);
		die( json_encode( $response ) );
	}

	public function wp_ajax_import() {
		if ( ! $this->ajax_security_check( $_POST['_nonce'], $this->id ) ) {
			return false;
		}

		$data = $this->get_import_data( $_POST );
		$file_handle = fopen( $data->file->path, 'r' );

		if ( isset( $data->options->has_col_names ) ) {
			fgetcsv( $file_handle );
		}

		$rows = array();
		
		while ( ! feof( $file_handle ) ) {
			$row = fgetcsv( $file_handle );
			
			if ( is_array( $row ) && count( $row ) > 0 ) {
				$filtered_row = array_filter( $row );

				if ( $filtered_row ) {
					$rows[] = $filtered_row;
				}
			}
		}

		fclose( $file_handle );
		
		if ( ! $rows ) {
			return false;
		}

		$output = $this->do_import( $rows, $data );
		$response = (object) array(
			'MSG'  => 'OK',
			'html' => $output,
		);
		die( json_encode( $response ) );
	}

	public function get_name_from_number( $num ) {
		$numeric = $num % 26;
		$letter = chr( 65 + $numeric );
		$num2 = intval( $num / 26 );
	
		if ( $num2 > 0 ) {
			return $this->get_name_from_number( $num2 - 1 ) . $letter;
		} else {
			return $letter;
		}
	}

	public function get_html_select_options( $options ) {
		$html = sprintf( '<option selected value>%s</option>', __( '--ignore--', 'rhci' ) );

		foreach ( $options as $key => $option ) {
			$html .= sprintf( '<option value="%1$s">%2$s</option>', $key, $option );
		}

		return $html;
	}

	private function ajax_security_check( $nonce, $action ) {
		if ( current_user_can( $this->capability ) && wp_verify_nonce( $nonce, $action ) ) {
			return true;
		}

		return false;
	}
	
	public function get_attachment_id_by_url( $url ) {
		global $wpdb;
		$url = trim( $url );
		$attachment = $wpdb->get_col( $wpdb->prepare(
			"
			SELECT ID
			FROM $wpdb->posts
			WHERE guid = %s
			",
			$url
		) );

		return $attachment[0];
	}

	public function get_taxonomies( $post_type, $output = 'objects' ) {
		$taxonomies = array();
		$exclude = array( 'post_tag', 'post_format' );

		foreach ( get_object_taxonomies( $post_type, $output ) as $taxonomy => $taxonomy_obj ) {
			if ( ! in_array( $taxonomy, $exclude ) ) {
				$taxonomies[ $taxonomy ] = $taxonomy_obj;		
			}
		}

		return $taxonomies;
	}

	public function taxonomies_to_options_args( $taxonomies ) {
		if ( ! is_array( $taxonomies ) || ! $taxonomies ) {
			return;
		}

		$options_args = array();

		foreach ( $taxonomies as $taxonomy => $taxonomy_obj ) {
			$options_args[ $taxonomy ] = $taxonomy_obj->labels->name;
		}

		return $options_args;
	}

	public function get_html_wp_notice( $message, $type ) {
		return sprintf( '<div id="message" class="notice %2$s"><p>%1$s</p></div>', $message, $type ); 
	}

	public function get_form_data( $str ) {
		$data = array();
		parse_str( $str, $data );

		return $data;
	}

	public function get_import_data( $raw_data ) {
		$file_id = intval( $raw_data['file_id'] );
		$form_data = $this->get_form_data( $raw_data['data'] );
	
		$data = (object) array(
			'file'          => (object) array(
				'id'   => $file_id,
				'path' => get_attached_file( $file_id ),
			),
			'csv_interface' => filter_var( $form_data['rhci_csv_interface'], FILTER_SANITIZE_STRING ),
			'options'       => (object) $form_data['rhci_options' ],
		);

		if ( isset( $form_data['rhci_col_map'] ) ) {
			$data->col_map = $form_data['rhci_col_map'];
		}

		if ( empty( $file_id ) || empty( $data->csv_interface ) || empty( $data->options ) ) {
			return false;
		}

		return $data;
	}

	public function set_postinfo_boxes( $post_ID ) {
		global $rhc_plugin;
		
		$postinfo_boxes = $rhc_plugin->get_option( 'postinfo_boxes', false, true );
		if ( false !== $postinfo_boxes ) {
			foreach ( $postinfo_boxes as $id => $o ) {
				foreach ( $o->data as $data_id => $data_o ) {
					$postinfo_boxes[ $id ]->data[ $data_id ]->post_ID = $post_ID;
				}
			}
			update_post_meta( $post_ID, 'postinfo_boxes', $postinfo_boxes );
		}
	}

	public function set_auw_cta( $post_ID ) {
		$metas = array(
			'rhc_auw_cta_label'  => '',
			'rhc_auw_cta_url'    => '',
			'rhc_auw_cta_target' => '_self',
		);

		foreach ( $metas as $meta_key => $meta_value ) {
			update_post_meta( $post_ID, $meta_key, $meta_value );
		}
	}

	public function set_datetime( $post_ID ) {
		global $wpdb;
		$fc_start = get_post_meta( $post_ID, 'fc_start', true );
		$fc_end = get_post_meta( $post_ID, 'fc_end', true );
	
		if ( ! $fc_start || ! $fc_end ) {
			return false;
		}

		$fc_start_time = get_post_meta( $post_ID, 'fc_start_time', true );
		$fc_end_time = get_post_meta( $post_ID, 'fc_end_time', true );
		$fc_allday = ( $fc_start_time && $fc_end_time ) ? '0' : '1';
		
		$this->update_datetime(
			$post_ID,
			array( 'fc_start_datetime', 'fc_range_start' ),
			$fc_start,
			( $fc_start_time ) ? $fc_start_time : '00:00'
		);
		$this->update_datetime(
			$post_ID,
			array( 'fc_end_datetime', 'fc_range_end' ),
			$fc_end,
			( $fc_end_time ) ? $fc_end_time : '00:00'
		);
		$wpdb->insert(
			"{$wpdb->prefix}rhc_events",
			array(
				'event_start' => sprintf( '%s %s', $fc_start, ( $fc_start_time ) ? $fc_start_time : '00:00' ),
				'event_end'   => sprintf( '%s %s', $fc_end, ( $fc_start_time ) ? $fc_end_time : '00:00' ),
				'post_id'     => $post_ID,
				'allday'      => $fc_allday
			)
		);
	}

	public function update_datetime( $post_ID, $keys, $date, $time ) {
		if ( is_array( $keys ) ) {
			foreach( $keys as $key ) {
				update_post_meta( $post_ID, $key, sprintf( '%s %s',
					date( 'Y-m-d', strtotime( $date ) ),
					date( 'H:i:s', strtotime( $time ) )
				) );
			}
		}
	}

	public function get_html_col_map( $column_names, $data ) {
		global $rhc_plugin;

		$csv_interface = ( $data->csv_interface ) ? $data->csv_interface : 'events';
		if ( 'events' == $csv_interface ) {
			$csv_fields = array(
				'post_title'        => __( 'Event Name', 'rhci' ),
				'post_name'         => __( 'Event Permalink', 'rhci' ),
				'post_content'      => __( 'Event Content', 'rhci' ),
				'post_excerpt'      => __( 'Event Excerpt', 'rhci' ),
				'fc_start'          => __( 'Start Date', 'rhci' ),
				'fc_start_time'     => __( 'Start Time', 'rhci' ),
				'fc_end'            => __( 'End Date', 'rhci' ),
				'fc_end_time'       => __( 'End Time', 'rhci' ),
			);

			$extra_columns = array(
				'post_status'       => __( 'Event Status', 'rhci' ),
				'post_author'       => __( 'Event Author', 'rhci' ),
				'fc_color'          => __( 'Event Color', 'rhci' ),
				'fc_text_color'     => __( 'Text Color', 'rhci' ),
				'_thumbnail_id'     => __( 'WordPress Featuerd Image', 'rhci' ),
				'rhc_top_image'     => __( 'Event Page Top Image', 'rhci' ),
				'rhc_dbox_image'    => __( 'Event Detail Box Image', 'rhci' ),
				'rhc_tooltip_image' => __( 'Event Featured Image', 'rhci' ),
				'rhc_month_image'   => __( 'Month View Image', 'rhci' ),
			);

			foreach ( $extra_columns as $column_key => $column_name ) {
				if ( '1' == $rhc_plugin->get_option( "rhci_extra_column_{$column_key}" ) ) {
					$csv_fields[ $column_key ] = $column_name;			
				}
			}

			$csv_fields = $csv_fields + $this->taxonomies_to_options_args( $this->get_taxonomies( $data->options->post_type ) );
		} elseif ( 'taxonomy_terms_data' == $csv_interface ) {
			$term_fields = array(
				'name'        => __( 'Name', 'rhci' ),
				'slug'        => __( 'Slug', 'rhci' ),
				'description' => __( 'Description', 'rhci' ),
			);

			$term_metas = array(
				'content'          => __( 'HTML Description', 'rhci' ),
				'phone'            => __( 'Phone', 'rhci' ),
				'email'            => __( 'Email', 'rhci' ),
				'website'          => __( 'Website', 'rhci' ),	
				'websitelabel'     => __( 'Website Label', 'rhci' ),
				'website_nofollow' => __( 'No Follow', 'rhci' ),
				'image'            => __( 'Image', 'rhci' ),
			);

			$venue_metas = array(
				'address'              => __( 'Address', 'rhci' ),
				'city'                 => __( 'City', 'rhci' ),
				'state'                => __( 'State/Province/Other', 'rhci' ),
				'zip'                  => __( 'Postal code', 'rhci' ),	
				'iso3166_country_code' => __( 'Country ISO3166 code', 'rhci' ),	
				'country'              => __( 'Country', 'rhci' ),	
				'gaddress'             => __( 'Google address', 'rhci' ),
				'glat'                 => __( 'Latitude', 'rhci' ),
				'glon'                 => __( 'Longitude', 'rhci' ),
				'gzoom'                => __( 'Zoom', 'rhci' ),
				'ginfo'                => __( 'Text for info windows', 'rhci' ),
			);

			if ( 'venue' == $data->options->taxonomy ) {
				$csv_fields = array_merge( $term_fields, $term_metas, $venue_metas );
				unset( $csv_fields['description'] );
			} elseif ( 'organizer' == $data->options->taxonomy ) {
				$csv_fields = array_merge( $term_fields, $term_metas );
			} else {
				$csv_fields = $term_fields;
			}
		}

		$select_options = $this->get_html_select_options( $csv_fields );
		$output = '';

		foreach ( $column_names as $key => $column_name ) {
			$output .= '<div class="pt-option pt-option-select">';
				$output .= sprintf( '<span class="pt-label pt-type-select">%1$s</span>', $column_name );
				$output .= sprintf( '<select name="rhci_col_map[%1$s]">', $key );
					$output .= $select_options;
				$output .= '</select>';
			$output .= '</div>';
		}

		return $output;
	}

	public function do_import( $rows, $data ) {
		if ( 'events' == $data->csv_interface ) {
			return $this->do_import_events( $rows, $data );
		} elseif ( 'taxonomy_terms_data' == $data->csv_interface ) {
			return $this->do_import_tax_terms_data( $rows, $data );
		}
	}

	public function do_import_events( $rows, $data ) {
		$post_fields = array(
			'post_title'   => '',
			'post_name'    => '',
			'post_content' => '',
			'post_excerpt' => '',
			'post_author'  => get_current_user_id(),
			'post_status'  => 'publish',
			'post_type'    => RHC_EVENTS,
		);

		$rhc_meta = array(
			'fc_start',
			'fc_start_time',
			'fc_end',
			'fc_end_time',
			'fc_color',
			'fc_text_color',
		);

		$rhc_images = array(
			'_thumbnail_id',
			'rhc_top_image',
			'rhc_dbox_image',
			'rhc_tooltip_image',
			'rhc_month_image',
		);
		
		$meta_fields = array_merge( $rhc_meta, $rhc_images );
		$taxonomies = $this->get_taxonomies( $data->options->post_type );
		$events_count = 0;

		if ( is_object( $data->options ) ) {
			foreach ( $data->options as $option_name => $option_value ) {
				if ( array_key_exists( $option_name, $post_fields ) ) {
					$post_fields[ $option_name ] = $option_value;
				}
			}
		}

		foreach ( $rows as $row ) {
			$post_args = $post_fields;
			$post_meta = array();
			$post_terms = array();

			if ( is_array( $data->col_map ) ) {
				foreach ( $data->col_map as $col_numb => $meta_name ) {
					if ( array_key_exists( $meta_name, $post_fields ) ) {
						$post_args[ $meta_name ] = isset( $row[ $col_numb ] ) ? mb_convert_encoding( $row[ $col_numb ], 'UTF-8', 'UTF-8' ) : ' ';
					}

					if ( in_array( $meta_name, $meta_fields ) ) {
						if ( in_array( $meta_name, $rhc_images ) ) {
							$post_meta[ $meta_name ] = $this->get_attachment_id_by_url( $row[ $col_numb ] );
						} else {
							$post_meta[ $meta_name ] = $row[ $col_numb ];
						}
					}
					
					if ( array_key_exists( $meta_name, $taxonomies ) ) {
						$post_terms[ $meta_name ] = explode( '|', $row[ $col_numb ] );
					}
				}
			}

			$post_ID = wp_insert_post( $post_args );

			if ( ! is_wp_error( $post_ID ) ) {
				$events_count++;
			}

			if ( ! empty( $post_meta ) ) {
				if ( ! isset( $post_meta['fc_start_time'] ) || ! isset( $post_meta['fc_end_time'] ) ) {
					update_post_meta( $post_ID, 'fc_allday', '1' );
				}

				foreach ( $post_meta as $meta_key => $meta_value ) {
					if ( $meta_key == 'fc_start' || $meta_key == 'fc_end' ) {
						$meta_value = date( 'Y-m-d', strtotime( $meta_value ) );
					} elseif ( $meta_key == 'fc_start_time' || $meta_key == 'fc_end_time' ) {
						$meta_value = date( 'H:i', strtotime( $meta_value ) );
					}

					update_post_meta( $post_ID, $meta_key, $meta_value );
				}
			}

			$this->set_required_meta( $post_ID );

			if ( ! empty( $post_terms ) ) {
				foreach ( $post_terms as $taxonomy => $terms ) {
					wp_set_object_terms( $post_ID, $terms, $taxonomy );
				}
			}
		}

		return $this->get_html_wp_notice( sprintf( _n( 'Congratulations! %s Event was successfully imported.', 'Congratulations! %s Events were successfully imported.', $events_count, 'rhci' ), number_format_i18n( $events_count ) ), 'updated' );
	}

	public function do_import_tax_terms_data( $rows, $data ) {
		foreach( $rows as $row ) {
			$term_args = array();
			$term_metas = array();
			
			if ( is_array( $data->col_map ) ) {
				foreach ( $data->col_map as $col_numb => $meta_name ) {
					if ( isset( $row[ $col_numb ] ) ) {
						$meta_value = trim( $row[ $col_numb ] );					
					
						if ( in_array( $meta_name, array( 'slug', 'name', 'description' ) ) ) {
							$term_args[ $meta_name ] = $meta_value;
						} else {
							$term_metas[ $meta_name ] = $meta_value;
						}
					}
				}
			}

			if ( ! empty( $term_args['slug'] ) ) {
				$term = get_term_by( 'slug', $term_args['slug'], $data->options->taxonomy, ARRAY_A );
			} elseif ( ! empty( $term_args['name'] ) ) {
				$term = get_term_by( 'name', $term_args['name'], $data->options->taxonomy, ARRAY_A );
			} else {
				continue;
			}

			if ( $term ) {
				wp_update_term( $term['term_id'], $data->options->taxonomy, $term_args );
			} else {
				$term_name = ( ! empty( $term_args['name'] ) ) ? $term_args['name'] : $term_args['slug'];
				$term = wp_insert_term( $term_name, $data->options->taxonomy, $term_args );
			}
		
			if ( $term_metas ) {
				foreach ( $term_metas as $meta_key => $meta_value ) {
					if ( 'website_nofollow' == $meta_key ) {
						$meta_value = ( '1' == $meta_value ) ? 'rel="nofollow"' : '';
					}

					update_term_meta( $term['term_id'], $meta_key, $meta_value );
				}
			}
		}

		return $this->get_html_wp_notice( __( 'Congratulations! Terms data was successfully imported.', 'rhci' ), 'updated' );
	}

	public function set_required_meta( $post_ID ) {
		$this->set_postinfo_boxes( $post_ID );
		$this->set_auw_cta( $post_ID );
		$this->set_datetime( $post_ID );
	}
}
