<?php
/**
 * Content Hooks Class
 *
 * @package errigal
 * @since 1.1.0
 */

namespace Errigal\Hook;

defined( 'ABSPATH' ) || exit;

use Errigal\Constant\{
	Errigal_Component_Class as Component_Class,
	Errigal_Content_Hook as Content_Hook,
	Errigal_Navigation_Class as Navigation_Class,
	Errigal_Html_Attr as Html_Attr,
	Errigal_Html_Option as Html_Option,
	Errigal_WP_Hook as WP_Hook,
};
use Errigal\Content\Errigal_Content as Content;
use Errigal\Customiser\Errigal_Custom_Heading_Style as Heading_Style;
use Errigal\Shared\{
	Errigal_Html_Builder as Html_Builder,
	Errigal_Html_Schema as Html_Schema,
	Errigal_Utility as Utility,
	Errigal_Validator as Validator,
};

/**
 * This class is in charge of adding content hooks.
 *
 * @since 1.1.0
 */
class Errigal_Content_Hooks extends Errigal_Hooks_Base {
	/**
	 * Input ID.
	 *
	 * @since 1.2.0
	 *
	 * @see Errigal\Hook\Errigal_Content_Hooks::customise_password_form()
	 *
	 * @var string
	 */
	private const INPUT_ID = 'input_id';

	/**
	 * Customises password form.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/the_password_form/
	 *
	 * @param string      $output Password form HTML output.
	 * @param int|WP_Post $post   Optional. Post ID or WP_Post object. Default global $post.
	 * @return string
	 */
	public function customise_password_form( $output, $post = 0 ) {
		if ( Validator::is_non_empty_string( $output ) ) {
			$post         = get_post( $post );
			$html_builder = Html_Builder::create(
				array(
					$this::INPUT_ID => 'pwbox-' . (
						is_int( $post->ID )
							? $post->ID
							: wp_rand()
					),
				)
			);

			$output = $html_builder->create_p()->render_element(
				esc_html__( 'This content is password protected. To view it please enter your password below.', 'errigal' )
			);
			$html_builder->create_form(
				array(
					Html_Option::ATTRS => array(
						Html_Attr::CLASS_NAME => 'post-password-form',
						Html_Attr::ACTION     => site_url( 'wp-login.php?action=postpass', 'login_post' ),
						Html_Attr::METHOD     => Html_Attr::VALUE_POST,
					),
				)
			)->render_element(
				function ( $html_builder ) {
					if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
						return;
					}

					$html_builder->create_p(
						array(
							Html_Option::ATTRS => array(
								Html_Attr::CLASS_NAME => Component_Class::INPUT_FIELD,
							),
						)
					)->render_element(
						function ( $html_builder ) {
							if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
								return;
							}

							$html_builder->create_label(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::FOR => $html_builder->get_arg( $this::INPUT_ID ),
									),
								)
							)->render_element(
								esc_html_x( 'Password', 'Post password form', 'errigal' )
							);
							$html_builder->create_input(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::TYPE => 'password',
										Html_Attr::ID   => $html_builder->get_arg( $this::INPUT_ID ),
										Html_Attr::NAME => 'post_password',
										Html_Attr::REQUIRED => '',
										Html_Attr::SPELLCHECK => false,
										Html_Attr::SIZE => 20,
									),
								)
							)->render_element();
						}
					);
					$html_builder->create_p()->render_element(
						function ( $html_builder ) {
							if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
								return;
							}

							$html_builder->create_input(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::TYPE  => Html_Attr::VALUE_SUBMIT,
										Html_Attr::NAME  => _x( 'Submit', 'Post password form', 'errigal' ),
										Html_Attr::CLASS_NAME => array(
											'post-password-form__submit',
											Component_Class::BUTTON,
											Component_Class::OUTLINED,
										),
										Html_Attr::VALUE => _x( 'Enter', 'Post password form', 'errigal' ),
									),
								)
							)->render_element();
						}
					);
				}
			);
		}

		return $output;
	}

	/**
	 * Adds empty title fallback.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/the_title/
	 *
	 * @param string $post_title Post title.
	 * @return string
	 */
	public function add_empty_title_fallback( $post_title ) {
		if ( ! Validator::is_non_empty_string( $post_title ) ) {
			return esc_html_x( 'Untitled', 'Fallback for missing titles', 'errigal' );
		}

		return $post_title;
	}

	/**
	 * Adds class to paginated links.
	 *
	 * @since 1.0.0
	 *
	 * @link https://developer.wordpress.org/reference/hooks/wp_link_pages_args/
	 *
	 * @param array $parsed_args Associative array of arguments for page link.
	 *                           See wp_link_pages() for information on accepted arguments.
	 * @return array
	 */
	public function add_class_to_paginated_links( $parsed_args ) {
		if ( Validator::is_associative_array( $parsed_args ) ) {
			$parsed_args['next_or_number'] = 'number';

			if ( ! Content::is_paginated() ) {
				return $parsed_args;
			}

			$arg_before           = 'before';
			$arg_after            = 'after';
			$link_before          = $parsed_args['link_before'] ?? '';
			$link_after           = $parsed_args['link_after'] ?? '';
			$closing_anchor_tag   = Html_Builder::create()->create_a()->get_close_tag();
			$current_page_number  = Content::get_current_page_number();
			$previous_page_number = $current_page_number - 1;
			$next_page_number     = $current_page_number + 1;

			if ( $previous_page_number > 0 ) {
				$parsed_args[ $arg_before ] = wp_kses(
					( $parsed_args[ $arg_before ] ?? '' ) .
					str_replace(
						Navigation_Class::POST_PAGE_NUMBERS,
						Utility::get_class(
							Navigation_Class::PREV,
							Navigation_Class::POST_PAGE_NUMBERS
						),
						_wp_link_page( $previous_page_number )
					) .
					$link_before .
					( $parsed_args['previouspagelink'] ?? '' ) .
					$link_after .
					$closing_anchor_tag,
					Html_Schema::get_allowed_html_post_svg()
				);
			}

			if ( $next_page_number <= Content::get_total_pages() ) {
				$parsed_args[ $arg_after ] = wp_kses(
					str_replace(
						Navigation_Class::POST_PAGE_NUMBERS,
						Utility::get_class(
							Navigation_Class::NEXT,
							Navigation_Class::POST_PAGE_NUMBERS
						),
						_wp_link_page( $next_page_number )
					) .
					$link_before .
					( $parsed_args['nextpagelink'] ?? '' ) .
					$link_after .
					$closing_anchor_tag .
					( $parsed_args[ $arg_after ] ?? '' ),
					Html_Schema::get_allowed_html_post_svg()
				);
			}
		}

		return $parsed_args;
	}

	/**
	 * Adds entry content classes.
	 *
	 * @since 1.1.0
	 *
	 * @see Errigal\Content\Errigal_Content::get_entry_content_classes()
	 *
	 * @param string[] $classes Site content class names.
	 * @return string[]
	 */
	public function add_entry_content_classes( $classes ) {
		if ( Validator::is_string_list( $classes ) ) {
			$classes[] = Heading_Style::get_heading_style_class();

			return Utility::sanitise_classes( $classes );
		}

		return $classes;
	}

	/**
	 * Adds hooks.
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	protected function add_hooks() {
		add_filter( WP_Hook::THE_PASSWORD_FORM, array( $this, 'customise_password_form' ), WP_Hook::PRIORITY_DEFAULT, 2 );
		add_filter( WP_Hook::THE_TITLE, array( $this, 'add_empty_title_fallback' ) );
		add_filter( WP_Hook::WP_LINK_PAGES_ARGS, array( $this, 'add_class_to_paginated_links' ) );
		add_filter( Content_Hook::ENTRY_CONTENT_CLASSES, array( $this, 'add_entry_content_classes' ) );
	}
}
