<?php
/**
 * Item block settings.
 *
 * @package Tasty_Roundups
 */

namespace Tasty_Roundups\Blocks;

use Tasty_Roundups\Block_Editor;

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

if ( ! class_exists( '\Tasty_Roundups\Blocks\Item_Block' ) ) {
	/**
	 * The container block class.
	 */
	class Item_Block {
		/**
		 * The global settings.
		 *
		 * @var array
		 */
		private $settings = array();

		/**
		 * The block content.
		 *
		 * @var string
		 */
		private $content = '';

		/**
		 * The block object
		 *
		 * @var WP_Block
		 */
		private $block;

		/**
		 * The block attributes.
		 *
		 * @var array
		 */
		private $attributes = array();

		/**
		 * The class names for the item wrapper.
		 *
		 * @var array
		 */
		private $item_classes = array();

		/**
		 * Apply the user settings customizations.
		 *
		 * @since 2.0
		 *
		 * @param string $output The block output.
		 * @return string
		 */
		public static function apply_customization_settings( $output ) {
			if ( false === stripos( $output, 'data-tasty-roundups-customization' ) ) {
				return $output;
			}
			$settings = Block_Editor::get_customization_settings();
			/**
			 * Allow the customization settings to be modified based on context.
			 *
			 * @var array $settings Customization settings.
			 */
			$settings = apply_filters( 'tasty_roundups_customization_settings', $settings );
			$output   = preg_replace_callback(
				'#<[a-z]+[^>]+data-tasty-roundups-customization=[\'"](?<options>[^\'"]+)[\'"][^>]*>#U',
				function ( $matches ) use ( $settings ) {
					$element = $matches[0];
					$styles  = '';
					foreach ( explode( ' ', $matches['options'] ) as $option ) {
						if ( false === stripos( $option, '.' ) ) {
							continue;
						}

						list( $key, $css_property ) = explode( '.', $option );

						if ( in_array( $css_property, array( 'innerHTML', 'innerText' ), true ) ) {
							continue;
						}

						$key = str_replace( '-', '_', $key );
						if ( empty( $settings[ $key ] ) ) {
							continue;
						}

						$value = $settings[ $key ];
						if ( in_array( $css_property, array( 'border-radius', 'border-width' ), true )
							&& is_numeric( $value ) ) {
							$value .= 'px';
						}

						$styles .= $css_property . ': ' . $value . ' !important; ';
					}

					if ( ! $styles ) {
						return $element;
					}

					$styles = trim( $styles );
					if ( preg_match( '#style=[\'"](?<existing>[^\'"]+)[\'"]#', $element, $inline_style ) ) {
						$element = str_replace(
							$inline_style[0],
							str_replace(
								$inline_style['existing'],
								rtrim( $inline_style['existing'], '; ' ) . '; ' . $styles,
								$inline_style[0]
							),
							$element
						);
					} else {
						$element = str_replace(
							' data-tasty-roundups-customization',
							' style="' . esc_attr( $styles ) . '" data-tasty-roundups-customization',
							$element
						);
					}
					return $element;
				},
				$output
			);

			return $output;
		}

		/**
		 * Construct the object.
		 *
		 * @param array     $attributes The block attributes.
		 * @param string    $content    The block content.
		 * @param \WP_block $block      The block object.
		 */
		public function __construct( $attributes, $content, $block ) {
			$this->settings   = Block_Editor::get_customization_settings();
			$this->content    = $content;
			$this->block      = $block;
			$this->attributes = wp_parse_args( $attributes, $this->get_default_attributes() );
		}

		/**
		 * Render the block.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		public function render() {
			if ( empty( $this->attributes['title'] ) &&
				empty( $this->attributes['description'] )
			) {
				return '';
			}

			$image_align_class    = $this->attributes['imageClassName'];
			$this->item_classes[] = "tasty-roundups-item $image_align_class";
			$display_numbers      = 'on' === $this->settings['numbers'] ? true : false;
			$disable_description  = $this->block->context['tasty-roundups/disableDescription'] ?? false;

			if ( isset( $this->block->context['tasty-roundups/displayNumbers'] ) ) {
				$display_numbers = 'on' === $this->block->context['tasty-roundups/displayNumbers'] ? true : false;
			}

			$number_html  = $this->get_number_html( $display_numbers );
			$link_start   = $this->get_link_start_html();
			$link_end     = $this->get_link_end_html();
			$media_html   = $this->get_media_html();
			$meta_html    = $this->get_meta_html();
			$button_html  = $this->get_button_html();
			$item_classes = implode( ' ', $this->item_classes );

			$output = tasty_roundups_get_template_part(
				'tasty-roundups-item',
				array(
					'attributes'          => $this->attributes,
					'content'             => $this->content,
					'item_classes'        => $item_classes,
					'link_start'          => $link_start,
					'link_end'            => $link_end,
					'number_html'         => $number_html,
					'media_html'          => $media_html,
					'meta_html'           => $meta_html,
					'button_html'         => $button_html,
					'disable_description' => $disable_description,
				)
			);

			$output = $this->apply_customization_settings( $output );

			return $output;
		}

		/**
		 * Generate the button HTML.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_button_html() {
			$button_html    = '';
			$disable_button = $this->block->context['tasty-roundups/disableButton'] ?? false;

			if ( $disable_button ) {
				return $button_html;
			}

			$button_text = ! empty( $this->attributes['buttonText'] ) ? $this->attributes['buttonText'] : $this->settings['button_text'];

			if ( ! empty( $button_text ) ) {
				$custom_styles = 'button-background-color.background button-text-color.color button-border-radius.border-radius';
				$button_class  = $this->get_button_classes();

				$button_link_start = str_replace(
					'<a ',
					'<a class="' . $button_class . '" data-tasty-roundups-customization="' . esc_attr( $custom_styles ) . '" ',
					$this->get_link_start_html()
				);

				$button_html = $button_link_start . wp_kses_post( $button_text ) . $this->get_link_end_html();
			}

			return $button_html;
		}

		/**
		 * Generate the button classes.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_button_classes() {
			$button_class = 'tasty-roundups-button';

			switch ( $this->block->context['tasty-roundups/buttonStyle'] ?? 'filled' ) {
				case 'filled':
					$button_class .= ' tasty-roundups-button-filled';
					break;
				case 'outline':
					$button_class .= ' tasty-roundups-button-outline';
					break;
				case 'link':
					$button_class .= ' tasty-roundups-button-link';
					break;
			}

			return $button_class;
		}

		/**
		 * Render the meta HTML.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_meta_html() {
			$meta_html     = '';
			$ratings_html  = $this->get_ratings_html();
			$comments_html = $this->get_comments_html();

			$add_meta_wrapper = $ratings_html || $comments_html;

			if ( $add_meta_wrapper ) {
				$meta_html = '<div class="tasty-roundups-meta">';
			}

			if ( ! empty( $ratings_html ) ) {
				$meta_html .= $ratings_html;
			}

			if ( ! empty( $ratings_html ) && ! empty( $comments_html ) ) {
				$meta_html .= $this->get_meta_separator_icon();
			}

			if ( ! empty( $comments_html ) ) {
				$meta_html .= $comments_html;
			}

			if ( $add_meta_wrapper ) {
				$meta_html .= '</div>';
			}

			return $meta_html;
		}

		/**
		 * Render the separator icon
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_meta_separator_icon() {
			return '<svg class="tasty-roundups-meta-separator" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 4 4" width="4" height="4"><path fill="currentColor" d="M2 4a1.94 1.94 0 0 1-1.005-.268 2.09 2.09 0 0 1-.727-.727A1.94 1.94 0 0 1 0 2c0-.37.09-.705.268-1.005C.45.692.692.452.995.273A1.916 1.916 0 0 1 2 0c.37 0 .705.09 1.005.273.303.179.543.42.722.722C3.91 1.295 4 1.63 4 2c0 .367-.09.702-.273 1.005-.179.303-.42.545-.722.727C2.705 3.91 2.37 4 2 4Z" opacity="0.5" /></svg>';
		}

		/**
		 * Generate the comments HTML
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_comments_html() {
			$comments_html    = '';
			$disable_comments = $this->block->context['tasty-roundups/disableComments'] ?? false;

			if ( $disable_comments ) {
				return $comments_html;
			}

			$post_id = ! empty( $this->attributes['postId'] ) ? $this->attributes['postId'] : false;

			if ( $post_id && comments_open( $post_id ) ) {
				$comments_html  = '<div class="tasty-roundups-post-comments">';
				$comments_html .= $this->get_comments_icon();
				$comments_html .= '<p>' . (int) get_comments_number( $post_id ) . '</p>';
				$comments_html .= '</div>';
			}

			return $comments_html;
		}

		/**
		 * Generate the comments icon.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_comments_icon() {
			return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 14.25c3.866 0 7.25-2.095 7.25-6.75C15.25 2.845 11.866.75 8 .75S.75 2.845.75 7.5c0 1.768.488 3.166 1.305 4.22.239.31.334.72.168 1.073-.1.215-.207.42-.315.615-.454.816.172 2.005 1.087 1.822 1.016-.204 2.153-.508 3.1-.956.198-.094.418-.13.636-.103.414.053.838.079 1.269.079Z"></svg>';
		}

		/**
		 * Generate the HTML for the ratings summary.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_ratings_html() {
			$ratings_html = '';

			if ( $this->block->context['tasty-roundups/disableRating'] ?? null ) {
				return $ratings_html;
			}

			if ( defined( 'TASTY_RECIPES_PLUGIN_VERSION' ) && class_exists( '\Tasty_Recipes' ) ) {
				$recipe_id = ! empty( $this->attributes['tastyRecipe']['recipeId'] ) ? $this->attributes['tastyRecipe']['recipeId'] : false;

				if ( $recipe_id ) {
					$recipe = \Tasty_Recipes\Objects\Recipe::get_by_id( $recipe_id );

					$ratings_html  = '<div class="tasty-roundups-recipe-rating">';
					$ratings_html .= $this->get_rating_icon();
					$ratings_html .= '<p>' . sprintf(
						// translators: First %s is the average rating and second %s is the total number of reviews.
						__( '%1$s/5 from %2$s ratings', 'tasty-roundups' ),
						$recipe ? $recipe->get_average_rating() : 0,
						$recipe ? $recipe->get_total_reviews() : 0
					) . '</p>';
					$ratings_html .= '</div>';
				}
			}

			return $ratings_html;
		}

		/**
		 * Render the rating icon.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_rating_icon() {
			return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" width="14" height="14"> <path fill="#FFC207" d="M7.776.454a.25.25 0 0 1 .448 0l2.069 4.192a.25.25 0 0 0 .188.137l4.626.672a.25.25 0 0 1 .139.426l-3.348 3.263a.25.25 0 0 0-.072.222l.79 4.607a.25.25 0 0 1-.362.263l-4.138-2.175a.25.25 0 0 0-.232 0l-4.138 2.175a.25.25 0 0 1-.363-.263l.79-4.607a.25.25 0 0 0-.071-.222L.754 5.881a.25.25 0 0 1 .139-.426l4.626-.672a.25.25 0 0 0 .188-.137L7.776.454Z" /></svg>';
		}

		/**
		 * Generate the HTML for the media element.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_media_html() {
			$html          = '';
			$disable_image = $this->block->context['tasty-roundups/disableImage'] ?? false;

			if ( true === $disable_image ) {
				return $html;
			}

			if ( $this->has_media() ) {
				if ( ! empty( $this->attributes['mediaId'] ) ) {
					$html = $this->get_local_image_html();
				} elseif ( 'image' === $this->attributes['mediaType'] && ! empty( $this->attributes['mediaUrl'] ) ) {
					$html = $this->get_external_image_html();
				}

				$this->item_classes[] = 'tasty-roundups-item-has-image';
			}

			return $html;
		}

		/**
		 * Check if the item has media.
		 *
		 * @since 2.0
		 *
		 * @return bool
		 */
		private function has_media() {
			return ! empty( $this->attributes['mediaId'] ) || ! empty( $this->attributes['mediaUrl'] );
		}

		/**
		 * Generate the HTML for the image when it is loaded from the media library.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_local_image_html() {
			$media_position = $this->block->context['tasty-roundups/imagePosition'] ?? $this->settings['media_position'];

			$image_align_class = $this->attributes['imageClassName'];
			$media_size        = 'medium_large';

			if ( 'tasty-roundups-item-align-top' === $image_align_class ) {
				$media_size = 'large';
			}

			/**
			 * Filters item media size.
			 *
			 * @var string $media_size Media size.
			 * @var string $media_position Media position.
			 * @var array  $attributes Block attributes.
			 */
			$media_size = apply_filters( 'tasty_roundups_item_media_size', $media_size, $media_position, $this->attributes );

			$media_url = wp_get_attachment_image_url( $this->attributes['mediaId'], $media_size );

			return '<img src="' . esc_url( $media_url ) . '" alt="' . esc_attr( $this->attributes['mediaAlt'] ) . '" class="' . $this->get_media_classes() . '" ' . $this->get_media_style_html() . ' ' . $this->get_media_attrs_html() . ' />';
		}

		/**
		 * Generate the HTML for external images.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_external_image_html() {
			return '<img src="' . esc_url( $this->attributes['mediaUrl'] ) . '" alt="' . esc_attr( $this->attributes['mediaAlt'] ) . '" class="' . $this->get_media_classes() . '" ' . $this->get_media_style_html() . ' ' . $this->get_media_attrs_html() . ' />';
		}

		/**
		 * Generate the media style.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_media_style_html() {
			$image_shape        = $this->block->context['tasty-roundups/imageShape'] ?? 'square';
			$custom_image_style = $this->block->context['tasty-roundups/customImageShape'] ?? false;

			if ( ! $custom_image_style || 'custom' !== $image_shape ) {
				return '';
			}

			if ( 'all' === $custom_image_style['type'] ) {
				return 'style="border-radius: ' . esc_attr( $custom_image_style['value'] ) . 'px;"';
			} elseif ( 'individual' === $custom_image_style['type'] ) {
				return 'style="border-top-left-radius: ' . esc_attr( $custom_image_style['value']['topLeft'] ) . 'px; border-top-right-radius: ' . esc_attr( $custom_image_style['value']['topRight'] ) . 'px; border-bottom-left-radius: ' . esc_attr( $custom_image_style['value']['bottomLeft'] ) . 'px; border-bottom-right-radius: ' . esc_attr( $custom_image_style['value']['bottomRight'] ) . 'px;"';
			}

			return '';
		}

		/**
		 * Generate the media attributes HTML.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_media_attrs_html() {
			$attrs      = array();
			$attrs_html = '';

			/**
			 * Filters the attributes used in the media HTML.
			 *
			 * @var array $attrs      Existing attributes to be used.
			 * @var array $attributes Block attributes.
			 */
			$attrs = apply_filters(
				'tasty_roundups_item_media_attrs',
				$attrs,
				$this->attributes
			);

			foreach ( $attrs as $key => $value ) {
				$attrs_html .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
			}

			return $attrs_html;
		}

		/**
		 * Generate the class names for the media element.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_media_classes() {
			$media_class = 'tasty-roundups-image';

			switch ( $this->block->context['tasty-roundups/imageShape'] ?? 'square' ) {
				case 'square':
					$media_class .= ' tasty-roundups-image-square';
					break;
				case 'rounded':
					$media_class .= ' tasty-roundups-image-rounded';
					break;
				case 'circle':
					$media_class .= ' tasty-roundups-image-circle';
					break;
				case 'cover':
					$media_class .= ' tasty-roundups-image-cover';
					break;
			}

			return $media_class;
		}

		/**
		 * Generate the HTML for the item number.
		 *
		 * @since 2.0
		 *
		 * @param bool $display_numbers Whether to display numbers.
		 * @return string
		 */
		private function get_number_html( $display_numbers ) {
			if ( $display_numbers ) {
				return '<i class="tasty-roundups-item-number" data-tasty-roundups-customization="number-text-color.color number-background-color.background-color number-border-color.border-color number-border-width.border-width"></i>';
			}

			return '';
		}

		/**
		 * Generate the HTML for link start.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_link_start_html() {
			$link_start = '';

			if ( ! empty( $this->attributes['href'] ) ) {
				$link_start = '<a';

				if ( ! empty( $this->attributes['linkTarget'] ) ) {
					$link_start .= ' target="' . esc_attr( $this->attributes['linkTarget'] ) . '"';
				}

				if ( ! empty( $this->attributes['linkRel'] ) ) {
					$link_start .= ' rel="' . esc_attr( $this->attributes['linkRel'] ) . '"';
				}

				$link_start .= ' href="' . esc_url( $this->attributes['href'] ) . '">';
			}

			return $link_start;
		}

		/**
		 * Generate the HTML for link end.
		 *
		 * @since 2.0
		 *
		 * @return string
		 */
		private function get_link_end_html() {
			if ( ! empty( $this->attributes['href'] ) ) {
				return '</a>';
			}

			return '';
		}

		/**
		 * Get the default attributes for the block.
		 *
		 * @since 2.0
		 *
		 * @return array
		 */
		private function get_default_attributes() {
			return array(
				'title'          => '',
				'description'    => '',
				'buttonText'     => $this->settings['button_text'],
				'href'           => '',
				'linkRel'        => '',
				'linkTarget'     => '',
				'mediaAlt'       => '',
				'mediaId'        => '',
				'mediaType'      => '',
				'mediaUrl'       => '',
				'imageClassName' => 'tasty-roundups-item-align-left',
				'postId'         => 0,
				'tastyRecipe'    => array(
					'enabled'       => false,
					'recipeId'      => null,
					'ratingAverage' => 0,
					'ratingCount'   => 0,
				),
				'comments'       => array(
					'open'  => false,
					'count' => 0,
				),
				'externalUrl'    => '',
			);
		}
	}
}
