<?php

namespace Brandy\BlockStyles\SeparatorWave;

use Brandy\Traits\SingletonTrait;

class Caller {
	use SingletonTrait;

	protected function __construct() {
		add_action( 'init', array( $this, 'register_wave_style' ) );
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_editor_script' ) );
		add_action( 'enqueue_block_assets', array( $this, 'enqueue_styles' ) );
		add_filter( 'render_block_core/separator', array( $this, 'apply_wave_inline_style' ), 10, 2 );
	}

	public function register_wave_style() {
		register_block_style(
			'core/separator',
			array(
				'name'  => 'wave',
				'label' => __( 'Wave', 'brandy' ),
			)
		);
	}

	public function enqueue_editor_script() {
		wp_enqueue_script(
			'brandy/separator-wave',
			BRANDY_TEMPLATE_URL . '/inc/BlockStyles/SeparatorWave/script.js',
			array( 'wp-blocks', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-hooks', 'wp-i18n', 'wp-element' ),
			BRANDY_SCRIPT_VERSION,
			true
		);
	}

	public function enqueue_styles() {
		wp_enqueue_style(
			'brandy/separator-wave',
			BRANDY_TEMPLATE_URL . '/inc/BlockStyles/SeparatorWave/style.css',
			array(),
			BRANDY_SCRIPT_VERSION
		);
	}

	/**
	 * Generate a looped SVG wave path with $count full cycles.
	 * Each cycle = one peak + one trough via cubic bezier segments.
	 * midY / troughY are proportional to the element height so the shape
	 * scales naturally with amplitude.
	 */
	private function build_wave_styles( $color, $amp, $count ) {
		$h        = $amp * 2 + 4;
		$mid_y    = round( $h * 0.40, 1 );
		$trough_y = round( $h * 0.80, 1 );
		$seg_w    = 1440 / ( $count * 2 );  // width of each half-cycle

		$path = "M0,{$mid_y}";
		for ( $i = 0; $i < $count * 2; $i++ ) {
			$cp1_x    = round( $i * $seg_w + $seg_w * 0.33, 1 );
			$cp2_x    = round( $i * $seg_w + $seg_w * 0.67, 1 );
			$end_x    = round( ( $i + 1 ) * $seg_w, 1 );
			$target_y = ( 0 === $i % 2 ) ? 0 : $trough_y;
			$path    .= " C{$cp1_x},{$target_y} {$cp2_x},{$target_y} {$end_x},{$mid_y}";
		}
		$path .= " L1440,{$h} L0,{$h} Z";

		$svg  = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 ' . $h . '" preserveAspectRatio="none">'
			. '<path d="' . $path . '" fill="black"/>'
			. '</svg>';
		$mask = 'url(data:image/svg+xml,' . rawurlencode( $svg ) . ')';

		return array(
			'border:none',
			'border-top:none',
			'height:' . $h . 'px',
			'background-color:' . esc_attr( $color ),
			'-webkit-mask-image:' . $mask,
			'mask-image:' . $mask,
			'-webkit-mask-size:100% 100%',
			'mask-size:100% 100%',
			'-webkit-mask-repeat:no-repeat',
			'mask-repeat:no-repeat',
			'width:100%',
			'max-width:100%',
			'margin-left:0',
			'margin-right:0',
		);
	}

	public function apply_wave_inline_style( $html, $block ) {
		$class_name = $block['attrs']['className'] ?? '';
		if ( ! str_contains( $class_name, 'is-style-wave' ) ) {
			return $html;
		}

		$color  = ! empty( $block['attrs']['waveColor'] ) ? $block['attrs']['waveColor'] : '#000000';
		$ripple = isset( $block['attrs']['waveRipple'] ) ? absint( $block['attrs']['waveRipple'] ) : 50;
		$ripple = max( 20, min( 120, $ripple ) );
		$count  = isset( $block['attrs']['waveCount'] ) ? absint( $block['attrs']['waveCount'] ) : 4;
		$count  = max( 1, min( 10, $count ) );

		$tag = new \WP_HTML_Tag_Processor( $html );
		if ( ! $tag->next_tag() ) {
			return $html;
		}

		// Fully replace inline style with wave styles to prevent stray borders leaking through
		$tag->set_attribute( 'style', implode( ';', $this->build_wave_styles( $color, $ripple, $count ) ) . ';' );
		return $tag->get_updated_html();
	}
}

Caller::get_instance();
