<?php
/**
 * Widget Base Class
 *
 * @package errigal
 * @since 1.0.3
 */

namespace Errigal\Widget;

defined( 'ABSPATH' ) || exit;

use Errigal\Constant\{
	Errigal_Component_Class as Component_Class,
	Errigal_Html_Attr as Html_Attr,
	Errigal_Html_Option as Html_Option,
	Errigal_WP_Class as WP_Class,
};
use Errigal\Shared\{
	Errigal_Html_Builder as Html_Builder,
	Errigal_Validator as Validator,
};
use WP_Widget;

/**
 * This class is in charge of providing shared widget functions.
 *
 * @since 1.0.3
 *
 * @link https://developer.wordpress.org/reference/classes/wp_widget/
 */
abstract class Errigal_Widget_Base extends WP_Widget {
	/**
	 * Image: class.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	public const IMAGE_CLASS = 'image_class';

	/**
	 * Image: URL.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	public const IMAGE_URL = 'image_url';

	/**
	 * Image: alt.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	public const IMAGE_ALT = 'image_alt';

	/**
	 * Widget: classname.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/__construct/
	 *
	 * @var string
	 */
	protected const WIDGET_CLASSNAME = 'classname';

	/**
	 * Widget: description.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/__construct/
	 *
	 * @var string
	 */
	protected const WIDGET_DESCRIPTION = 'description';

	/**
	 * Widget: customize_selective_refresh.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/__construct/
	 *
	 * @var string
	 */
	protected const WIDGET_CUSTOMIZE_SELECTIVE_REFRESH = 'customize_selective_refresh';

	/**
	 * Control: label.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	protected const CONTROL_LABEL = 'label';

	/**
	 * Control: type.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	protected const CONTROL_TYPE = 'type';

	/**
	 * Control: Type: text.
	 *
	 * @since 1.0.3
	 *
	 * @var string
	 */
	protected const CONTROL_TYPE_TEXT = 'text';

	/**
	 * Control: Type: textarea.
	 *
	 * @since 1.0.3
	 *
	 * @var string
	 */
	protected const CONTROL_TYPE_TEXTAREA = 'textarea';

	/**
	 * Control: Type: dropdown-pages.
	 *
	 * @since 1.0.3
	 *
	 * @var string
	 */
	protected const CONTROL_TYPE_DROPDOWN_PAGES = 'dropdown-pages';

	/**
	 * Control: Type: URL.
	 *
	 * @since 1.0.3
	 *
	 * @var string
	 */
	protected const CONTROL_TYPE_URL = 'url';

	/**
	 * Control: Type: image.
	 *
	 * @since 1.0.3
	 *
	 * @var string
	 */
	protected const CONTROL_TYPE_IMAGE = 'image';

	/**
	 * Control: default.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	protected const CONTROL_DEFAULT = 'default';

	/**
	 * Control: value.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	protected const CONTROL_VALUE = 'value';

	/**
	 * Control: control_options.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	protected const CONTROL_OPTIONS = 'control_options';

	/**
	 * Control: control_options: image_type.
	 *
	 * @since 1.2.0
	 *
	 * @var string
	 */
	protected const CONTROL_OPTIONS_IMAGE_TYPE = 'image_type';

	/**
	 * Control: control_options: is_circle_image.
	 *
	 * @since 1.1.0
	 *
	 * @var string
	 */
	protected const CONTROL_OPTIONS_IS_CIRCLE_IMAGE = 'is_circle_image';

	/**
	 * Widget arg: before_widget.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/widget/
	 *
	 * @var string
	 */
	protected const WIDGET_ARG_BEFORE_WIDGET = 'before_widget';

	/**
	 * Widget arg: after_widget.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/widget/
	 *
	 * @var string
	 */
	protected const WIDGET_ARG_AFTER_WIDGET = 'after_widget';

	/**
	 * Widget arg: before_title.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/widget/
	 *
	 * @var string
	 */
	protected const WIDGET_ARG_BEFORE_TITLE = 'before_title';

	/**
	 * Widget arg: after_title.
	 *
	 * @since 1.1.0
	 *
	 * @link https://developer.wordpress.org/reference/classes/wp_widget/widget/
	 *
	 * @var string
	 */
	protected const WIDGET_ARG_AFTER_TITLE = 'after_title';

	/**
	 * Control: id.
	 *
	 * @since 1.2.0
	 *
	 * @var string
	 */
	private const CONTROL_ID = 'id';

	/**
	 * Renders form.
	 *
	 * @since 1.0.3
	 *
	 * @param array $form_controls Associative array of arguments for form.
	 *                             See Errigal_Widget_Base::render_form_control() for information on accepted arguments.
	 * @return void
	 */
	final protected function render_form( $form_controls ) {
		if ( ! Validator::is_associative_array( $form_controls ) ) {
			return;
		}

		foreach ( $form_controls as $id => $args ) {
			self::render_form_control( $id, $args );
		}
	}

	/**
	 * Renders form control.
	 *
	 * @since 1.0.3
	 *
	 * @param string $id   Control ID.
	 * @param array  $args {
	 *     Optional. Associative array of arguments for form control.
	 *
	 *     @type string $label           Optional. Label for control. Default empty string.
	 *     @type string $type            Optional. Control type. Core controls include 'dropdown-pages', 'image', 'text', 'textarea'.
	 *                                   Additional input types such as 'url' are supported implicitly. Default 'text'.
	 *     @type string $default         Optional. Default value control. Default empty string.
	 *     @type string $value           Optional. Value for control. Default empty string.
	 *     @type array  $control_options {
	 *         Optional. Associative array of optional arguments for form control.
	 *
	 *         @type string $image_type      Optional. Image type. Default empty string.
	 *         @type bool   $is_circle_image Optional. Whether to show image in circle. This is for 'image' only. Default false.
	 *     }
	 * }
	 * @return void
	 */
	protected function render_form_control( $id, $args ) {
		if (
			! Validator::is_non_empty_string( $id ) ||
			! Validator::is_associative_array( $args )
		) {
			return;
		}

		$args = wp_parse_args(
			$args,
			array(
				self::CONTROL_ID      => $id,
				self::CONTROL_LABEL   => '',
				self::CONTROL_TYPE    => self::CONTROL_TYPE_TEXT,
				self::CONTROL_DEFAULT => '',
				self::CONTROL_VALUE   => '',
				self::CONTROL_OPTIONS => array(),
			)
		);

		$type = $args[ self::CONTROL_TYPE ];

		if (
			! Validator::is_non_empty_string( $type ) ||
			! Validator::is_non_empty_string( $args[ self::CONTROL_LABEL ] ) ||
			! is_string( $args[ self::CONTROL_DEFAULT ] ) ||
			! is_array( $args[ self::CONTROL_OPTIONS ] )
		) {
			return;
		}

		if ( self::CONTROL_TYPE_DROPDOWN_PAGES === $type ) {
			Html_Builder::create( $args )->create_p()->render_element(
				function ( $html_builder ) {
					if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
						return;
					}

					$id = $html_builder->get_arg( self::CONTROL_ID );

					$this->render_label( $html_builder->get_args() );
					wp_dropdown_pages(
						array(
							'selected'          => esc_attr(
								$html_builder->get_arg( self::CONTROL_VALUE )
							),
							'name'              => esc_attr( $this->get_field_name( $id ) ),
							'id'                => esc_attr( $this->get_field_id( $id ) ),
							'class'             => 'errigal-widget__select',
							'show_option_none'  => esc_html(
								$html_builder->get_arg( self::CONTROL_DEFAULT )
							),
							'option_none_value' => '0',
						)
					);
				}
			);

			return;
		}

		if ( self::CONTROL_TYPE_IMAGE === $type ) {
			$args[ self::CONTROL_OPTIONS ] = wp_parse_args(
				$args[ self::CONTROL_OPTIONS ],
				array(
					self::CONTROL_OPTIONS_IMAGE_TYPE      => '',
					self::CONTROL_OPTIONS_IS_CIRCLE_IMAGE => false,
				)
			);

			if ( ! Validator::is_non_empty_string( $args[ self::CONTROL_OPTIONS ][ self::CONTROL_OPTIONS_IMAGE_TYPE ] ) ) {
				return;
			}

			Html_Builder::create( $args )->create_div(
				array(
					Html_Option::ATTRS => array(
						Html_Attr::CLASS_NAME => array(
							'errigal-widget__image-control',
							Validator::is_non_empty_string( $args[ self::CONTROL_VALUE ] )
								? 'has-image'
								: null,
						),
					),
				)
			)->render_element(
				function ( $html_builder ) {
					if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
						return;
					}

					$this->render_label( $html_builder->get_args() );
					$html_builder->create_div(
						array(
							Html_Option::ATTRS => array(
								Html_Attr::CLASS_NAME => array(
									'errigal-widget__image-container',
									Validator::is_true(
										$html_builder->get_arg(
											self::CONTROL_OPTIONS,
											self::CONTROL_OPTIONS_IS_CIRCLE_IMAGE
										)
									)
										? 'circle-image'
										: null,
								),
							),
						)
					)->render_element(
						function ( $html_builder ) {
							if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
								return;
							}

							$id    = $html_builder->get_arg( self::CONTROL_ID );
							$value = $html_builder->get_arg( self::CONTROL_VALUE );

							get_template_part(
								'template-parts/component/widget/image',
								null,
								array(
									self::IMAGE_CLASS => 'errigal-widget__image',
									self::IMAGE_URL   => esc_url( $value ),
									self::IMAGE_ALT   => esc_attr( $html_builder->get_arg( self::CONTROL_LABEL ) ),
								)
							);
							$html_builder->create_input(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::TYPE  => 'url',
										Html_Attr::ID    => $this->get_field_id( $id ),
										Html_Attr::NAME  => $this->get_field_name( $id ),
										Html_Attr::CLASS_NAME => array(
											WP_Class::WIDEFAT,
											'errigal-widget__image-path',
										),
										Html_Attr::VALUE => esc_url( $value ),
									),
								)
							)->render_element();
						}
					);
					$html_builder->create_div(
						array(
							Html_Option::ATTRS => array(
								Html_Attr::CLASS_NAME => 'errigal-widget__add-image-button-container',
							),
						)
					)->render_element(
						function ( $html_builder ) {
							if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
								return;
							}

							$html_builder->create_button(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::CLASS_NAME => 'errigal-widget__add-image-button',
										Html_Attr::TYPE => Html_Attr::VALUE_BUTTON,
									),
								)
							)->render_element(
								esc_html(
									sprintf(
										/* translators: %s: Image type. */
										__( 'Add %s', 'errigal' ),
										$html_builder->get_arg(
											self::CONTROL_OPTIONS,
											self::CONTROL_OPTIONS_IMAGE_TYPE
										)
									)
								)
							);
						}
					);
					$html_builder->create_div(
						array(
							Html_Option::ATTRS => array(
								Html_Attr::CLASS_NAME => 'errigal-widget__image-buttons-container',
							),
						)
					)->render_element(
						function ( $html_builder ) {
							if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
								return;
							}

							$image_type = $html_builder->get_arg(
								self::CONTROL_OPTIONS,
								self::CONTROL_OPTIONS_IMAGE_TYPE
							);

							$html_builder->create_button(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::CLASS_NAME => array(
											Component_Class::BUTTON,
											'errigal-widget__remove-image-button',
										),
										Html_Attr::TYPE => Html_Attr::VALUE_BUTTON,
									),
								)
							)->render_element(
								esc_html(
									sprintf(
										/* translators: %s: Image type. */
										__( 'Remove %s', 'errigal' ),
										$image_type
									)
								)
							);
							$html_builder->create_button(
								array(
									Html_Option::ATTRS => array(
										Html_Attr::CLASS_NAME => array(
											Component_Class::BUTTON,
											'errigal-widget__change-image-button',
										),
										Html_Attr::TYPE => Html_Attr::VALUE_BUTTON,
									),
								)
							)->render_element(
								esc_html(
									sprintf(
										/* translators: %s: Image type. */
										__( 'Change %s', 'errigal' ),
										$image_type
									)
								)
							);
						}
					);
				}
			);

			return;
		}

		if (
			self::CONTROL_TYPE_TEXT === $type ||
			self::CONTROL_TYPE_URL === $type
		) {
			Html_Builder::create( $args )->create_p()->render_element(
				function ( $html_builder ) use ( $type ) {
					if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
						return;
					}

					$id = $html_builder->get_arg( self::CONTROL_ID );

					$this->render_label( $html_builder->get_args() );
					$html_builder->create_input(
						array(
							Html_Option::ATTRS => array(
								Html_Attr::TYPE       => $type,
								Html_Attr::ID         => $this->get_field_id( $id ),
								Html_Attr::NAME       => $this->get_field_name( $id ),
								Html_Attr::CLASS_NAME => array(
									WP_Class::WIDEFAT,
									'errigal-widget__text',
								),
								Html_Attr::VALUE      => $html_builder->get_arg( self::CONTROL_VALUE ),
							),
						)
					)->render_element();
				}
			);

			return;
		}

		if ( self::CONTROL_TYPE_TEXTAREA === $type ) {
			Html_Builder::create( $args )->create_p()->render_element(
				function ( $html_builder ) use ( $type ) {
					if ( ! Html_Builder::is_html_builder( $html_builder ) ) {
						return;
					}

					$id = $html_builder->get_arg( self::CONTROL_ID );

					$this->render_label( $html_builder->get_args() );
					$html_builder->create_textarea(
						array(
							Html_Option::ATTRS => array(
								Html_Attr::TYPE       => $type,
								Html_Attr::ID         => $this->get_field_id( $id ),
								Html_Attr::NAME       => $this->get_field_name( $id ),
								Html_Attr::CLASS_NAME => array(
									WP_Class::WIDEFAT,
									'errigal-widget__textarea',
								),
								Html_Attr::ROWS       => 6,
								Html_Attr::COLS       => 20,
							),
						)
					)->render_element(
						esc_textarea(
							$html_builder->get_arg( self::CONTROL_VALUE )
						)
					);
				}
			);
		}
	}

	/**
	 * Renders label.
	 *
	 * @since 1.0.3
	 *
	 * @param array $args {
	 *     Associative array of arguments for form control.
	 *
	 *     @type string $id    Control ID.
	 *     @type string $label Label for control.
	 * }
	 * @return void
	 */
	private function render_label( $args ) {
		$args = wp_parse_args(
			$args,
			array(
				self::CONTROL_ID    => '',
				self::CONTROL_LABEL => '',
			)
		);

		$id    = $args[ self::CONTROL_ID ];
		$label = $args[ self::CONTROL_LABEL ];

		if (
			! Validator::is_non_empty_string( $id ) ||
			! Validator::is_non_empty_string( $label )
		) {
			return;
		}

		Html_Builder::create()->create_label(
			array(
				Html_Option::ATTRS => array(
					Html_Attr::FOR => $this->get_field_id( $id ),
				),
			)
		)->render_element(
			esc_html( $label . ':' )
		);
	}
}
