<?php

if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Additional UI functions related to WordPress Admin Dashboard UI
 */
class Permalink_Manager_UI_Elements {

	public function __construct() {
		add_filter( 'default_hidden_columns', array( $this, 'quick_edit_hide_column' ), 99 );
		add_action( 'quick_edit_custom_box', array( $this, 'quick_edit_column_form' ), 999, 3 );
	}

	/**
	 * Generate the option field
	 *
	 * @param $input_name
	 * @param $args
	 *
	 * @return string
	 */
	static public function generate_option_field( $input_name, $args ) {
		global $permalink_manager_options;

		// Reset $fields variables
		$fields = '';

		// Allow to filter the $args
		$args = apply_filters( 'permalink_manager_field_args', $args, $input_name );

		$field_type     = ( isset( $args['type'] ) ) ? $args['type'] : 'text';
		$default        = ( isset( $args['default'] ) ) ? $args['default'] : '';
		$label          = ( isset( $args['label'] ) ) ? $args['label'] : '';
		$rows           = ( isset( $args['rows'] ) ) ? "rows=\"{$args['rows']}\"" : "rows=\"5\"";
		$description    = ( isset( $args['before_description'] ) ) ? $args['before_description'] : "";
		$description    .= ( isset( $args['description'] ) ) ? "<p class=\"field-description description\">{$args['description']}</p>" : "";
		$description    .= ( isset( $args['after_description'] ) ) ? $args['after_description'] : "";
		$description    .= ( isset( $args['pro'] ) ) ? sprintf( "<p class=\"field-description description alert info\">%s</p>", ( self::pro_text( true ) ) ) : "";
		$append_content = ( isset( $args['append_content'] ) ) ? "{$args['append_content']}" : "";

		// Input attributes
		$input_atts = ( ! empty( $args['input_class'] ) ) ? "class='{$args['input_class']}'" : '';
		$input_atts .= ( ! empty( $args['readonly'] ) ) ? " readonly='readonly'" : '';
		$input_atts .= ( ! empty( $args['disabled'] ) ) ? " disabled='disabled'" : '';
		$input_atts .= ( ! empty( $args['placeholder'] ) ) ? " placeholder='{$args['placeholder']}'" : '';
		$input_atts .= ( ! empty( $args['extra_atts'] ) ) ? " {$args['extra_atts']}" : '';

		// Display the field if the related class exists
		if ( ! empty( $args['class_exists'] ) ) {
			$related_classes       = (array) $args['class_exists'];
			$related_classes_exist = 0;

			foreach ( $related_classes as $related_class ) {
				if ( class_exists( $related_class ) ) {
					$related_classes_exist = 1;
					break;
				}
			}

			// Do not display if the related class it not found
			if ( empty( $related_classes_exist ) ) {
				$field_type = $args['container_class'] = 'hidden';
			}
		}

		// Check the container classes
		$container_class = ( isset( $args['container_class'] ) ) ? " class=\"{$args['container_class']} field-container\"" : " class=\"field-container\"";

		// Get the field value (if it is not set in $args)
		if ( ! empty( $args['value'] ) ) {
			$value = $args['value'];
		} else {
			// Extract the section and field name from $input_name
			preg_match( '/([^\[]+)(?:\[([^\[]+)\])(?:\[([^\[]+)\])?/', $input_name, $field_section_and_name );

			if ( $field_section_and_name ) {
				$section_name = $field_section_and_name[1];
				$field_name   = $field_section_and_name[2];

				if ( ! empty( $field_section_and_name[3] ) ) {
					$subsection_name = $field_section_and_name[3];
					$value           = ( isset( $permalink_manager_options[ $section_name ][ $field_name ][ $subsection_name ] ) ) ? $permalink_manager_options[ $section_name ][ $field_name ][ $subsection_name ] : $default;
				} else {
					$value = ( isset( $permalink_manager_options[ $section_name ][ $field_name ] ) ) ? $permalink_manager_options[ $section_name ][ $field_name ] : $default;
				}
			} else {
				$value = ( isset( $permalink_manager_options[ $input_name ] ) ) ? $permalink_manager_options[ $input_name ] : $default;
			}
		}

		switch ( $field_type ) {
			case 'checkbox' :
				$fields .= '<div class="checkboxes">';
				foreach ( $args['choices'] as $choice_value => $choice ) {
					$input_template = "<label for='%s[]'><input type='checkbox' %s value='%s' name='%s[]' %s /> %s</label>";

					if ( empty( $choice['label'] ) && is_array( $choice ) ) {
						if ( in_array( $choice_value, array( 'post_types', 'taxonomies' ) ) ) {
							$group_labels = array( 'post_types' => __( 'Post types', 'permalink-manager' ), 'taxonomies' => __( 'Taxonomies', 'permalink-manager' ) );
							$fields       .= sprintf( '<p>%s</p>', $group_labels[ $choice_value ] );
						}

						foreach ( $choice as $sub_choice_value => $sub_choice ) {
							$label = ( ! empty( $sub_choice['label'] ) ) ? $sub_choice['label'] : $sub_choice;
							$atts  = ( ! empty( $value[ $choice_value ] ) && in_array( $sub_choice_value, $value[ $choice_value ] ) ) ? "checked='checked'" : "";
							$atts  .= ( ! empty( $sub_choice['atts'] ) ) ? " {$sub_choice['atts']}" : "";

							$fields .= sprintf( $input_template, $input_name, $input_atts, $sub_choice_value, "{$input_name}[{$choice_value}]", $atts, $label );
						}
					} else {
						$label = ( ! empty( $choice['label'] ) ) ? $choice['label'] : $choice;
						$atts  = ( is_array( $value ) && in_array( $choice_value, $value ) ) ? "checked='checked'" : "";
						$atts  .= ( ! empty( $choice['atts'] ) ) ? " {$choice['atts']}" : "";

						$fields .= sprintf( $input_template, $input_name, $input_atts, $choice_value, $input_name, $atts, $label );
					}
				}
				$fields .= '</div>';

				// Add helper checkboxes for bulk actions
				if ( isset( $args['select_all'] ) || isset( $args['unselect_all'] ) ) {
					$select_all_label   = ( ! empty( $args['select_all'] ) ) ? $args['select_all'] : __( 'Select all', 'permalink-manager' );
					$unselect_all_label = ( ! empty( $args['unselect_all'] ) ) ? $args['unselect_all'] : __( 'Unselect all', 'permalink-manager' );

					$fields .= "<p class=\"checkbox_actions extra-links\">";
					$fields .= ( isset( $args['select_all'] ) ) ? "<a href=\"#\" class=\"select_all\">{$select_all_label}</a>&nbsp;" : "";
					$fields .= ( isset( $args['unselect_all'] ) ) ? "<a href=\"#\" class=\"unselect_all\">{$unselect_all_label}</a>" : "";
					$fields .= "</p>";
				}
				break;

			case 'single_checkbox' :
				$fields .= '<div class="single_checkbox">';
				if ( is_array( $value ) ) {
					$input_key = preg_replace( '/(.*)(?:\[([^\[]+)\])$/', '$2', $input_name );
					$checked   = ( ! empty( $value[ $input_key ] ) ) ? "checked='checked'" : "";
				} else {
					$checked = ( $value == 1 ) ? "checked='checked'" : "";
				}
				$checkbox_label = ( isset( $args['checkbox_label'] ) ) ? $args['checkbox_label'] : '';

				$fields .= "<input type='hidden' {$input_atts} value='0' name='{$input_name}' />";
				$fields .= "<label for='{$input_name}'><input type='checkbox' {$input_atts} value='1' name='{$input_name}' {$checked} /> {$checkbox_label}</label>";
				$fields .= '</div>';
				break;

			case 'radio' :
				$fields .= '<div class="radios">';
				foreach ( $args['choices'] as $choice_value => $choice ) {
					$label = ( is_array( $choice ) ) ? $choice['label'] : $choice;
					$atts  = ( $choice_value == $value ) ? "checked='checked'" : "";
					$atts  .= ( ! empty( $choice['atts'] ) ) ? " {$choice['atts']}" : "";

					$fields .= "<label for='{$input_name}[]'><input type='radio' {$input_atts} value='{$choice_value}' name='{$input_name}[]' {$atts} /> {$label}</label>";
				}
				$fields .= '</div>';
				break;

			case 'select' :
				$fields .= '<span class="select">';
				$fields .= "<select name='{$input_name}' {$input_atts}>";
				foreach ( $args['choices'] as $choice_value => $choice ) {
					$label = ( is_array( $choice ) ) ? $choice['label'] : $choice;
					$atts  = ( $choice_value == $value ) ? "selected='selected'" : "";
					$atts  .= ( ! empty( $choice['atts'] ) ) ? " {$choice['atts']}" : "";

					if ( $choice == '---' ) {
						$fields .= "<option disabled=\"disabled\">------------------</option>";
					} else {
						$fields .= "<option value='{$choice_value}' {$atts}>{$label}</option>";
					}
				}
				$fields .= '</select>';
				$fields .= '</span>';
				break;

			case 'textarea' :
				$fields .= sprintf( "<textarea %s name='%s' %s>%s</textarea>", $input_atts, $input_name, $rows, esc_textarea( $value ) );
				break;

			case 'pre' :
				$fields .= sprintf( "<pre %s>%s</pre>", $input_atts, esc_textarea( $value ) );
				break;

			case 'info' :
				$fields .= sprintf( "<div %s>%s</div>", $input_atts, $value );
				break;

			case 'clearfix' :
				return "<div class=\"clearfix\"></div>";

			default :
				$input_type = ( in_array( $field_type, array( 'text', 'password', 'number', 'hidden' ) ) ) ? $field_type : 'text';
				$fields     .= sprintf( "<%s type='%s' %s value='%s' name='%s' />", 'input', $input_type, $input_atts, esc_attr( $value ), $input_name );
		}

		// Get the final HTML output
		if ( isset( $args['container'] ) && $args['container'] == 'tools' ) {
			$html = "<div{$container_class}>";
			$html .= "<h4>{$label}</h4>";
			$html .= "<div class='{$input_name}-container'>{$fields}</div>";
			$html .= $description;
			$html .= $append_content;
			$html .= "</div>";
		} else if ( isset( $args['container'] ) && $args['container'] == 'row' ) {
			$html = sprintf( "<tr id=\"%s\" data-field=\"%s\" %s>", esc_attr( preg_replace( '/(?:.*\[)(.*)(?:\].*)/', '$1', $input_name ) ), $input_name, $container_class );
			$html .= sprintf( "<th><label for=\"%s\">%s</label></th>", $input_name, $args['label'] );
			$html .= sprintf( "<td><fieldset>%s%s</fieldset></td>", $fields, $description );
			$html .= "</tr>";
			$html .= ( $append_content ) ? "<tr class=\"appended-row\"><td colspan=\"2\">{$append_content}</td></tr>" : "";
		} else if ( isset( $args['container'] ) && $args['container'] == 'screen-options' ) {
			$html = "<fieldset data-field=\"{$input_name}\" {$container_class}><legend>{$args['label']}</legend>";
			$html .= "<div class=\"field-content\">{$fields}{$description}</div>";
			$html .= ( $append_content ) ? "<div class=\"appended-row\">{$append_content}</div>" : "";
			$html .= "</fieldset>";
		} else {
			$html = $fields . $append_content;
		}

		return apply_filters( 'permalink_manager_field_output', $html );
	}

	/**
	 * Display hidden field to indicate posts or taxonomies admin sections
	 *
	 * @param string $type
	 *
	 * @return string
	 */
	static public function section_type_field( $type = 'post' ) {
		return self::generate_option_field( 'content_type', array( 'value' => $type, 'type' => 'hidden' ) );
	}

	/**
	 * Display the HTML output of form for provided fields array
	 *
	 * @param array $fields
	 * @param string $container
	 * @param array $button
	 * @param string $sidebar
	 * @param array $nonce
	 * @param bool $wrap
	 * @param string $form_class
	 *
	 * @return string
	 */
	static public function get_the_form( $fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array(), $wrap = false, $form_class = '' ) {
		// 1. Check if the content will be displayed in columns and button details
		switch ( $container ) {
			case 'columns-3' :
				$wrapper_class     = 'columns-container';
				$form_column_class = 'column column-2_3';
				$sidebar_class     = 'column column-1_3';
				break;

			case 'tabs' :
				$wrapper_class = 'form settings-tabs';
				$sidebar_class = $form_column_class = '';
				break;

			// there will be more cases in the future ...
			default :
				$sidebar_class = 'sidebar';
				$wrapper_class = $form_column_class = '';
		}

		// 2. Process the array with button and nonce field settings
		$button_text       = ( ! empty( $button['text'] ) ) ? $button['text'] : '';
		$button_class      = ( ! empty( $button['class'] ) ) ? $button['class'] : '';
		$button_attributes = ( ! empty( $button['attributes'] ) ) ? $button['attributes'] : '';
		$nonce_action      = ( ! empty( $nonce['action'] ) ) ? $nonce['action'] : '';
		$nonce_name        = ( ! empty( $nonce['name'] ) ) ? $nonce['name'] : '';
		$form_classes      = ( ! empty( $form_class ) ) ? $form_class : '';

		// 3. Now get the HTML output (start section row container)
		$html = ( $wrapper_class ) ? "<div class=\"{$wrapper_class}\">" : '';

		// 4. Display settings tabs
		if ( $container == 'tabs' ) {
			// Get active section
			$active_tab = ( ! empty( $_POST['pm_active_tab'] ) ) ? sanitize_key( $_POST['pm_active_tab'] ) : key( array_slice( $fields, 0, 1, true ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing

			$html .= "<ul class=\"subsubsub\">";
			foreach ( $fields as $tab_name => $tab ) {
				$active_class = ( $active_tab === $tab_name ) ? 'current' : '';
				$html         .= sprintf( "<li><a href=\"#%s\" class=\"%s\" data-tab=\"%s\">%s</a></li>", $tab_name, $active_class, $tab_name, $tab['section_name'] );
			}
			$html .= "</ul>";
		}

		// 5. Display some notes
		if ( $sidebar_class && $sidebar ) {
			$html .= sprintf( "<div class=\"%s\">", $sidebar_class );
			$html .= "<div class=\"section-notes\">";
			$html .= $sidebar;
			$html .= "</div>";
			$html .= "</div>";
		}

		// 6. Start fields' section
		$html .= ( $form_column_class ) ? sprintf( "<div class=\"%s\">", $form_column_class ) : "";
		$html .= sprintf( "<form method=\"POST\" class=\"%s\">", $form_classes );
		$html .= ( $wrap ) ? "<table class=\"form-table\">" : "";

		// 7. Loop through all fields assigned to this section
		foreach ( $fields as $field_name => $field ) {
			$tab_name   = ( isset( $field['fields'] ) ) ? $field_name : '';
			$field_name = ( ! empty( $field['name'] ) ) ? $field['name'] : $field_name;

			// A. Display table row
			if ( isset( $field['container'] ) && $field['container'] == 'row' ) {
				$row_output = "";

				// Loop through all fields assigned to this section
				if ( isset( $field['fields'] ) ) {
					foreach ( $field['fields'] as $section_field_id => $section_field ) {
						if ( is_string( $section_field ) ) {
							$row_output .= $section_field;
						} else {
							$section_field_name         = ( ! empty( $section_field['name'] ) ) ? $section_field['name'] : "{$field_name}[$section_field_id]";
							$section_field['container'] = 'row';

							$row_output .= self::generate_option_field( $section_field_name, $section_field );
						}
					}
				} else {
					$row_output .= self::generate_option_field( $field_name, $field );
				}

				if ( isset( $field['section_name'] ) ) {
					if ( $container == 'tabs' ) {
						$is_active_tab = ( ! empty( $active_tab ) && $active_tab == $tab_name ) ? 'class="active-tab"' : '';

						$html .= sprintf( "<div id=\"pm_%s\" data-tab=\"%s\" %s>", $tab_name, $tab_name, $is_active_tab );
					}

					$html .= "<h3>{$field['section_name']}</h3>";
					$html .= ( isset( $field['append_content'] ) ) ? $field['append_content'] : "";
					$html .= ( isset( $field['description'] ) ) ? sprintf( "<p class=\"description\">%s</p>", $field['description'] ) : "";
					$html .= sprintf( "<table class=\"form-table\" data-field=\"%s\">%s</table>", $field_name, $row_output );
					$html .= ( $container == 'tabs' ) ? "</div>" : "";
				} else {
					$html .= $row_output;
				}
			} // B. Display single field
			else {
				$html .= self::generate_option_field( $field_name, $field );
			}
		}

		$html .= ( $wrap ) ? "</table>" : "";

		// 8. Add a hidden field with section name for settings page
		if ( $container == 'tabs' && ! empty( $active_tab ) ) {
			$html .= self::generate_option_field( 'pm_active_tab', array( 'value' => $active_tab, 'type' => 'hidden', 'readonly' => true ) );
		}

		// 9. End the fields' section + add button & nonce fields
		if ( $nonce_action && $nonce_name ) {
			$html .= wp_nonce_field( $nonce_action, $nonce_name, true, false );
			$html .= self::generate_option_field( 'pm_session_id', array( 'value' => uniqid(), 'type' => 'hidden' ) );
		}
		$html .= ( $button_text ) ? get_submit_button( $button_text, $button_class, '', false, $button_attributes ) : "";
		$html .= '</form>';
		$html .= ( $form_column_class ) ? "</div>" : "";

		// 10. End the section row container
		$html .= ( $wrapper_class ) ? "</div>" : "";

		return $html;
	}

	/**
	 * Get the plugin sections' HTML code
	 *
	 * @param array $sections
	 * @param string $active_section
	 * @param string $active_subsection
	 *
	 * @return string
	 */
	static public function get_plugin_sections_html( $sections, $active_section = '', $active_subsection = '' ) {
		global $permalink_manager_after_sections_html;

		$html = "<div id=\"permalink-manager\" class=\"wrap\">";
		$html .= sprintf( '<h2 id="plugin-name-heading">%1$s <a href="%2$s" class="author-link" target="_blank">%3$s</a></h2>', PERMALINK_MANAGER_PLUGIN_NAME, esc_attr( PERMALINK_MANAGER_PROMO ), PERMALINK_MANAGER_VERSION );

		// Display the tab navigation
		$html .= "<div id=\"permalink-manager-tab-nav\" class=\"nav-tab-wrapper\">";
		foreach ( $sections as $section_name => $section_properties ) {
			$active_class = ( $active_section === $section_name ) ? 'nav-tab-active nav-tab' : 'nav-tab';
			$section_url  = Permalink_Manager_Admin_Functions::get_admin_url( "&section={$section_name}" );

			$html .= sprintf( "<a href=\"%s\" class=\"%s section_%s\">%s</a>", $section_url, $active_class, $section_name, $section_properties['name'] );
		}

		// Upgrade to Pro version
		$html .= ( ! Permalink_Manager_Admin_Functions::is_pro_active() ) ? sprintf( "<a href=\"%s\" target=\"_blank\" class=\"nav-tab section_upgrade\"><i class=\"dashicons dashicons-external\"></i> %s</a>", PERMALINK_MANAGER_PROMO, __( 'Upgrade to PRO', 'permalink-manager' ) ) : '';
		$html .= "</div>";

		// Now display the active section
		$html                 .= "<div id=\"permalink-manager-sections\">";
		$active_section_array = ( isset( $sections[ $active_section ] ) ) ? $sections[ $active_section ] : "";

		// Display additional navigation for subsections
		if ( isset( $sections[ $active_section ]['subsections'] ) ) {
			$html .= "<ul class=\"subsubsub\">";
			foreach ( $sections[ $active_section ]['subsections'] as $subsection_name => $subsection ) {
				$active_class   = ( $active_subsection === $subsection_name ) ? 'current' : '';
				$subsection_url = Permalink_Manager_Admin_Functions::get_admin_url( "&section={$active_section}&subsection={$subsection_name}" );

				$html .= "<li><a href=\"{$subsection_url}\" class=\"{$active_class}\">{$subsection['name']}</a></li>";
			}
			$html .= "</ul>";
		}

		// A. Execute the function assigned to the subsection
		if ( isset( $active_section_array['subsections'][ $active_subsection ]['function'] ) ) {
			$class_name     = $active_section_array['subsections'][ $active_subsection ]['function']['class'];
			$section_object = new $class_name();

			$section_content = call_user_func( array( $section_object, $active_section_array['subsections'][ $active_subsection ]['function']['method'] ) );
		} // B. Execute the function assigned to the section
		else if ( isset( $active_section_array['function'] ) ) {
			$class_name     = $active_section_array['function']['class'];
			$section_object = new $class_name();

			$section_content = call_user_func( array( $section_object, $active_section_array['function']['method'] ) );
		} // C. Display the raw HTMl output of subsection
		else if ( isset( $active_section_array['subsections'][ $active_subsection ]['html'] ) ) {
			$section_content = $active_section_array['subsections'][ $active_subsection ]['html'];
		} // D. Try to display the raw HTMl output of section
		else {
			$section_content = ( isset( $active_section_array['html'] ) ) ? $active_section_array['html'] : "";
		}

		$html .= "<div class=\"single-section\" data-section=\"{$active_section}\" id=\"{$active_section}\">{$section_content}</div>";
		$html .= "</div>";

		// Display alerts and another content if needed and close .wrap container
		$html .= $permalink_manager_after_sections_html;
		$html .= "</div>";

		return $html;
	}

	/**
	 * Display the array or HTML table with updated slugs after one of the actions is triggered
	 *
	 * @param array $updated_array
	 * @param bool $return_array
	 * @param bool $display_full_table
	 * @param bool $preview_mode
	 *
	 * @return array|string
	 */
	static function display_updated_slugs( $updated_array, $return_array = false, $display_full_table = true, $preview_mode = false ) {
		global $permalink_manager_before_sections_html, $adjust_id_url_filter_off;

		$updated_slugs_count = 0;
		$html                = $main_content = $alert = "";

		// Disable "Adjust IDs for multilingual functionality" in WPML to make sure that the correct URLs are displayed in the results table
		$adjust_id_url_filter_off = true; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound

		if ( is_array( $updated_array ) ) {
			// Check if slugs should be displayed
			$first_slug = reset( $updated_array );
			$show_slugs = ( ! empty( $_POST['mode'] ) && $_POST['mode'] == 'slugs' ) ? true : false; // phpcs:ignore WordPress.Security.NonceVerification.Missing

			$header_footer = '<tr>';
			$header_footer .= sprintf( '<th class="column-primary">%s</th>', __( 'Title', 'permalink-manager' ) );
			if ( $show_slugs ) {
				$header_footer .= ( isset( $first_slug['old_slug'] ) ) ? sprintf( '<th>%s</th>', __( 'Old Slug', 'permalink-manager' ) ) : '';
				$header_footer .= ( isset( $first_slug['new_slug'] ) ) ? sprintf( '<th>%s</th>', __( 'New Slug', 'permalink-manager' ) ) : '';
			} else {
				$header_footer .= sprintf( '<th>%s</th>', __( 'Old URI', 'permalink-manager' ) );
				$header_footer .= sprintf( '<th>%s</th>', __( 'New URI', 'permalink-manager' ) );
			}
			$header_footer .= '</tr>';

			$screen_reader_button = sprintf( '<button type="button" class="toggle-row"><span class="screen-reader-text">%s</span></button>', __( 'Show more details', 'permalink-manager' ) );

			foreach ( $updated_array as $row ) {
				// Odd/even class
				$updated_slugs_count ++;
				$alternate_class = ( $updated_slugs_count % 2 == 1 ) ? ' class="alternate"' : '';

				// Taxonomy
				if ( ! empty( $row['tax'] ) ) {
					$term_link = get_term_link( intval( $row['ID'] ), $row['tax'] );
					$permalink = ( is_wp_error( $term_link ) ) ? "-" : $term_link;
				} else {
					$permalink = get_permalink( $row['ID'] );
				}

				// Decode permalink
				$permalink = rawurldecode( rawurldecode( $permalink ) );

				$main_content .= sprintf( '<tr data-id="%s" %s>', $row['ID'], $alternate_class );
				$main_content .= sprintf( '<td class="row-title column-primary" data-colname="%s">%s<a target="_blank" href="%s"><span class="small">%s</span></a> %s</td>', __( 'Title', 'permalink-manager' ), sanitize_text_field( $row['item_title'] ), $permalink, $permalink, $screen_reader_button );

				if ( $show_slugs ) {
					$main_content .= ( isset( $row['old_slug'] ) ) ? sprintf( '<td data-colname="%s">%s</td>', __( 'Old Slug', 'permalink-manager' ), rawurldecode( $row['old_slug'] ) ) : "";
					$main_content .= ( isset( $row['new_slug'] ) ) ? sprintf( '<td data-colname="%s">%s</td>', __( 'New Slug', 'permalink-manager' ), rawurldecode( $row['new_slug'] ) ) : "";
				} else {
					$main_content .= sprintf( '<td data-colname="%s">%s</td>', __( 'Old URI', 'permalink-manager' ), rawurldecode( $row['old_uri'] ) );
					$main_content .= sprintf( '<td data-colname="%s">%s</td>', __( 'New URI', 'permalink-manager' ), rawurldecode( $row['new_uri'] ) );
				}
				$main_content .= '</tr>';
			}

			// Merge header, footer and content
			if ( $display_full_table ) {
				$html = sprintf( '<h3 id="updated-list">%s</h3>', __( 'List of updated items', 'permalink-manager' ) );
				$html .= '<table class="widefat wp-list-table updated-slugs-table">';
				$html .= sprintf( '<thead>%s</thead><tbody>%s</tbody><tfoot>%s</tfoot>', $header_footer, $main_content, $header_footer );
			} else {
				$html = $main_content;
			}

			$html .= '</table>';
		}

		// 3. Display the alert
		if ( isset( $updated_slugs_count ) ) {
			if ( $updated_slugs_count > 0 && ! $preview_mode ) {
				// translators: %d is the number of items where custom permalinks were updated
				$alert_content = sprintf( _n( '<strong class="updated_count">%d</strong> item was updated!', '<strong class="updated_count">%d</strong> items were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
				// translators: %s is the anchor link to the updated items' table
				$alert_content .= sprintf( __( '<a %s>Click here</a> to go to the list of processed items', 'permalink-manager' ), "href=\"#updated-list\"" );

				$alert = self::get_alert_message( $alert_content, 'updated updated_slugs' );
			} else {
				$alert_content = ( $preview_mode ) ? sprintf( '[%s] ', __( 'Preview mode', 'permalink-manager' ) ) : '';
				$alert_content .= __( '<strong>No items</strong> were processed!', 'permalink-manager' );

				$alert = self::get_alert_message( $alert_content, 'error updated_slugs' );
			}
		}

		if ( $return_array ) {
			return array(
				'html'  => $html,
				'alert' => $alert
			);
		} else {
			$permalink_manager_before_sections_html .= $alert;

			return $html;
		}
	}

	/**
	 * Get the HTML output of URI Editor
	 *
	 * @param WP_Post|WP_Term $element
	 * @param bool $gutenberg
	 *
	 * @return string
	 */
	public static function display_uri_box( $element, $gutenberg = false ) {
		global $permalink_manager_options;

		// Check the user capabilities
		if ( Permalink_Manager_Admin_Functions::current_user_can_edit_uris() === false ) {
			return '';
		}

		if ( ! empty( $element->ID ) ) {
			$id          = $element_id = $element->ID;
			$native_slug = $element->post_name;

			$auto_update_val = get_post_meta( $id, "auto_update_uri", true );

			$is_draft          = ( ! empty( $element->post_status ) && ( in_array( $element->post_status, array( 'draft', 'auto-draft' ) ) ) ) ? true : false;
			$is_draft_excluded = Permalink_Manager_Helper_Functions::is_draft_excluded( $element );
			$is_front_page     = Permalink_Manager_Helper_Functions::is_front_page( $id );

			// Allow users force the URI Editor to appear for drafts and auto-drafts
			if ( $is_draft_excluded && $is_draft ) {
				$is_draft_excluded = apply_filters( 'permalink_manager_auto_draft_hide_editor', $is_draft_excluded, $element, $gutenberg );
			}

			// Get URIs
			$uri         = Permalink_Manager_URI_Functions_Post::get_post_uri( $id, true, $is_draft );
			$default_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $id );
			$native_uri  = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $id, true );
		} else if ( class_exists( 'Permalink_Manager_URI_Functions_Tax' ) ) {
			$id          = $element->term_id;
			$element_id  = "tax-{$id}";
			$native_slug = $element->slug;

			$auto_update_val = get_term_meta( $id, "auto_update_uri", true );

			// Get URIs
			$uri         = Permalink_Manager_URI_Functions_Tax::get_term_uri( $element->term_id, true );
			$default_uri = Permalink_Manager_URI_Functions_Tax::get_default_term_uri( $element->term_id );
			$native_uri  = Permalink_Manager_URI_Functions_Tax::get_default_term_uri( $element->term_id, true );
		} else {
			return '';
		}

		// If the draft is excluded do not display the contents of URI Editor
		if ( ! empty( $is_draft_excluded ) ) {
			if ( ! empty( $element->post_status ) && $element->post_status == 'auto-draft' ) {
				$alert = __( 'Save your post to activate the permalink editor and make changes to the custom permalink.', 'permalink-manager' );
			} else {
				/* translators: Link to settings page */
				$alert = sprintf( __( 'The custom permalink cannot be edited due to the <a href="%s" target="_blank">Permalink Manager settings</a> ("<strong>Exclude drafts & pending posts</strong>") and the post status not allowing it.', 'permalink-manager' ), Permalink_Manager_Admin_Functions::get_admin_url( '&section=settings#exclusion' ) );
			}

			$html = ( ! $gutenberg ) ? "<div class=\"permalink-manager-edit-uri-box\">" : "<div class=\"permalink-manager-gutenberg permalink-manager-edit-uri-box\">";
			$html .= sprintf( '<p class="uri_locked">%s</p>', $alert );
			$html .= "</div>";
		} else {
			// Auto-update settings
			$auto_update_def_val = $permalink_manager_options["general"]["auto_update_uris"];

			if ( $auto_update_def_val == 1 ) {
				$auto_update_def_label = __( "Auto-update \"Custom permalink\"", "permalink-manager" );
			} else if ( $auto_update_def_val == 2 ) {
				$auto_update_def_label = __( "Don't save/generate custom permalinks", "permalink-manager" );
			} else {
				$auto_update_def_label = __( "Don't auto-update \"Custom permalink\"", "permalink-manager" );
			}

			$auto_update_choices = array(
				/* translators: The global value of the "Auto-update" mode setting */
				0   => array( "label" => sprintf( __( "Use global settings [%s]", "permalink-manager" ), $auto_update_def_label ), "atts" => "data-readonly=\"{$auto_update_def_val}\"" ),
				10  => '---',
				- 1 => array( "label" => __( "Don't auto-update \"Custom permalink\"", "permalink-manager" ), "atts" => "data-readonly=\"0\"" ),
				- 2 => array( "label" => __( "Don't auto-update \"Custom permalink\" and exclude from the \"Regenerate/reset\" tool", "permalink-manager" ), "atts" => "data-readonly=\"0\"" ),
				1   => array( "label" => __( "Auto-update \"Custom permalink\"", "permalink-manager" ), "atts" => "data-readonly=\"1\"" ),
				11  => '---',
				2   => array( "label" => __( "Disable custom permalink (disallow further changes)", "permalink-manager" ), "atts" => "data-readonly=\"2\"" ),
			);

			// Decode default URI
			$default_uri = rawurldecode( $default_uri );

			// Start HTML output
			// 1. Button
			if ( ! $gutenberg ) {
				$html = sprintf( "<span><button type=\"button\" class=\"button button-small hide-if-no-js\" id=\"permalink-manager-toggle\">%s</button></span>", __( "Permalink Manager", "permalink-manager" ) );

				$html .= "<div id=\"permalink-manager\" class=\"postbox permalink-manager-edit-uri-box\" style=\"display: none;\">";

				// 2. The heading
				$html .= "<a class=\"close-button\"><span class=\"screen-reader-text\">" . __( "Close: ", "permalink-manager" ) . __( "Permalink Manager", "permalink-manager" ) . "</span><span class=\"close-icon\" aria-hidden=\"false\"></span></a>";
				$html .= sprintf( "<h2><span>%s</span></h2>", __( "Permalink Manager", "permalink-manager" ) );

				// 3. The fields container [start]
				$html .= "<div class=\"inside\">";
			} else {
				$html = "<div class=\"permalink-manager-gutenberg permalink-manager-edit-uri-box\">";
			}

			// 4. Custom URI
			if ( ! empty( $is_front_page ) ) {
				$custom_uri_field = self::generate_option_field( "custom_uri", array( "type" => "hidden", "extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => rawurldecode( $uri ) ) );
				$custom_uri_field .= __( "The custom URI cannot be edited on frontpage.", "permalink-manager" );
			} else {
				$custom_uri_field = self::generate_option_field( "custom_uri", array( "extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => rawurldecode( $uri ) ) );
				$custom_uri_field .= sprintf( '<p class="uri_locked hidden">%s %s</p>', '<span class="dashicons dashicons-lock"></span>', __( 'The URL above is displayed in read-only mode. To enable editing, change the "<strong>Permalink update</strong>" setting to <em>Don\'t auto-update "Custom permalink"</em>.', 'permalink-manager' ) );
			}

			$html .= sprintf( "<div class=\"custom_uri_container\"><p><label for=\"custom_uri\" class=\"strong\">%s</label></p><span>%s</span><span class=\"duplicated_uri_alert\"></span></div>", __( "Custom permalink", "permalink-manager" ), $custom_uri_field );

			// 5. Auto-update URI
			if ( empty( $is_front_page ) ) {
				if ( ! empty( $auto_update_choices ) ) {
					$html .= sprintf( "<div><p><label for=\"auto_auri\" class=\"strong\">%s %s</label></p><span>%s</span></div>", __( "Permalink update", "permalink-manager" ), self::help_tooltip( __( "If 'auto-update mode' is turned on, the 'Custom permalink' field will be automatically changed to 'Default custom permalink' (displayed below) after the post is saved or updated.", "permalink-manager" ) ), self::generate_option_field( "auto_update_uri", array( "type" => "select", "input_class" => "widefat auto_update", "value" => $auto_update_val, "choices" => $auto_update_choices ) ) );
				}
			}

			// 6. Native slug
			if ( ! empty( $element->ID ) && ! empty( $permalink_manager_options["general"]["show_native_slug_field"] ) ) {
				$native_slug_field = self::generate_option_field( "native_slug", array( "extra_atts" => "data-default=\"{$native_slug}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat native_slug", "value" => rawurldecode( $native_slug ) ) );

				$html .= sprintf( "<div class=\"native_slug_container\"><p><label for=\"native_slug\" class=\"strong\">%s %s</label></p><span>%s</span></div>", __( "Native slug", "permalink-manager" ), self::help_tooltip( __( "The native slug is by default automatically used in native permalinks (when Permalink Manager is disabled).", "permalink-manager" ) ), $native_slug_field );
			}

			if ( empty( $is_front_page ) ) {
				// 7. Default custom permalink
				$html .= "<div class=\"default-permalink-row columns-container\">";
				$html .= sprintf( "<span class=\"column-3_4\"><strong>%s:</strong> %s</span>", __( "Default custom permalink", "permalink-manager" ), esc_html( $default_uri ) );
				$html .= sprintf( "<span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span>", __( "Use \"Default custom permalink\"", "permalink-manager" ) );
				// $html .= sprintf( "<span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\" target=\"_blank\"><span class=\"dashicons dashicons-external\"></span> %s</a></span>", __( "Go to \"Permastructures\"", "permalink-manager" ) );
				$html .= "</div>";

				// 8. Native permalink info
				if ( ! empty( $permalink_manager_options['general']['redirect'] ) && ! ( ! empty( $element->post_status ) && in_array( $element->post_status, array( 'auto-draft', 'trash', 'draft' ) ) ) ) {
					$native_permalink = trim( Permalink_Manager_Permastructure_Functions::get_permalink_base( $element ), "/" ) . "/";
					$native_permalink .= $native_uri;

					$native_permalink_label = ( $native_uri === $uri ) ? __( "Original WordPress permalink:", "permalink-manager" ) : __( "Original WordPress permalink (redirected):", "permalink-manager" );

					$html .= sprintf( "<div class=\"default-permalink-row columns-container\"><span><strong>%s</strong> <a href=\"%s\">%s</a></span></div>", $native_permalink_label, $native_permalink, rawurldecode( $native_uri ) );
				}
			}

			// 9. Custom redirects
			$html .= ( $element->ID ) ? self::display_redirect_panel( $id ) : self::display_redirect_panel( "tax-{$id}" );

			// 10. Extra save button for Gutenberg
			if ( $gutenberg ) {
				$html .= sprintf( "<div class=\"default-permalink-row save-row columns-container hidden\"><div><a href=\"#\" class=\"button button-primary\" id=\"permalink-manager-save-button\">%s</a></div></div>", __( "Save permalink", "permalink-manager" ) );
			} else {
				$html .= "</div>";
			}

			$html .= "</div>";
		}

		// 11. Append nonce field, element ID & native slug
		$html .= self::generate_option_field( "permalink-manager-edit-uri-element-slug", array( "type" => "hidden", "value" => $native_slug ) );
		$html .= self::generate_option_field( "permalink-manager-edit-uri-element-id", array( "type" => "hidden", "value" => $element_id ) );
		$html .= wp_nonce_field( 'permalink-manager-edit-uri-box', 'permalink-manager-nonce', true, false );

		return $html;
	}

	/**
	 * Get the HTML output of the redirect panel
	 *
	 * @param string|int $element_id
	 *
	 * @return string
	 */
	public static function display_redirect_panel( $element_id ) {
		// Heading
		$html = "<div class=\"permalink-manager redirects-row redirects-panel columns-container\">";
		$html .= sprintf( "<div><a class=\"button\" href=\"#\" id=\"toggle-redirect-panel\">%s</a></div>", __( "Manage redirects", "permalink-manager" ) );

		$html .= "<div id=\"redirect-panel-inside\">";
		if ( class_exists( 'Permalink_Manager_Pro_Addons' ) ) {
			$html .= Permalink_Manager_Pro_Addons::display_redirect_form( $element_id );
		} else {
			$html .= self::pro_text( true );
		}
		$html .= "</div>";
		$html .= "</div>";

		return $html;
	}

	/**
	 * Hide "Custom URI" column
	 *
	 * @param array $hidden
	 *
	 * @return array
	 */
	function quick_edit_hide_column( $hidden ) {
		$hidden[] = 'permalink-manager-col';

		return $hidden;
	}

	/**
	 * Display the simplified URI Editor in "Quick Edit" mode
	 *
	 * @param string $column_name
	 * @param string $post_type
	 * @param string $taxonomy
	 */
	public static function quick_edit_column_form( $column_name, $post_type, $taxonomy = '' ) {
		// Check the user capabilities
		if ( Permalink_Manager_Admin_Functions::current_user_can_edit_uris() === false || $column_name !== 'permalink-manager-col' ) {
			return;
		}

		$html = Permalink_Manager_UI_Elements::generate_option_field( 'permalink-manager-quick-edit', array( 'value' => true, 'type' => 'hidden' ) );
		$html .= '<fieldset class="inline-edit-permalink">';
		$html .= sprintf( "<legend class=\"inline-edit-legend\">%s</legend>", __( "Permalink Manager", "permalink-manager" ) );

		$html .= '<div class="inline-edit-col">';
		$html .= sprintf( "<label class=\"inline-edit-group\"><span class=\"title\">%s</span><span class=\"input-text-wrap\">%s</span></label>", __( "Custom permalink", "permalink-manager" ), Permalink_Manager_UI_Elements::generate_option_field( "custom_uri", array( "input_class" => "custom_uri", "value" => '' ) ) );
		$html .= "</div>";

		$html .= "</fieldset>";

		// Append nonce field & element ID
		$html .= Permalink_Manager_UI_Elements::generate_option_field( "permalink-manager-edit-uri-element-id", array( "type" => "hidden", "input_class" => "permalink-manager-edit-uri-element-id", "value" => "" ) );
		$html .= wp_nonce_field( 'permalink-manager-edit-uri-box', 'permalink-manager-nonce', true, false );

		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo $html;
	}

	/**
	 * Get the HTML output of error/info message
	 *
	 * @param string $alert_content
	 * @param string $alert_type
	 * @param bool $dismissible
	 * @param bool $id
	 *
	 * @return string
	 */
	public static function get_alert_message( $alert_content = "", $alert_type = "", $dismissible = true, $id = false ) {
		// Ignore empty messages (just in case)
		if ( empty( $alert_content ) || empty( $alert_type ) ) {
			return "";
		}

		$class    = ( $dismissible ) ? "is-dismissible" : "";
		$alert_id = ( $id ) ? " data-alert_id=\"{$id}\"" : "";

		return sprintf( "<div class=\"{$alert_type} permalink-manager-notice notice {$class}\"{$alert_id}> %s</div>", wpautop( $alert_content ) );
	}

	/**
	 * Get the HTML output of help tooltip
	 *
	 * @param string $text
	 *
	 * @return string
	 */
	static function help_tooltip( $text = '' ) {
		return " <a href=\"#\" title=\"{$text}\" class=\"help_tooltip\"><span class=\"dashicons dashicons-editor-help\"></span></a>";
	}

	/**
	 * Display the license expiration date (in Pro version) or information about the premium functionality
	 *
	 * @param string $text_only
	 *
	 * @return string
	 */
	static function pro_text( $text_only = false ) {
		if ( class_exists( 'Permalink_Manager_Pro_License' ) ) {
			$text = Permalink_Manager_Pro_License::get_expiration_date( false, true );
		} else {
			/* translators: Permalink Manager Pro website */
			$text = sprintf( __( 'This functionality is available only in <a href="%s" target="_blank">Permalink Manager Pro</a>.', 'permalink-manager' ), PERMALINK_MANAGER_PROMO );
		}

		return ( $text_only ) ? $text : sprintf( "<div class=\"alert info\"> %s</div>", wpautop( $text, 'alert' ) );
	}
}