<?php
if ( ! class_exists( 'NISHIKI_BLOCKS_PRO_FILTER_SEARCH_TERMS' ) ) {
	class NISHIKI_BLOCKS_PRO_FILTER_SEARCH_TERMS {

		const BLOCK_PREFIX = 'nishiki-blocks-pro';
		const BLOCK_FUNC_PREFIX = 'nishiki_blocks_pro';

		/**
		 * Construct.
		 */
		public function __construct() {
			add_filter( 'register_block_type_args', array( $this, 'custom_modify_block_args' ), 10, 2 );
	
			// クエリー追加
			add_filter( 'query_vars', [ $this, 'add_query_vars' ] );
	
			// 検索結果フィルター
			add_action( 'pre_get_posts', [ $this, 'search_filter' ] );
	
			// クエリーセット
			add_action( 'parse_query', [ $this, 'set_query' ] );

		}
		
		/**
		 * クエリーセット
		 *
		 */
		public function set_query( $query ){
			if ( isset( $_GET[ self::BLOCK_FUNC_PREFIX . '_filter_search' ] ) ) {
				$query->is_home = false;
				$query->is_search = true;
			}
			//var_dump($query);
		}
	
		/**
		 * 検索結果フィルター
		 *
		 * @param [type] $query クエリー
		 * @return void
		 */
		public function search_filter( $query ) {
			if ( ! is_admin() && $query->is_main_query() ) {
				if ( $query->is_search ) {
	
					$taxonomies = $this->get_taxonomies();
	
					$form_input_types = [ 'checkbox', 'radio', 'select' ];
	
					foreach ( $taxonomies as $taxonomy ) {
						if( $taxonomy->show_in_rest ){
							foreach( $form_input_types as $form_input_type ){
								$name = self::BLOCK_FUNC_PREFIX . '_' . $form_input_type . '_' . $taxonomy->name;
								if( ! empty( $query->query[ $name ] ) ){
									if( is_array( $query->query[ $name ] ) ){
										foreach( $query->query[ $name ] as $term_id ){
											$tax_query[] = self::create_tax_query( $term_id, $taxonomy->name );
										}
									} else {
										$tax_query[] = self::create_tax_query( $query->query[ $name ], $taxonomy->name );
									}
								}
							}
						}
					}
	
					// relation
					if( get_query_var( 'relation' ) ){
						$tax_query['relation'] = get_query_var( 'relation' );
					} else {
						$tax_query['relation'] = 'or';
					}

					// post type
					if( isset( $_GET['post_type'] ) && ! empty( $_GET['post_type'] ) ){

						if( is_array( $_GET['post_type'] ) ){
							$post_types = array_map( 'htmlspecialchars', $_GET['post_type'] );
						}

						if( ! empty( $post_types ) ){
							$query->set( 'post_type', $post_types );
						}

					}

					$query->set( 'tax_query', $tax_query );
				}
			}
		}
	
		/**
		 * クエリー追加
		 *
		 * @param array $vars 配列
		 * @return $vars
		 */
		public function add_query_vars( $vars ) {
			$taxonomies = $this->get_taxonomies();
	
			foreach ( $taxonomies as $taxonomy ) {
				if( $taxonomy->show_in_rest ){
					$vars[] = 'checkbox_' . $taxonomy->name;
					$vars[] = 'radio_' . $taxonomy->name;
					$vars[] = 'select_' . $taxonomy->name;
				}
			}
	
			$vars[] = self::BLOCK_FUNC_PREFIX . '_filter_search';
				
			return $vars;
		}
	
		/**
		 * tax_query追加
		 */
		public function create_tax_query( $term_id, $taxonomy ){
	
			$data = [
				'taxonomy' => $taxonomy,
				'field' => 'term_id',
				'terms' => $term_id,
				'operator' => 'IN',
			];
	
			return $data;
		}

		/**
		 * ダイナミックブロックうに関する設定を追加
		 */
		public function custom_modify_block_args( $args, $block_type ) {
			$attributes = array(
							'postType' => array(
								'type'    => 'string',
								'default' => 'post',
							),
							'displayType' => array(
								'type'    => 'string',
								'default' => 'checkbox',
							),
							'selectTaxonomy' => array(
								'type'    => 'string',
								'default' => 'category',
							),
							'displayCount' => array(
								'type'    => 'boolean',
							),
							'widthDesktop' => array(
								'type'    => 'string',
								'default' => '50',
							),
							'widthTablet' => array(
								'type'    => 'string',
								'default' => '50',
							),
							'widthSmartPhone' => array(
								'type'    => 'string',
								'default' => '100',
							),
							'term_id' => array(
								'type'    => 'string',
								'default' => -1,
							),
							'orderBy'	=> array(
								'type'    => 'string',
								'default' => 'name',
							),
							'order'	=> array(
								'type'    => 'string',
								'default' => 'ASC',
							),
						);
			
			$taxonomies = $this->get_taxonomies();
	
			//　ここにタクソノミーごとのタームを配列で保存しておく
			foreach( $taxonomies as $taxonomy ){
				if( $taxonomy->show_in_rest ){

					$term_ids = '[]';
	
					$terms = get_terms( 
						array(
							'taxonomy' => $taxonomy->name,
						),
						array(
							'hide_empty' => false,
						)
					);
			
					if( ! empty( $terms ) ){
						$term_ids = json_encode( array_column( $terms,'term_id' ) );
					}
			
					$attributes[ 'terms_' . $taxonomy->name ] = array(
						'type'    => 'object',
						'default'  => array(
							'label' => $taxonomy->label,
							'ids' => $term_ids,
						),
					);
				}
			}

			if ( 'nishiki-blocks-pro/filter-search-terms' === $block_type ) {
				$args['attributes'] = $attributes;
				$args['render_callback'] = array( $this, 'block_callback' );
			}

			return $args;
		}
	
		/**
		 * レンダリング
		 *
		 * @param array $attributes 属性
		 * @return $card
		 */
		public function block_callback( $attributes, $content, $block ) {

			global $wp_query;
	
			//var_dump($wp_query->query);
	
			//var_dump($attributes[ 'terms_category' ]);
	
			$output  = '';
			$count   = false;
			$orderby = $attributes['orderBy'];
			$order   = $attributes['order'];
			$classes = [];
			$selected_post_type_taxonomies = [];

			$classes[] = 'wp-block-nishiki-blocks-pro-filter-search__item';
	
			if ( ! empty( $attributes['widthDesktop'] ) ) {
				$classes[] = $attributes['widthDesktop'] == '100' ? 'width-100' : 'width-50';
			}
	
			if ( ! empty( $attributes['widthTablet'] ) ) {
				$classes[] = $attributes['widthTablet'] == '100' ? 'md:width-100' : 'md:width-50';
			}
	
			if ( ! empty( $attributes['widthSmartPhone'] ) ) {
				$classes[] = $attributes['widthSmartPhone'] == '100' ? 'sp:width-100' : 'sp:width-50';
			}
	
			$wrapper_attributes = get_block_wrapper_attributes( 
				array( 
					'class' => trim( implode( ' ', $classes ) ),
				)
			);
	
			$output .= '<div ' . $wrapper_attributes . '>';

			if( ! empty( $attributes[ 'terms_' . $attributes['selectTaxonomy'] ]['label'] ) ){
				$output .= '<p class="label">' . esc_html( $attributes[ 'terms_' . $attributes['selectTaxonomy'] ]['label'] ) . '</p>';
			}
	
			if( ! empty( $attributes['selectTaxonomy'] ) && ! empty( $attributes[ 'terms_' . $attributes['selectTaxonomy'] ] ) ){
				$selected_post_type_taxonomies = get_object_taxonomies( $attributes['postType'] );
	
				if( in_array( $attributes['selectTaxonomy'], $selected_post_type_taxonomies, true ) ){
					$select_terms = json_decode( $attributes[ 'terms_' . $attributes['selectTaxonomy'] ]['ids'] );
				}
			}
	
			if( ! empty( $select_terms ) ){
				if( ! empty( $attributes['displayCount'] ) ) {
					$count = true;
				}
	
				$output .= '<div class="select-terms">';
		
				switch( $attributes['displayType'] ){
					case 'checkbox':
						$output .= self::create_checkbox( $select_terms, $attributes['selectTaxonomy'], $count, $orderby, $order );
	
						break;
					
					case 'radio':
						$output .= self::create_radio( $select_terms, $attributes['selectTaxonomy'], $count, $orderby, $order );
		
						break;
					
					case 'select':
						$output .= self::create_selectbox( $select_terms, $attributes['selectTaxonomy'], $count, $orderby, $order );
		
						break;
				}
	
				$output .= '</div>';
			} else {
				if( in_array( $attributes['selectTaxonomy'], $selected_post_type_taxonomies, true ) ){
					$output .= '1 つ以上のタームを選択してください。';
				} else {
					$output .= 'この投稿タイプにはタームが存在しません。他の投稿タイプを選択してください。';
				}
			}
	
			$output .= '</div>';

			return $output;
		}
	
		/**
		 * チェックボックス作成
		 */
		public function create_checkbox( $terms, $taxonomy, $count, $orderby, $order ){
			$output = '';
			$item_num = '';

			$terms = self::sorted_terms( $terms, $taxonomy, $orderby, $order );

			$name = 'checkbox_' . $taxonomy;
	
			foreach( $terms as $term ){
				// タームデータ取得
				$term_data = get_term( $term, $taxonomy );
	
				// query の中からタームのデータに合うものを checked する
				global $wp_query;
	
				$checked = '';
	
				if( ! is_admin() ){
					foreach( $wp_query->query as $key => $val ){
						if( $key == $name ){
							//var_dump($val);
							if( ! empty( $val ) ){
								if( in_array( strval( $term_data->term_id ), $val, true ) ){
									$checked = ' checked';
								}
							}
						}
					}
				}
	
				if( $count ){
					$item_num = '(' . $term_data->count . ')';
				}
	
				if( ! empty( $term_data->term_id ) ){
					$output .= '<label class="checkbox">';
					$output .= '<input type="checkbox" name="' . esc_attr( $name ) . '[]" value="' . absint( $term_data->term_id ) . '"' . esc_attr( $checked ) . '>' . esc_html( $term_data->name . $item_num );
					$output .= '</label>';
				}
			}
	
			return $output;
		}
	
		/**
		 * ラジオボタン作成
		 */
		public function create_radio( $terms, $taxonomy, $count, $orderby, $order ){
			$output = '';
			$item_num = '';
			$checked_flag = false;
			$no_checked = '';

			$terms = self::sorted_terms( $terms, $taxonomy, $orderby, $order );
	
			$name = 'radio_' . $taxonomy;
	
			foreach( $terms as $term ){
				// タームデータ取得
				$term_data = get_term( $term, $taxonomy );
	
				// query の中からタームのデータに合うものを checked する
				global $wp_query;
	
				$checked = '';
				
				if( ! is_admin() ){
					foreach( $wp_query->query as $key => $val ){
						if( $key == $name ){
							if( ! empty( $val ) && ! is_array( $val ) ){
								if( strval( $term_data->term_id ) === $val ){
									$checked = ' checked';
									$checked_flag = true;
								}
							}
						}
					}
				}
	
				if( $count ){
					$item_num = '(' . $term_data->count . ')';
				}
	
				$output .= '<label class="radio">';
				$output .= '<input type="radio" name="' . esc_attr( $name ) . '" value="' . absint( $term_data->term_id ) . '"' . esc_attr( $checked ) . '>' . esc_html( $term_data->name . $item_num );
				$output .= '</label>';
			}
	
			if( false === $checked_flag ){
				$no_checked = ' checked';
			}
	
			$output = '<label class="radio"><input type="radio" name="' . esc_attr( $name ) . '" value=""' . esc_attr( $no_checked ) . '>指定なし</label>' . $output;
	
			return $output;
		}
	
		/**
		 * セレクトボックス作成
		 */
		public function create_selectbox( $terms, $taxonomy, $count, $orderby, $order ){
			$output = '';
			$item_num = '';
			$options = '';
			$selected_flag = false;
			$no_selected = '';

			$terms = self::sorted_terms( $terms, $taxonomy, $orderby, $order );

			$name = 'select_' . $taxonomy;
	
			$output .= '<label class="select">';
			$output .= '<div class="select-inner">';
			$output .= '<select name="' . esc_attr( $name ) . '">';
	
			foreach( $terms as $term ){
				// タームデータ取得
				$term_data = get_term( $term, $taxonomy );
	
				// query の中からタームのデータに合うものを checked する
				global $wp_query;
	
				$selected = '';
				
				if( ! is_admin() ){
					foreach( $wp_query->query as $key => $val ){
						if( $key == $name ){
							if( ! empty( $val ) && ! is_array( $val ) ){
								if( strval( $term_data->term_id ) === $val ){
									$selected = ' selected';
									$selected_flag = true;
								}
							}
						}
					}
				}
	
				if( $count ){
					$item_num = '(' . $term_data->count . ')';
				}
	
				if( ! empty( $term_data->term_id ) ){
					$options .= '<option value="' . absint( $term_data->term_id ) . '"' . esc_attr( $selected ) . '>' . esc_html( $term_data->name . $item_num ) . '</option>';
				}
			}
	
			if( false === $selected_flag ){
				$no_selected = ' selected';
			}
	
			$options = '<option value=""' . esc_attr( $no_selected ) . '>指定なし</option>' . $options;
	
			$output .= $options;
			$output .= '</select>';
			$output .= '</div>';
			$output .= '</label>';
	
			return $output;
		}

		/**
		 * タクソノミー取得
		 *
		 * @return void
		 */
		public function get_taxonomies() {
			$builtin_taxonomy = array(
				'categories',
				'tags',
			);
			$args             = array(
				'public'   => true,
			);
			$output     = 'objects'; // names || objects
			$operator   = 'and'; // 'and' || 'or'
			$taxonomies = get_taxonomies( $args, $output, $operator );
	
			return $taxonomies;
		}

		/**
		 * ソート条件追加
		 */
		public function sorted_terms( $terms, $taxonomy, $orderby, $order ){

			$sorted_terms = get_terms( [
				'taxonomy'   => $taxonomy,
				'orderby'    => $orderby,
				'order'      => $order,
				'include'    => $terms,
				'hide_empty' => false,
			] );

			return array_column( $sorted_terms, 'term_id' );
		}
	
	}

	global $pagenow;

	if( $pagenow == 'nav-menus.php' ) {
		return false;
	}
	
	$output = new NISHIKI_BLOCKS_PRO_FILTER_SEARCH_TERMS();
}
