<?php

namespace Barn2\Plugin\WC_Product_Options\Util;

use Barn2\Plugin\WC_Product_Options\Model\Option as Option_Model;
use Barn2\Plugin\WC_Product_Options\Util\Price as Price_Util;

use WC_Product;

/**
 * Display utilities.
 *
 * @package   Barn2\woocommerce-product-options
 * @author    Barn2 Plugins <support@barn2.com>
 * @license   GPL-3.0
 * @copyright Barn2 Media Ltd
 */
final class Display {

	/**
	 * Retrieves the HTML for the supplied groups.
	 *
	 * @param array $groups
	 * @param WC_Product $product
	 */
	public static function get_groups_html( $groups, $product ) {
		$displayed_attributes = [];

		ob_start();

		do_action( 'wc_product_options_before_option_container', $groups, $product );

		$product_attributes = self::get_product_attributes( $product );

		printf(
			'<div class="wpo-options-container" data-product-attributes="%s">',
			// a list of terms for each product attribute assigned to this product
			esc_attr( empty( $product_attributes ) ? '{}' : json_encode( $product_attributes ) )
		);

		foreach ( $groups as $group ) {
			$options = Option_Model::where( 'group_id', $group->id )->orderBy( 'menu_order', 'asc' )->get();

			if ( $options->isEmpty() ) {
				continue;
			}

			if ( $group->display_name ) {
				$context    = 'group_name';
				$group_name = apply_filters( 'wc_product_options_get_output_string', $group->name, $group, $context );
				printf( '<h2 class="wpo-group-title">%s</h2>', esc_html( $group_name ) );
			}

			foreach ( $options as $option ) {
				$class = Util::get_field_class( $option->type );

				if ( ! class_exists( $class ) ) {
					continue;
				}

				$field = new $class( $option, $product );

				// Skip if we already output this attribute option.
				if ( $selected_attribute = $field->is_valid_attribute_option_for_product() ) {
					if ( in_array( $selected_attribute, $displayed_attributes, true ) ) {
						continue;
					}

					$displayed_attributes[] = $selected_attribute;
					$displayed_attributes   = array_unique( $displayed_attributes );
				}

				$field->render();
			}
		}

		print( '<input type="hidden" name="wpo-hidden-fields" value="1" />' );

		print( '</div>' );

		do_action( 'wc_product_options_after_option_container', $groups, $product );

		return ob_get_clean();
	}

	/**
	 * Retrives the totals HTML for the supplied product
	 *
	 * @param WC_Product $product
	 * @return string
	 */
	public static function get_totals_container_html( $product ) {
		/**
		 * Filters the product price to display in the totals container.
		 *
		 * @param float $price The product price.
		 * @param WC_Product $product The product object.
		 * @return string
		 */
		$price = apply_filters( 'wc_product_options_product_price_container', wc_get_price_to_display( $product ), $product );

		$price_string = str_replace( '%1$s', '<span class="wpo-currency">%1$s</span>', get_woocommerce_price_format() );
		$price_string = "<span class=\"wpo-price\">$price_string</span>";

		$formatted_price = sprintf(
			$price_string,
			get_woocommerce_currency_symbol(),
			Price_Util::get_formatted_price( $price )
		);

		$exclude_price = Option_Model::get_product_price_exclusion_status( $product );
		$product_meta  = array_filter(
			$product->get_meta_data(),
			function ( $meta ) {
				return strpos( $meta->key, '_' ) !== 0;
			}
		);

		/**
		 * Filters the total label text.
		 *
		 * @param string $total_label The total label.
		 * @param WC_Product $product The product object.
		 */
		$total_label = apply_filters( 'wc_product_options_total_label', __( 'Total:', 'woocommerce-product-options' ), $product );

		$html = sprintf(
			'<div class="wpo-totals-container"
				data-product-price="%1$s"
				data-exclude-product-price="%4$s"
				data-weight="%5$s"
				data-width="%6$s"
				data-length="%7$s"
				data-height="%8$s"
				data-meta="%9$s"
			>
				<span class="wpo-totals-label">%3$s<span>
				%2$s
			</div>',
			esc_attr( $price ),
			wp_kses( $formatted_price, [ 'span' => [ 'class' => [] ] ] ),
			esc_html( $total_label ),
			$exclude_price ? 'true' : 'false',
			esc_attr( $product->get_weight() ),
			esc_attr( $product->get_width() ),
			esc_attr( $product->get_length() ),
			esc_attr( $product->get_height() ),
			esc_attr( json_encode( array_values( $product_meta ) ) )
		);

		return $html;
	}

	/**
	 * Get the output string for the field.
	 *
	 * This method runs a filter to allow for further string customization,
	 * including internationalization.
	 *
	 * @param string $string_value
	 * @param array $args
	 * @return string
	 */
	public static function get_output_string( $string_value, $args ) {
		return apply_filters( 'wc_product_options_get_frontend_string', $string_value, $args );
	}

	public static function get_product_attributes( $product ) {
		if ( is_a( $product, 'WC_Product_Variable' ) ) {
			return [];
		}

		// get all the terms for each product attribute assigned to this product
		// this is used in the conditional logic
		$terms = [];

		foreach ( $product->get_attributes() as $attribute ) {
			$attribute_terms = get_the_terms( $product->get_id(), $attribute->get_name() );

			if ( empty( $attribute_terms ) || is_wp_error( $attribute_terms ) ) {
				continue;
			}

			$terms[ $attribute->get_name() ] = array_map(
				function ( $term ) {
					return $term->slug;
				},
				$attribute_terms
			);
		}

		return $terms;
	}
}
