<?php
if ( ! class_exists( 'NISHIKI_PRO_BLOCK_EDITOR_HEADING' ) ) {
	/**
	 * 見出しスタイル作成
	 */
	class NISHIKI_PRO_BLOCK_EDITOR_HEADING extends NISHIKI_PRO_BLOCK_EDITOR_UTILITY {

		/**
		 * 見出しのレベル
		 *
		 * @var array
		 */
		private $heading_style_array = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' );

		/**
		 * ページのURL
		 *
		 * @var string
		 */
		private $admin_url = 'admin.php?page=nishiki-pro-block-editor.php&select=headings';

		/**
		 * 単位の配列
		 *
		 * @var array
		 */
		private $select_size_unit_array = array(
			'rem',
			'em',
			'px',
		);

		/**
		 * ボーダースタイルの配列
		 *
		 * @var array
		 */
		private $select_border_style_array = array(
			'dotted',
			'dashed',
			'solid',
			'double',
			'groove',
			'ridge',
			'inset',
			'outset',
		);

		/**
		 * Constructor.
		 */
		public function __construct() {
			// フォーム追加.
			add_action( 'admin_init', array( $this, 'register_settings' ), 20 );

			// ブロックスタイル追加
			add_action( 'init', array( $this, 'register_heading_block_style' ), 10 );

			// Ajax追加
			add_action( 'admin_enqueue_scripts', array( $this, 'add_ajax' ), 10 );
			add_action( 'wp_ajax_nishiki-pro-add-heading-action', array( $this, 'add_ajax_cb' ), 10 );
			add_action( 'wp_ajax_nishiki-pro-delete-heading-action', array( $this, 'delete_ajax_cb' ), 10 );
			add_action( 'wp_ajax_nishiki-pro-update-heading-action', array( $this, 'update_ajax_cb' ), 10 );
			add_action( 'wp_ajax_nishiki-pro-template-heading-action', array( $this, 'template_ajax_cb' ), 10 );

			// Codemirror 追加
			$get_select = ! empty( $_GET['select'] ) ? htmlspecialchars( $_GET['select'] ) : '';
			$get_page = ! empty( $_GET['page'] ) ? htmlspecialchars( $_GET['page'] ) : '';

			if ( is_admin() && 'nishiki-pro-block-editor.php' === $get_page && 'headings' === $get_select ) {
				add_action( 'admin_enqueue_scripts', array( $this, 'codemirror_enqueue_scripts' ), 10 );
			}
		}

		/**
		 * CSRF検証の統一関数
		 *
		 * @param string $action アクション名
		 * @param string $nonce_key nonceのキー名（通常は'nonce'）
		 * @return bool 検証結果
		 */
		private function verify_nonce_and_permission( $action, $nonce_key = 'nonce' ) {
			// 権限チェック
			if ( ! current_user_can( 'manage_options' ) ) {
				$this->send_error_response( '権限がありません。', 403 );
				return false;
			}

			// Refererチェック
			if ( ! wp_verify_nonce( wp_create_nonce( 'wp_rest' ), 'wp_rest' ) ) {
				// 基本的なRefererチェック
				$referer = wp_get_referer();
				if ( ! $referer || ! wp_validate_redirect( $referer, admin_url() ) ) {
					$this->send_error_response( 'リファラーが不正です。', 403 );
					return false;
				}
			}

			// CSRF対策 - nonceチェック
			$nonce_value = isset( $_POST[ $nonce_key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $nonce_key ] ) ) : '';
			
			if ( empty( $nonce_value ) ) {
				$this->send_error_response( 'セキュリティトークンが見つかりません。', 403 );
				return false;
			}

			if ( ! wp_verify_nonce( $nonce_value, $action ) ) {
				$this->send_error_response( 'セキュリティチェックに失敗しました。ページを再読み込みしてお試しください。', 403 );
				return false;
			}

			// リクエストメソッドのチェック
			if ( ! in_array( $_SERVER['REQUEST_METHOD'], array( 'POST' ), true ) ) {
				$this->send_error_response( '無効なリクエストメソッドです。', 405 );
				return false;
			}

			// Content-Typeチェック（Ajax リクエストの場合）
			if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
				$content_type = isset( $_SERVER['CONTENT_TYPE'] ) ? $_SERVER['CONTENT_TYPE'] : '';
				if ( strpos( $content_type, 'application/x-www-form-urlencoded' ) === false && 
					 strpos( $content_type, 'multipart/form-data' ) === false ) {
					$this->send_error_response( '無効なContent-Typeです。', 400 );
					return false;
				}
			}

			return true;
		}

		/**
		 * エラーレスポンスの送信
		 *
		 * @param string $message エラーメッセージ
		 * @param int    $status_code HTTPステータスコード
		 */
		private function send_error_response( $message, $status_code = 400 ) {
			status_header( $status_code );
			$data = wp_json_encode( array( 'error' => $message ) );
			header( 'Content-Type: application/json; charset=UTF-8' );
			echo wp_kses_post( $data );
			wp_die();
		}

		/**
		 * 成功レスポンスの送信
		 *
		 * @param mixed $data レスポンスデータ
		 */
		private function send_success_response( $data ) {
			$response = wp_json_encode( array( 'success' => true, 'data' => $data ) );
			header( 'Content-Type: application/json; charset=UTF-8' );
			echo wp_kses_post( $response );
			wp_die();
		}

		/**
		 * オプション名の検証
		 *
		 * @param string $option_name オプション名
		 * @return bool 検証結果
		 */
		private function validate_option_name( $option_name ) {
			if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $option_name ) ) {
				$this->send_error_response( '無効なオプション名です。', 400 );
				return false;
			}
			return true;
		}

		/**
		 * 数値パラメータの安全な取得
		 *
		 * @param string $key パラメータのキー
		 * @param int    $min 最小値
		 * @param int    $max 最大値
		 * @return int|false 検証済みの数値またはfalse
		 */
		private function get_safe_numeric_param( $key, $min = 0, $max = 999 ) {
			if ( ! isset( $_POST[ $key ] ) ) {
				return false;
			}

			$value = absint( $_POST[ $key ] );
			
			if ( $value < $min || $value > $max ) {
				$this->send_error_response( "パラメータ「{$key}」の値が範囲外です。", 400 );
				return false;
			}

			return $value;
		}

		/**
		 * Codemirror 追加
		 *
		 * @return void
		 */
		public function codemirror_enqueue_scripts() {
			$cm_settings['codeEditor'] = wp_enqueue_code_editor( array( 'type' => 'text/css' ) );
			wp_localize_script( 'wp-theme-plugin-editor', 'cm_settings', $cm_settings );

			wp_enqueue_script( 'wp-theme-plugin-editor' );
			wp_enqueue_style( 'wp-codemirror' );

			wp_enqueue_script(
				'wp-theme-plugin-script',
				get_template_directory_uri() . '/extension/class/block-editor/js/heading.js',
				array( 'wp-theme-plugin-editor' ),
				'1.0.0',
				false
			);
		}

		/**
		 * フォームの設定
		 */
		public function register_settings() {

			register_setting(
				$this->page_name . '_headings',
				$this->page_name . '_headings',
				array( $this, 'sanitize' )
			);

			add_settings_section(
				$this->page_name . '_headings',
				'',
				array( $this, 'cb' ),
				$this->page_name . '_headings'
			);
		}

		/**
		 * 出力（コールバック）
		 *
		 * @param array $args 設定
		 * @return void
		 */
		public function cb( $args ) {

			echo '<h3>見出しスタイル作成</h3>';

			// フォーム作成
			$this->create_form();

			echo '<div class="nishiki-pro-template-heading-wrap" style="border: 1px solid #aaa; padding: 1rem; border-radius: 4px;position: relative;margin-top: 2.5rem;">';
			echo '<h3 style="margin: 0;display: inline-block;position: absolute;top: -0.7rem;background: #f1f1f1;padding: 0 0.5rem;"> テンプレート</h3>';
			echo '<div class="nishiki-pro-template-heading-buttons">';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="dot01"><span class="preview">ドット01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="polka-dot01"><span class="preview">水玉ドット01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="color01"><span class="preview">カラー01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="baloon01"><span class="preview">フキダシ01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="accent01"><span class="preview">アクセント01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="accent02"><span class="preview">アクセント02</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="stripe01"><span class="preview">ストライプ01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="stitch01"><span class="preview">ステッチ01</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="border01"><span class="preview">ボーダー（上下）</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="border02"><span class="preview">ボーダー（下）</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="border03"><span class="preview">ボーダー</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="border04"><span class="preview">ボーダー（水平）</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="bracket01"><span class="preview">カッコ（左上/右下）</span></div>';
			echo '<div class="nishiki-pro-template-heading button-secondary dashicons-before dashicons-plus" data-heading-template="bracket02"><span class="preview">カッコ（左右）</span></div>';
			echo '</div>';
			echo '</div>';

			echo '<div style="border: 1px solid #aaa; padding: 1rem; border-radius: 4px;position: relative;margin-top: 2.5rem;">';
			echo '<h3 style="margin: 0;display: inline-block;position: absolute;top: -0.7rem;background: #f1f1f1;padding: 0 0.5rem;">※ 入力ルール</h3>';
			echo '<h4>・マージン/パディング/ボーダーについて</h4>';
			echo '<p>設定しない場合は、数値を空欄にしてください。</p>';
			echo '<h4>・追加 CSS について</h4>';
			echo '<p>セレクターは「is-style-[クラス名]」で指定してください。</p>';
			echo '<p>例:クラス名「heading-01」の h1 に適用する書き方</p>';
			echo '<p><code>h1.is-style-heading-01{ font-size: 1rem; }</code></p>';
			echo '</div>';

			// submit_button();
		}

		/**
		 * フォーム作成
		 */
		public function create_form() {
			echo '<p>※ 保存ボタンが動かない場合は、サーバー側で WAF の設定をオフにしていください。WAF の設定方法は各サーバー管理会社にお問い合わせください。テーマ側の問題ではありません。</p>';
			echo '<p>ブロックエディターで使える見出しのスタイルを作成できます。</p>';
			echo '<div id="nishiki-pro-block-heading-wrap" class="nishiki-pro-block-heading-wrap">';
			$this->heading_list();
			echo '<div id="nishiki-pro-heading-style-wrap" class="nishiki-pro-heading-style-wrap">';
			$this->get_heading_settings();
			echo '</div>';
			echo '</div>';
		}

		/**
		 * 一覧表示
		 */
		public function heading_list() {
			$num = 0;
			$page_name = $this->page_name . '_headings';
			$get_edit = isset( $_GET['edit'] ) ? sanitize_text_field( wp_unslash( $_GET['edit'] ) ) : null;

			// 現在選択されているインデックスを決定
			$current_edit = null;
			if ( null === $get_edit ) {
				// editパラメータが指定されていない場合は0番目を選択
				$current_edit = 0;
			} else {
				// editパラメータが指定されている場合の検証
				if ( is_numeric( $get_edit ) && intval( $get_edit ) >= 0 ) {
					$current_edit = absint( $get_edit );
				}
			}

			// DB からデータを読み込む
			$data = get_option( $page_name );

			if ( ! empty( $data ) && count( $data ) >= 1 ) {
				echo '<ul id="nishiki-pro-heading-style-list" class="nishiki-pro-heading-style-list">';

				foreach ( $data as $heading_style ) {
					$class = '';

					// 現在選択されている項目にcurrentクラスを追加
					if ( null !== $current_edit && $current_edit === $num ) {
						$class .= ' current';
					}

					echo '<li>';
					foreach ( $heading_style as $key => $val ) {
						// ラベル（クラス名）の安全な出力
						if ( 'label' === $key ) {
							$admin_url = esc_url( $this->admin_url . '&edit=' . $num );
							echo '<a href="' . $admin_url . '" ';
							echo 'class="label' . esc_attr( $class ) . '">';
							echo esc_html( $val );
							echo '</a>';
						}
					}
					echo '</li>';

					++$num;
				}

				echo '</ul>';
			}
		}

		/**
		 * 見出し設定詳細
		 *
		 * @return boolean
		 */
		public function get_heading_settings() {
			$get_select = ! empty( $_GET['select'] ) ? sanitize_text_field( wp_unslash( $_GET['select'] ) ) : '';
			$get_edit = isset( $_GET['edit'] ) ? sanitize_text_field( wp_unslash( $_GET['edit'] ) ) : null;

			if ( empty( $get_select ) ) {
				return false;
			}

			if ( 'headings' !== $get_select ) {
				return false;
			}

			$page_name = sanitize_text_field( $this->page_name . '_headings' );

			// オプション名の検証
			if ( ! preg_match( '/^[a-zA-Z0-9_-]+$/', $page_name ) ) {
				echo esc_html( __( '無効なオプション名です。', 'textdomain' ) );
				return false;
			}

			// DB からデータを読み込む
			$data = get_option( $page_name );

			// データが存在しない場合
			if ( empty( $data ) || ! is_array( $data ) ) {
				echo esc_html( __( '編集したい見出しを選ぶか、テンプレートから新しく追加してください。', 'textdomain' ) );
				return false;
			}

			// edit パラメータの処理
			$num = null;

			if ( null === $get_edit ) {
				// editパラメータが指定されていない場合は最初の要素（0番目）を表示
				$num = 0;
			} else {
				// editパラメータが指定されている場合の検証
				if ( is_numeric( $get_edit ) && intval( $get_edit ) >= 0 ) {
					$num = absint( $get_edit );
				} else {
					echo esc_html( __( '無効なIDが指定されました。', 'textdomain' ) );
					return false;
				}
			}

			// 指定されたインデックスのデータが存在するかチェック
			if ( ! isset( $data[ $num ] ) ) {
				echo esc_html( __( '編集したい見出しを選ぶか、テンプレートから新しく追加してください。', 'textdomain' ) );
				return false;
			}

			$data = $data[ $num ];

			if ( empty( $data ) ) {
				return false;
			}

			// 一覧を表示
			// 詳細画面
			echo '<div class="detail" id="' . esc_attr( 'item-heading-' . $num ) . '">';
			foreach ( $data as $key => $val ) {
				$label = $this->label_text( $key );

				// 名前とラベル（クラス名）
				if ( 'name' === $key || 'label' === $key ) {
					$class = '';

					if ( 'name' === $key ) {
						$class   = 'block-style-name';
						$desc    = '<p>' . esc_html( __( '半角英数字、ハイフン（-）、アンダースコア（_）のみ利用できます。', 'textdomain' ) ) . '</p><p>' . esc_html( __( '他のスタイルと同じクラス名にしないでください。', 'textdomain' ) ) . '</p>';
						$pattern = ' pattern="^[0-9_a-zA-Z/-]+$"';
					} else {
						$class   = 'block-style-label';
						$desc    = '<p>' . esc_html( __( '見出しブロックのスタイル名です。わかりやすい名前をつけましょう。', 'textdomain' ) ) . '</p>';
						$pattern = '';
					}

					echo '<div class="heading-input-wrap"><p class="heading-input-label">' . esc_html( __( '（必須）', 'textdomain' ) . $label ) . '</p><div><input' . esc_attr( $pattern ) . ' type="text" class="' . esc_attr( $class ) . '" id="' . esc_attr( 'heading-' . $num . '-' . $key ) . '" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . ']" value="' . esc_attr( $val ) . '" required>' . wp_kses_post( $desc ) . '</div></div>';
				}

				// h1-h6まで
				if ( in_array( $key, $this->heading_style_array, true ) ) {

					$is_show = '';

					if ( 'h1' === $key ) {
						$is_show = ' is-show';

						echo '<div class="heading-tabs">';
						for ( $i = 1; $i <= 6; ++$i ) {
							$tab_id = 'tab-' . $num . '-h' . $i;
							if ( 1 === $i ) {
								$is_active = ' is-active';
							} else {
								$is_active = '';
							}

							echo '<button class="heading-tab' . esc_attr( $is_active ) . '" id="' . esc_attr( $tab_id ) . '">' . esc_html( 'h' . $i ) . '</button>';
						}
						echo '</div>';
						echo '<div class="heading-tab-contents">';
					}

					echo '<div class="heading-wrap' . esc_attr( $is_show ) . '" id="' . esc_attr( 'tab-' . $num . '-' . $key . '-content' ) . '">';

					foreach ( $data[ $key ] as $property => $style ) {

						// フォント
						if ( 'font' === $property ) {

							foreach ( $style as $font_key => $font_value ) {

								if ( 'size' === $font_key ) {
									echo '<div class="heading-size heading-input-wrap">';
									echo '<p class="heading-input-label">' . esc_html( $this->label_text( $font_key ) ) . '</p>';
									echo '<div class="heading-size-input centering-vertical">';
									echo '<input id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $font_key ) . '" type="number" step="0.01" class="small-text" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $font_key ) . ']" value="' . esc_attr( $font_value ) . '" required>';
								}

								if ( 'unit' === $font_key ) {
									$id      = esc_attr( 'heading-' . $key . '-' . $property . '-' . $font_key );
									$class   = esc_attr( 'heading-' . $key . '-' . $property . '-' . $font_key );
									$name    = esc_attr( $page_name ) . '[' . $num . '][' . $key . '][' . $property . '][' . $font_key . ']';
									$val     = $font_value;
									$options = $this->select_size_unit_array;

									$this->select_form( $id, $class, $name, $val, $options );
									echo '</div>';
									echo '</div>';
								}

								// カラー
								if ( 'color' === $font_key ) {
									echo '<div class="heading-font-color heading-input-wrap flex">';
									echo '<div class="centering-vertical">';
									echo '<p class="heading-input-label">' . esc_html( $this->label_text( $font_key ) ) . '</p>';
									echo '<div class="heading-margin-input-wrap input-wrap">';
									echo '<div class="input centering-vertical">';
									echo '<p class="sub-title">' . esc_html( __( 'テキスト', 'textdomain' ) ) . '</p><input class="nishiki-pro-color-picker ' . esc_attr( 'heading-' . $num . '-' . $key . '-' . $property . '-' . $font_key ) . '" type="text" id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $font_key ) . '" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $font_key ) . ']" value="' . esc_attr( $font_value ) . '">';
									echo '</div>';
								}

								// 背景カラー
								if ( 'background-color' === $font_key ) {
									echo '<div class="input centering-vertical">';
									echo '<p class="sub-title">' . esc_html( __( '背景', 'textdomain' ) ) . '</p><input class="nishiki-pro-color-picker ' . esc_attr( 'heading-' . $num . '-' . $key . '-' . $property . '-' . $font_key ) . '" type="text" id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $font_key ) . '" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $font_key ) . ']" value="' . esc_attr( $font_value ) . '">';
									echo '</div>';
									echo '</div>';
									echo '</div>';
									echo '</div>';
								}

								// 行の高さ
								if ( 'line-height' === $font_key ) {
									echo '<div class="heading-input-wrap flex">';
									echo '<div class="input centering-vertical">';
									echo '<p class="heading-input-label">' . esc_html( $this->label_text( $font_key ) ) . '</p>';
									echo '<input id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $font_key ) . '" type="number" step="0.01" class="small-text" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $font_key ) . ']" value="' . esc_attr( $font_value ) . '">';
									echo '</div>';
									echo '</div>';
								}
							}
						}

						// マージン
						if ( 'margin' === $property ) {
							echo '<div class="heading-margin heading-input-wrap flex">';
							echo '<p class="heading-margin-title heading-input-label">' . esc_html( $this->label_array[ $property ] ) . '</p>';

							echo '<div class="heading-margin-input-wrap input-wrap">';
							foreach ( $style as $margin_key => $margin_value ) {

								echo '<div class="heading-margin-input input centering-vertical">';
								echo '<p class="sub-title">' . esc_html( $this->label_text( $margin_key ) ) . '</p><input type="number" step="0.01" id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $margin_key ) . '" class="small-text ' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $margin_key ) . '" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $margin_key ) . '][0]" value="' . esc_attr( $margin_value[0] ) . '">';

								$unit_id    = 'heading-' . $key . '-' . $property . '-' . $margin_key . '-unit';
								$unit_class = 'heading-' . $key . '-' . $property . '-' . $margin_key . '-unit';
								$name       = $page_name . '[' . $num . '][' . $key . '][' . $property . '][' . $margin_key . '][1]';
								$val        = $margin_value[1];
								$options    = $this->select_size_unit_array;

								$this->select_form( $unit_id, $unit_class, $name, $val, $options );

								echo '</div>';
							}
							echo '</div>';

							echo '</div>';
						}

						// パディング
						if ( 'padding' === $property ) {
							echo '<div class="heading-padding heading-input-wrap flex">';
							echo '<p class="heading-input-label">' . esc_html( $this->label_array[ $property ] ) . '</p>';

							echo '<div class="heading-padding-input-wrap input-wrap">';
							foreach ( $style as $padding_key => $padding_value ) {

								echo '<div class="heading-padding-input input centering-vertical">';
								echo '<p class="sub-title">' . esc_html( $this->label_text( $padding_key ) ) . '</p><input type="number" step="0.01" id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $padding_key ) . '" class="small-text ' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $padding_key ) . '" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $padding_key ) . '][0]" value="' . esc_attr( $padding_value[0] ) . '">';

								$id      = 'heading-' . $key . '-' . $property . '-' . $padding_key . '-unit';
								$class   = 'heading-' . $key . '-' . $property . '-' . $padding_key . '-unit';
								$name    = $page_name . '[' . $num . '][' . $key . '][' . $property . '][' . $padding_key . '][1]';
								$val     = $padding_value[1];
								$options = $this->select_size_unit_array;

								$this->select_form( $id, $class, $name, $val, $options );

								echo '</div>';
							}
							echo '</div>';

							echo '</div>';
						}

						// ボーダー
						if ( 'border' === $property ) {
							echo '<div class="heading-input-wrap flex">';
							echo '<p class="heading-input-label">' . esc_html( $this->label_array[ $property ] ) . '</p>';

							echo '<div class="input-wrap">';
							foreach ( $style as $border_key => $border_value ) {
								echo '<div class="input centering-vertical width-100">';
								echo '<p class="sub-title">' . esc_html( $this->label_text( $border_key ) ) . '</p>';
								echo '<div class="input-inner">';

								// 数値
								echo '<input type="number" step="0.01" id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $border_key ) . '" class="small-text" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $border_key ) . '][0]" value="' . esc_attr( $border_value[0] ) . '">';

								// 単位
								$unit_id      = 'heading-' . $key . '-' . $property . '-' . $border_key . '-unit';
								$unit_class   = 'heading-' . $key . '-' . $property . '-' . $border_key . '-unit';
								$unit_name    = $page_name . '[' . $num . '][' . $key . '][' . $property . '][' . $border_key . '][1]';
								$unit_val     = $border_value[1];
								$unit_options = $this->select_size_unit_array;

								$this->select_form( $unit_id, $unit_class, $unit_name, $unit_val, $unit_options );

								// スタイル
								$style_id      = 'heading-' . $key . '-' . $property . '-' . $border_key . '-style';
								$style_class   = 'heading-' . $key . '-' . $property . '-' . $border_key . '-style';
								$style_name    = $page_name . '[' . $num . '][' . $key . '][' . $property . '][' . $border_key . '][2]';
								$style_val     = $border_value[2];
								$style_options = $this->select_border_style_array;

								$this->select_form( $style_id, $style_class, $style_name, $style_val, $style_options );

								// カラー
								echo '<input class="nishiki-pro-color-picker ' . esc_attr( 'heading-' . $num . '-' . $key . '-' . $property . '-' . $border_key . '-color' ) . '" type="text" id="' . esc_attr( 'heading-' . $key . '-' . $property . '-' . $border_key . '-color' ) . '" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . '][' . esc_attr( $property ) . '][' . esc_attr( $border_key ) . '][3]" value="' . esc_attr( $border_value[3] ) . '">';

								echo '</div>';
								echo '</div>';
							}
							echo '</div>';

							echo '</div>';
						}
					}

					if ( 'h6' === $key ) {
						echo '</div>';
					}

					echo '</div>';
				}

				if ( 'code' === $key ) {
					echo '<div class="code">';
					echo '<p class="heading-title">' . esc_html( $label ) . '</p><textarea class="large-text code wp-nishiki-codemirror" id="wp-nishiki-codemirror" name="' . esc_attr( $page_name ) . '[' . absint( $num ) . '][' . esc_attr( $key ) . ']">' . esc_textarea( $val ) . '</textarea>';
					echo '</div>';
				}
			}
			echo '</div>';

			echo '<div class="livepreview">';
			echo '<div class="livepreview-inner">';
			echo '<p class="livepreview-title"><span><i class="dashicons-before dashicons-visibility"></i>' . esc_html( __( 'プレビュー', 'textdomain' ) ) . '</span></p>';
			echo '<style>.wrap .livepreview-heading h1{font-weight: bold; line-height:2;}</style>';
			echo '<div class="custom-style"></div>';

			echo '<div class="livepreview-heading entry-content wp-post-content">';
			echo '<div id="heading-h1" class="livepreview-heading-h1 is-selected"><h1>' . esc_html( __( '見出し1', 'textdomain' ) ) . '</h1></div>';
			echo '<div id="heading-h2" class="livepreview-heading-h2"><h2>' . esc_html( __( '見出し2', 'textdomain' ) ) . '</h2></div>';
			echo '<div id="heading-h3" class="livepreview-heading-h3"><h3>' . esc_html( __( '見出し3', 'textdomain' ) ) . '</h3></div>';
			echo '<div id="heading-h4" class="livepreview-heading-h4"><h4>' . esc_html( __( '見出し4', 'textdomain' ) ) . '</h4></div>';
			echo '<div id="heading-h5" class="livepreview-heading-h5"><h5>' . esc_html( __( '見出し5', 'textdomain' ) ) . '</h5></div>';
			echo '<div id="heading-h6" class="livepreview-heading-h6"><h6>' . esc_html( __( '見出し6', 'textdomain' ) ) . '</h6></div>';
			echo '</div>';
			echo '<input class="heading-livepreview-text large-text" type="text" value="' . esc_attr( __( '見出し', 'textdomain' ) ) . '">';
			echo '</div>';
			echo '<p style="text-align:right; margin-top:auto; margin-bottom:0;">';
			echo '<span id="nishiki-pro-update-button" class="nishiki-pro-update-heading button-primary" data-heading-num="' . esc_attr( $num ) . '">' . esc_html( __( '保存', 'textdomain' ) ) . '</span> ';
			echo '<span class="nishiki-pro-delete-heading button-secondary dashicons-before dashicons-no-alt" data-heading-num="' . esc_attr( $num ) . '">' . esc_html( __( 'スタイルを削除', 'textdomain' ) ) . '</span>';
			echo '</p>';
			echo '</div>';

			return true;
		}


		/**
		 * デフォルトデータの作成
		 *
		 * @param integer $index 数値
		 * @return mixed
		 */
		public function default_data( $index = 1 ) {
			// h1-h6までの共通設定を作成
			$heading_array = array();

			$default_font_size = array(
				1.8,
				1.7,
				1.4,
				1.2,
				1.15,
				1.1,
			);

			for ( $i = 1; $i <= 6; $i++ ) {
				$padding_top    = '';
				$padding_bottom = '';
				$border_top     = '';
				$border_bottom  = '';

				/*
				//if( $i == 2 ){
				//	$padding_top = 1;
				//	$padding_bottom = 1;
				//	$border_top = 1;
				//	$border_bottom = 1;
				//}
				*/

				$heading_array[ 'h' . $i ] = array(
					'font'    => array(
						'size'             => $default_font_size[ $i - 1 ],
						'unit'             => 'rem',
						'color'            => '',
						'background-color' => '',
						'line-height'      => 2,
					),
					'margin'  => array(
						'top'    => array( '', 'rem' ),
						'right'  => array( '', 'rem' ),
						'bottom' => array( '', 'rem' ),
						'left'   => array( '', 'rem' ),
					),
					'padding' => array(
						'top'    => array( $padding_top, 'rem' ),
						'right'  => array( '', 'rem' ),
						'bottom' => array( $padding_bottom, 'rem' ),
						'left'   => array( '', 'rem' ),
					),
					'border'  => array(
						'top'    => array( $border_top, 'px', 'solid', null ),
						'right'  => array( '', 'px', 'solid', null ),
						'bottom' => array( $border_bottom, 'px', 'solid', null ),
						'left'   => array( '', 'px', 'solid', null ),
					),
				);
			}

			$name  = 'heading-' . str_pad( $index, 2, 0, STR_PAD_LEFT );
			$label = '見出し' . str_pad( $index, 2, 0, STR_PAD_LEFT );

			$base_array = array(
				'name'  => $name,
				'label' => $label,
			);

			$code_array = array(
				'code' => '',
			);

			$data = array( array_merge( $base_array, $heading_array, $code_array ) );

			return $data;
		}

		/**
		 * ラベル出力
		 *
		 * @param string $label 文字列
		 */
		public function label_text( $label ) {
			$label_name = '';

			if ( array_key_exists( $label, $this->label_array ) ) {
				$label_name = $this->label_array[ $label ];
			}

			return $label_name;
		}

		/**
		 * フォームの出力（select）
		 *
		 * @param string $id ID 名
		 * @param string $class クラス名
		 * @param string $name 名前
		 * @param string $value 値
		 * @param array  $array 配列
		 * @return void
		 */
		public function select_form( $id, $class, $name, $value, $array = array() ) {
			if ( ! empty( $id ) && ! empty( $class ) && ! empty( $name ) && ! empty( $value ) && ! empty( $array ) ) {
				echo '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '">';
				foreach ( $array as $option ) {
					echo '<option value="' . esc_attr( $option ) . '" ' . selected( $value, $option ) . '>' . esc_html( $option ) . '</option>';
				}
				echo '</select>';
			}
		}


		/**
		 * 入力値のサニタイズ
		 *
		 * @param array $input 入力値
		 * @return $new_input
		 */
		public function sanitize( $input ) {
			$new_input = array();

			$name   = $this->page_name . '_headings';
			$option = get_option( $name );

			$num = 0;
			if ( isset( $input ) ) {
				foreach ( $input as $items ) {
					// 配列のサニタイズ
					foreach ( $items as $key => $val ) {
						// $key が h1-h6の場合の処理
						if ( in_array( $key, $this->heading_style_array, true ) ) {
							foreach ( $val as $style_key => $val_lv1 ) {
								// 保存されてる値が配列の場合
								if ( is_array( $val_lv1 ) ) {
									foreach ( $val_lv1 as $property => $val_lv2 ) {
										if ( is_array( $val_lv2 ) ) {
											// wp_die(var_dump($val_lv2));
											// 階層が
											foreach ( $val_lv2 as $index => $val_lv3 ) {
												$new_input[ $num ][ $key ][ $style_key ][ $property ][ $index ] = sanitize_text_field( $val_lv3 );
											}
										} else {
											// wp_die(var_dump($style_val));
											$new_input[ $num ][ $key ][ $style_key ][ $property ] = sanitize_text_field( $val_lv2 );
										}
									}
								} else {
									$new_input[ $num ][ $key ][ $style_key ] = sanitize_text_field( $val_lv1 );
								}
							}
						} else {
							if ( 'code' === $key ) {
								$new_input[ $num ][ $key ] = wp_kses_post( $val );
							} else {
								$new_input[ $num ][ $key ] = sanitize_text_field( $val );
							}
						}
					}

					++$num;
				}
			}

			return $new_input;
		}


		/**
		 * Ajax定義
		 */
		public function add_ajax() {
			$add_handle = 'nishiki-pro-add-heading-script';
			wp_enqueue_script(
				$add_handle,
				get_template_directory_uri() . '/extension/class/block-editor/js/heading-ajax-action.js',
				array( 'jquery' ),
				'1.0.0',
				false
			);

			// Add
			$add_action = 'nishiki-pro-add-heading-action';
			wp_localize_script(
				$add_handle,
				'nishiki_pro_add_heading_ajax',
				array(
					'ajax_url' => admin_url( 'admin-ajax.php' ),
					'action'   => $add_action,
					'nonce'    => wp_create_nonce( $add_action ),
				)
			);

			// Delete
			$delete_action = 'nishiki-pro-delete-heading-action';
			wp_localize_script(
				$add_handle,
				'nishiki_pro_delete_heading_ajax',
				array(
					'ajax_url' => admin_url( 'admin-ajax.php' ),
					'action'   => $delete_action,
					'nonce'    => wp_create_nonce( $delete_action ),
				)
			);

			// Reset
			$reset_action = 'nishiki-pro-reset-heading-action';
			wp_localize_script(
				$add_handle,
				'nishiki_pro_reset_heading_ajax',
				array(
					'ajax_url' => admin_url( 'admin-ajax.php' ),
					'action'   => $reset_action,
					'nonce'    => wp_create_nonce( $reset_action ),
				)
			);

			// template
			$template_action = 'nishiki-pro-template-heading-action';
			wp_localize_script(
				$add_handle,
				'nishiki_pro_template_heading_ajax',
				array(
					'ajax_url' => admin_url( 'admin-ajax.php' ),
					'action'   => $template_action,
					'nonce'    => wp_create_nonce( $template_action ),
				)
			);

			// Update
			$update_action = 'nishiki-pro-update-heading-action';
			wp_localize_script(
				$add_handle,
				'nishiki_pro_update_heading_ajax',
				array(
					'ajax_url' => admin_url( 'admin-ajax.php' ),
					'action'   => $update_action,
					'nonce'    => wp_create_nonce( $update_action ),
				)
			);
		}

		/*
		 * コールバック
		 */

		/**
		 * Add Ajax処理（CSRF強化版）
		 *
		 * @return void
		 */
		public function add_ajax_cb() {
			$action = 'nishiki-pro-add-heading-action';

			// 統一されたCSRF検証
			if ( ! $this->verify_nonce_and_permission( $action ) ) {
				return; // エラーレスポンスは関数内で送信済み
			}

			// オプション名の検証とサニタイズ
			$option_name = sanitize_text_field( $this->page_name . '_headings' );
			if ( ! $this->validate_option_name( $option_name ) ) {
				return; // エラーレスポンスは関数内で送信済み
			}

			$value = get_option( $option_name, array() );

			if ( ! is_array( $value ) ) {
				$value = array();
			}

			// データサイズのチェック（DoS対策）
			if ( count( $value ) >= 50 ) {
				$this->send_error_response( 'スタイルの数が上限に達しています。', 400 );
				return;
			}

			$index = count( $value ) + 1;
			$new_data = $this->default_data( $index );

			if ( ! is_array( $new_data ) ) {
				$this->send_error_response( 'データ生成に失敗しました。', 500 );
				return;
			}

			$value = array_merge( $value, $new_data );

			$update_result = update_option( $option_name, $value );

			if ( false === $update_result ) {
				$this->send_error_response( 'データ保存に失敗しました。', 500 );
				return;
			}

			$this->send_success_response( $value );
		}

		/**
		 * Delete Ajax処理（CSRF強化版）
		 *
		 * @return void
		 */
		public function delete_ajax_cb() {
			$action = 'nishiki-pro-delete-heading-action';

			// 統一されたCSRF検証
			if ( ! $this->verify_nonce_and_permission( $action ) ) {
				return;
			}

			// 数値パラメータの安全な取得
			$num = $this->get_safe_numeric_param( 'num', 0, 999 );
			if ( false === $num ) {
				$this->send_error_response( '削除対象が指定されていないか、値が不正です。', 400 );
				return;
			}

			// オプション名の検証
			$option_name = sanitize_text_field( $this->page_name . '_headings' );
			if ( ! $this->validate_option_name( $option_name ) ) {
				return;
			}

			$value = get_option( $option_name, array() );

			if ( ! is_array( $value ) || ! isset( $value[ $num ] ) ) {
				$this->send_error_response( '削除対象が見つかりません。', 404 );
				return;
			}

			unset( $value[ $num ] );
			$value = array_values( $value );

			$update_result = update_option( $option_name, $value );

			if ( false === $update_result ) {
				$this->send_error_response( 'データ削除に失敗しました。', 500 );
				return;
			}

			$this->send_success_response( $value );
		}

		/**
		 * Update Ajax処理（CSRF強化版）
		 *
		 * @return void
		 */
		public function update_ajax_cb() {
			$action = 'nishiki-pro-update-heading-action';

			// 統一されたCSRF検証
			if ( ! $this->verify_nonce_and_permission( $action ) ) {
				return;
			}

			// 必須パラメータのチェック
			if ( ! isset( $_POST['num'] ) || ! isset( $_POST['code'] ) ) {
				$this->send_error_response( '必須パラメータが不足しています。', 400 );
				return;
			}

			// 数値パラメータの安全な取得
			$num = $this->get_safe_numeric_param( 'num', 0, 999 );
			if ( false === $num ) {
				return;
			}

			// JSONデータの安全な処理
			$raw_code = isset( $_POST['code'] ) ? wp_unslash( $_POST['code'] ) : '';
			
			// JSON文字列の基本検証
			if ( empty( $raw_code ) || ! is_string( $raw_code ) ) {
				$this->send_error_response( 'JSONデータが不正です。', 400 );
				return;
			}

			// データサイズのチェック（DoS対策）
			if ( strlen( $raw_code ) > 100000 ) { // 100KB制限
				$this->send_error_response( 'データサイズが大きすぎます。', 400 );
				return;
			}

			// JSONデコードとエラーハンドリング
			$code = json_decode( $raw_code );
			
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				$this->send_error_response( 'JSON解析エラー: ' . json_last_error_msg(), 400 );
				return;
			}

			// デコードされたデータの構造検証
			if ( ! is_object( $code ) ) {
				$this->send_error_response( 'データ構造が不正です。', 400 );
				return;
			}

			// 必須プロパティの存在確認
			$required_properties = array( 'name', 'label', 'code' );
			foreach ( $required_properties as $property ) {
				if ( ! property_exists( $code, $property ) ) {
					$this->send_error_response( "必須プロパティ「{$property}」が見つかりません。", 400 );
					return;
				}
			}

			// h1-h6の存在確認
			for ( $i = 1; $i <= 6; $i++ ) {
				$h_property = 'h' . $i;
				if ( ! property_exists( $code, $h_property ) ) {
					$this->send_error_response( "見出しプロパティ「{$h_property}」が見つかりません。", 400 );
					return;
				}

				// 各見出しの必須プロパティ確認
				$heading_required = array( 'font', 'margin', 'padding', 'border' );
				foreach ( $heading_required as $req_prop ) {
					if ( ! property_exists( $code->{$h_property}, $req_prop ) ) {
						$this->send_error_response( "{$h_property}のプロパティ「{$req_prop}」が見つかりません。", 400 );
						return;
					}
				}
			}

			// オプション名の検証
			$option_name = sanitize_text_field( $this->page_name . '_headings' );
			if ( ! $this->validate_option_name( $option_name ) ) {
				return;
			}

			$value = get_option( $option_name, array() );

			if ( ! is_array( $value ) || ! isset( $value[ $num ] ) ) {
				$this->send_error_response( '更新対象が見つかりません。', 404 );
				return;
			}

			// データのサニタイズと保存
			$value[ $num ]['name']  = sanitize_text_field( $code->name );
			$value[ $num ]['label'] = sanitize_text_field( $code->label );
			$value[ $num ]['code']  = wp_kses_post( $code->code );

			for ( $i = 1; $i <= 6; $i++ ) {
				// Font - 各プロパティを個別にサニタイズ
				$value[ $num ][ 'h' . $i ]['font']['color']            = sanitize_hex_color( $code->{'h' . $i}->font->color );
				$value[ $num ][ 'h' . $i ]['font']['background-color'] = sanitize_hex_color( $code->{'h' . $i}->font->backgroundColor );
				
				// 数値系プロパティは空の場合は空文字列を保持
				$font_size = trim( $code->{'h' . $i}->font->size );
				$value[ $num ][ 'h' . $i ]['font']['size'] = ( $font_size !== '' && is_numeric( $font_size ) && $font_size >= 0.1 && $font_size <= 10 ) ? floatval( $font_size ) : '';
				
				$allowed_units = array( 'px', 'em', 'rem', '%' );
				$value[ $num ][ 'h' . $i ]['font']['unit'] = in_array( $code->{'h' . $i}->font->unit, $allowed_units ) ? $code->{'h' . $i}->font->unit : 'rem';
				
				$line_height = trim( $code->{'h' . $i}->font->lineHeight );
				$value[ $num ][ 'h' . $i ]['font']['line-height'] = ( $line_height !== '' && is_numeric( $line_height ) && $line_height >= 0.5 && $line_height <= 5 ) ? floatval( $line_height ) : '';

				// Margin - 配列の各要素をサニタイズ（範囲制限追加）
				$margin_positions = array( 'top', 'right', 'bottom', 'left' );
				foreach ( $margin_positions as $position ) {
					if ( property_exists( $code->{'h' . $i}->margin, $position ) && is_array( $code->{'h' . $i}->margin->{$position} ) ) {
						$margin_value = trim( $code->{'h' . $i}->margin->{$position}[0] );
						$value[ $num ][ 'h' . $i ]['margin'][$position][0] = ( $margin_value !== '' && is_numeric( $margin_value ) && $margin_value >= -100 && $margin_value <= 100 ) ? floatval( $margin_value ) : '';
						$value[ $num ][ 'h' . $i ]['margin'][$position][1] = in_array( $code->{'h' . $i}->margin->{$position}[1], $allowed_units ) ? $code->{'h' . $i}->margin->{$position}[1] : 'rem';
					}
				}

				// Padding - 配列の各要素をサニタイズ（範囲制限追加）
				foreach ( $margin_positions as $position ) {
					if ( property_exists( $code->{'h' . $i}->padding, $position ) && is_array( $code->{'h' . $i}->padding->{$position} ) ) {
						$padding_value = trim( $code->{'h' . $i}->padding->{$position}[0] );
						$value[ $num ][ 'h' . $i ]['padding'][$position][0] = ( $padding_value !== '' && is_numeric( $padding_value ) && $padding_value >= 0 && $padding_value <= 100 ) ? floatval( $padding_value ) : '';
						$value[ $num ][ 'h' . $i ]['padding'][$position][1] = in_array( $code->{'h' . $i}->padding->{$position}[1], $allowed_units ) ? $code->{'h' . $i}->padding->{$position}[1] : 'rem';
					}
				}

				// Border - 配列の各要素をサニタイズ（範囲制限追加）
				$allowed_border_styles = array( 'none', 'solid', 'dashed', 'dotted', 'double', 'groove', 'ridge', 'inset', 'outset' );
				foreach ( $margin_positions as $position ) {
					if ( property_exists( $code->{'h' . $i}->border, $position ) && is_array( $code->{'h' . $i}->border->{$position} ) ) {
						$border_width = trim( $code->{'h' . $i}->border->{$position}[0] );
						$value[ $num ][ 'h' . $i ]['border'][$position][0] = ( $border_width !== '' && is_numeric( $border_width ) && $border_width >= 0 && $border_width <= 50 ) ? floatval( $border_width ) : '';
						$value[ $num ][ 'h' . $i ]['border'][$position][1] = in_array( $code->{'h' . $i}->border->{$position}[1], $allowed_units ) ? $code->{'h' . $i}->border->{$position}[1] : 'px';
						$value[ $num ][ 'h' . $i ]['border'][$position][2] = in_array( $code->{'h' . $i}->border->{$position}[2], $allowed_border_styles ) ? $code->{'h' . $i}->border->{$position}[2] : 'solid';
						$value[ $num ][ 'h' . $i ]['border'][$position][3] = sanitize_hex_color( $code->{'h' . $i}->border->{$position}[3] );
					}
				}
			}

			$update_result = update_option( $option_name, array_values( $value ) );

			

			$response = wp_json_encode( array( 'success' => true, 'message' => 'データが正常に更新されました' ) );
			header( 'Content-Type: application/json; charset=UTF-8' );
			echo wp_kses_post( $response );
			wp_die();
		}

		/**
		 * Template
		 *
		 * @return mixed
		 */
		public function template_ajax_cb() {
			$action = 'nishiki-pro-template-heading-action';

			// 統一されたCSRF検証
			if ( ! $this->verify_nonce_and_permission( $action ) ) {
				return;
			}

			if ( empty( $_POST['template_name'] ) ) {
				$this->send_error_response( 'テンプレート名が指定されていません。', 400 );
				return;
			}

			$template_name = sanitize_text_field( wp_unslash( $_POST['template_name'] ) );

			// テンプレート名のホワイトリスト検証
			$allowed_templates = array(
				'dot01', 'polka-dot01', 'color01', 'baloon01', 'accent01', 'accent02',
				'stripe01', 'stitch01', 'border01', 'border02', 'border03', 'border04',
				'bracket01', 'bracket02'
			);

			if ( ! in_array( $template_name, $allowed_templates, true ) ) {
				$this->send_error_response( '無効なテンプレート名です。', 400 );
				return;
			}

			// オプション名の検証
			$option_name = sanitize_text_field( $this->page_name . '_headings' );
			if ( ! $this->validate_option_name( $option_name ) ) {
				return;
			}

			$value = get_option( $option_name, array() );

			if ( ! is_array( $value ) ) {
				$value = array();
			}

			// データサイズのチェック（DoS対策）
			if ( count( $value ) >= 50 ) {
				$this->send_error_response( 'スタイルの数が上限に達しています。', 400 );
				return;
			}

			$template_data = $this->heading_template( $template_name );

			if ( ! is_array( $template_data ) ) {
				$this->send_error_response( 'テンプレートデータの生成に失敗しました。', 500 );
				return;
			}

			$value = array_merge( $value, $template_data );

			$update_result = update_option( $option_name, $value );

			if ( false === $update_result ) {
				$this->send_error_response( 'データ保存に失敗しました。', 500 );
				return;
			}

			$this->send_success_response( $value );
		}

		/**
		 * ブロックスタイル登録
		 *
		 * @return boolean
		 */
		public function register_heading_block_style() {

			$num        = 0;
			$page_name  = $this->page_name . '_headings';
			$data       = get_option( $page_name );
			$block_name = 'heading';

			// var_dump($option);

			if ( ! empty( $data ) ) {

				foreach ( $data as $heading_style ) {
					// var_dump($heading_style);

					$css_block_style   = '';
					$input_block_style = '';
					$block_style       = '';

					foreach ( $heading_style as $key => $val ) {

						// 名前とラベル（クラス名）
						if ( 'name' === $key ) {
							$heading_name = $val;
						}

						if ( 'label' === $key ) {
							$heading_label = $val;
						}

						// h1-h6までのスタイル
						if ( in_array( $key, $this->heading_style_array, true ) ) {

							foreach ( $heading_style[ $key ] as $property => $style ) {

								// フォント
								if ( 'font' === $property ) {
									$color            = '';
									$background_color = '';
									$line_height      = '';

									foreach ( $style as $font_key => $font_value ) {

										if ( 'size' === $font_key && ! empty( $font_value ) ) {
											$input_font_size = $font_value;
										}

										if ( 'unit' === $font_key && ! empty( $font_value ) ) {
											$input_font_size_unit = $font_value;
										}

										if ( ! empty( $input_font_size ) && ! empty( $input_font_size_unit ) ) {
											$font_size = 'font-size:' . $input_font_size . $input_font_size_unit . ';';
										}

										if ( 'color' === $font_key && ! empty( $font_value ) ) {
											$color .= 'color:' . $font_value . ';';
										}

										if ( 'background-color' === $font_key && ! empty( $font_value ) ) {
											$background_color .= 'background-color:' . $font_value . ';';
										}

										if ( 'line-height' === $font_key && ! empty( $font_value ) ) {
											$line_height .= 'line-height:' . $font_value . ';';
										}
									}
								}

								// マージン
								if ( 'margin' === $property ) {
									$margin = '';

									foreach ( $style as $margin_key => $margin_value ) {

										// var_dump($margin_value);
										// var_dump($key);
										// $input_block_style .= $key . '.' . 'is-style-' . $heading_label . '{' . $property . '-' . $margin_key . ':' . $margin_value[0] . $margin_value[1] . ';}';
										if ( '' !== $margin_value[0] ) {
											$margin .= $property . '-' . $margin_key . ':' . $margin_value[0] . $margin_value[1] . ';';
										}
									}
								}

								// パディング
								if ( 'padding' === $property ) {
									$padding = '';

									foreach ( $style as $padding_key => $padding_value ) {
										if ( '' !== $padding_value[0] ) {
											$padding .= $property . '-' . $padding_key . ':' . $padding_value[0] . $padding_value[1] . ';';
										}
									}
								}

								// ボーダー
								if ( 'border' === $property ) {
									$border = '';

									foreach ( $style as $border_key => $border_value ) {
										if ( '' !== $border_value[0] ) {
											$border .= $property . '-' . $border_key . ':' . $border_value[0] . $border_value[1] . ' ' . $border_value[2] . ' ' . $border_value[3] . ';';
										}
									}
								}
							}

							// 全部まとめる
							$input_block_style .=
								$key . '.is-style-' . $heading_name . '
							{' . $font_size . $color . $background_color . $line_height . $margin . $padding . $border . '}';

							/*
							// 全部まとめる
							$input_block_style .= '
								.entry-content ' . $key . '.' . 'is-style-' . $heading_name . ',
								.editor-styles-wrapper ' . $key . '.' . 'is-style-' . $heading_name . '
							{' . $font_size . $color . $background_color . $line_height . $margin . $padding . $border . '}';
							*/

							if ( '' === $input_block_style ) {
								return false;
							}
							$str               = array( "\t", "\r\n", "\r", "\n" );
							$input_block_style = str_replace( $str, '', $input_block_style );

						}

						// 追加 CSS のスタイル
						if ( 'code' === $key && ! empty( $key ) ) {
							$css_block_style = preg_replace( '/[\r\n\t ]+/', ' ', $val );
						}
					}

					$block_style .= $input_block_style . $css_block_style;

					// var_dump($css_block_style);
					// var_dump($block_style);

					if ( $heading_name && $heading_label ) {
						register_block_style(
							'core/' . $block_name,
							array(
								'name'         => $heading_name,
								'label'        => $heading_label,
								'inline_style' => $block_style,
							)
						);
					}
				}
			}
		}
	}


	global $pagenow;

	if ( 'widgets.php' !== $pagenow ) {
		$output = new NISHIKI_PRO_BLOCK_EDITOR_HEADING();
	}
}
