<?php
/**
 * Animate Row module. Applies a global scroll-in animation (via the AOS
 * library) to Kadence rows, top-level columns, and sections that don't already
 * carry their own `data-aos` attribute.
 *
 * Ported from the standalone `bw-animate-row` plugin. Two notable changes:
 *
 *  1. AOS is now VENDORED (assets/vendor/aos/) and enqueued locally instead of
 *     hot-loaded from the unpkg CDN on every public page. The CDN approach was
 *     a supply-chain + visitor-privacy exposure (third-party JS running on
 *     every client site) and a single point of failure.
 *  2. The ten flat `bw_animation_*` / `bw_target_*` options collapse into the
 *     single nested `bw_dev_settings[animate_row]` section, and the inline
 *     footer init script becomes a localized handle on assets/js/animate-row.js.
 *
 * @package BW_Dev
 */

defined( 'ABSPATH' ) || exit;

class BW_Dev_Module_Animate_Row implements BW_Dev_Module_Interface {

	private const DEFAULTS = array(
		'enabled'         => 1,
		'type'            => 'fade-up',
		'duration'        => 1000,
		'easing'          => 'ease-in-out',
		'delay'           => 0,
		'offset'          => 100,
		'once'            => 1,
		'target_rows'     => 1,
		'target_columns'  => 0,
		'target_sections' => 1,
	);

	/**
	 * Allowed AOS animation types. Mirrors the AOS 2.3.4 keyword set.
	 */
	private const TYPES = array(
		'fade', 'fade-up', 'fade-down', 'fade-left', 'fade-right',
		'fade-up-right', 'fade-up-left', 'fade-down-right', 'fade-down-left',
		'flip-up', 'flip-down', 'flip-left', 'flip-right',
		'slide-up', 'slide-down', 'slide-left', 'slide-right',
		'zoom-in', 'zoom-in-up', 'zoom-in-down', 'zoom-in-left', 'zoom-in-right',
		'zoom-out', 'zoom-out-up', 'zoom-out-down', 'zoom-out-left', 'zoom-out-right',
	);

	/**
	 * Allowed AOS easing keywords.
	 */
	private const EASINGS = array(
		'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out',
		'ease-in-back', 'ease-out-back', 'ease-in-out-back',
		'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine',
		'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad',
		'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic',
	);

	public function slug(): string {
		return 'animate_row';
	}

	public function label(): string {
		return __( 'Animate Row', 'bw-dev' );
	}

	public function group(): string {
		return 'frontend';
	}

	public function default_settings(): array {
		return self::DEFAULTS;
	}

	public function sanitize( array $data ): array {
		$type   = isset( $data['type'] ) ? sanitize_text_field( wp_unslash( (string) $data['type'] ) ) : self::DEFAULTS['type'];
		$easing = isset( $data['easing'] ) ? sanitize_text_field( wp_unslash( (string) $data['easing'] ) ) : self::DEFAULTS['easing'];

		return array(
			'enabled'         => ! empty( $data['enabled'] ) ? 1 : 0,
			'type'            => in_array( $type, self::TYPES, true ) ? $type : self::DEFAULTS['type'],
			'duration'        => isset( $data['duration'] ) ? min( 5000, max( 0, absint( $data['duration'] ) ) ) : self::DEFAULTS['duration'],
			'easing'          => in_array( $easing, self::EASINGS, true ) ? $easing : self::DEFAULTS['easing'],
			'delay'           => isset( $data['delay'] ) ? min( 3000, max( 0, absint( $data['delay'] ) ) ) : self::DEFAULTS['delay'],
			'offset'          => isset( $data['offset'] ) ? min( 500, max( 0, absint( $data['offset'] ) ) ) : self::DEFAULTS['offset'],
			'once'            => ! empty( $data['once'] ) ? 1 : 0,
			'target_rows'     => ! empty( $data['target_rows'] ) ? 1 : 0,
			'target_columns'  => ! empty( $data['target_columns'] ) ? 1 : 0,
			'target_sections' => ! empty( $data['target_sections'] ) ? 1 : 0,
		);
	}

	private function get( string $key ) {
		$value = bw_dev()->settings()->get( $this->slug(), $key, self::DEFAULTS[ $key ] ?? null );
		return null === $value ? ( self::DEFAULTS[ $key ] ?? null ) : $value;
	}

	public function register(): void {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	/**
	 * Build the list of CSS selectors to animate from the target toggles.
	 */
	private function selectors(): array {
		$selectors = array();
		if ( $this->get( 'target_rows' ) ) {
			$selectors[] = '.wp-block-kadence-rowlayout';
		}
		if ( $this->get( 'target_columns' ) ) {
			// Direct child columns of a row layout only (not nested columns).
			$selectors[] = '.wp-block-kadence-rowlayout > .kt-row-layout-inner > .wp-block-kadence-column';
		}
		if ( $this->get( 'target_sections' ) ) {
			$selectors[] = '.wp-block-kadence-section';
		}
		return $selectors;
	}

	public function enqueue_assets(): void {
		// Feature temporarily disabled in 1.13.2 — see notice in render_tab().
		// 1.13.1 fixed the above-the-fold blank-hero case by skipping
		// initially-visible elements, but a follow-up live-site report
		// (promptvictoria.ca) shows that below-the-fold rows now don't
		// reveal either. Rather than ship another half-fix, the whole
		// feature is short-circuited here so no AOS CSS/JS reaches the
		// frontend on any site. The module-enabled state and saved settings
		// are preserved on every site so the feature can be re-enabled
		// once the JS is properly rewritten.
		return;

		// phpcs:disable
		if ( ! $this->get( 'enabled' ) ) {
			return;
		}
		$selectors = $this->selectors();
		if ( empty( $selectors ) ) {
			return; // Nothing targeted — don't load AOS at all.
		}

		wp_enqueue_style(
			'bw-dev-aos',
			BW_DEV_URL . 'assets/vendor/aos/aos.css',
			array(),
			'2.3.4'
		);
		wp_enqueue_script(
			'bw-dev-aos',
			BW_DEV_URL . 'assets/vendor/aos/aos.js',
			array(),
			'2.3.4',
			true
		);
		wp_enqueue_script(
			'bw-dev-animate-row',
			BW_DEV_URL . 'assets/js/animate-row.js',
			array( 'bw-dev-aos' ),
			BW_DEV_VERSION,
			true
		);
		wp_localize_script(
			'bw-dev-animate-row',
			'bwDevAnimateRowConfig',
			array(
				'selector' => implode( ', ', $selectors ),
				'type'     => (string) $this->get( 'type' ),
				'duration' => (int) $this->get( 'duration' ),
				'easing'   => (string) $this->get( 'easing' ),
				'delay'    => (int) $this->get( 'delay' ),
				'offset'   => (int) $this->get( 'offset' ),
				'once'     => (bool) $this->get( 'once' ),
			)
		);
		// phpcs:enable
	}

	public function render_tab(): void {
		$type    = (string) $this->get( 'type' );
		$easing  = (string) $this->get( 'easing' );
		$pfx     = BW_Dev_Settings::OPTION . '[' . $this->slug() . ']';
		?>
		<div class="notice notice-warning inline" style="margin:14px 0; padding:10px 14px;">
			<p style="margin:0; font-weight:600;">
				<?php esc_html_e( 'Feature temporarily disabled as of 1.13.2.', 'bw-dev' ); ?>
			</p>
			<p style="margin:6px 0 0;">
				<?php esc_html_e( 'The AOS-based scroll animations were causing above-the-fold and (after the 1.13.1 patch) below-the-fold elements to stay invisible on real Flywheel-hosted sites. Rather than ship another partial fix, the feature\'s assets are short-circuited site-wide — no AOS CSS or JS is loaded on any frontend page. Your saved settings below are preserved so re-enabling later doesn\'t lose your configuration. To control individual elements with scroll animations in the meantime, use Kadence\'s own per-block "Advanced → Block Animation" controls.', 'bw-dev' ); ?>
			</p>
		</div>

		<p class="description">
			<?php esc_html_e( 'Apply a global scroll-in animation to Kadence rows, columns, and sections. Blocks that already have their own animation (a data-aos attribute) keep it — this only fills in the ones that don\'t. Powered by the AOS library, bundled with the plugin (no external CDN).', 'bw-dev' ); ?>
		</p>

		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row"><?php esc_html_e( 'Enable animations', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[enabled]" value="1" <?php checked( $this->get( 'enabled' ), 1 ); ?> />
							<?php esc_html_e( 'Apply global scroll animations on the front end', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-animate-type"><?php esc_html_e( 'Animation type', 'bw-dev' ); ?></label></th>
					<td>
						<select id="bw-dev-animate-type" name="<?php echo esc_attr( $pfx ); ?>[type]">
							<?php foreach ( self::TYPES as $option ) : ?>
								<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $type, $option ); ?>><?php echo esc_html( $option ); ?></option>
							<?php endforeach; ?>
						</select>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-animate-duration"><?php esc_html_e( 'Duration (ms)', 'bw-dev' ); ?></label></th>
					<td>
						<input type="number" id="bw-dev-animate-duration" name="<?php echo esc_attr( $pfx ); ?>[duration]" value="<?php echo esc_attr( (string) $this->get( 'duration' ) ); ?>" min="0" max="5000" step="50" class="small-text" />
						<span class="description"><?php esc_html_e( '1000 = 1 second.', 'bw-dev' ); ?></span>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-animate-easing"><?php esc_html_e( 'Easing', 'bw-dev' ); ?></label></th>
					<td>
						<select id="bw-dev-animate-easing" name="<?php echo esc_attr( $pfx ); ?>[easing]">
							<?php foreach ( self::EASINGS as $option ) : ?>
								<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $easing, $option ); ?>><?php echo esc_html( $option ); ?></option>
							<?php endforeach; ?>
						</select>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-animate-delay"><?php esc_html_e( 'Delay (ms)', 'bw-dev' ); ?></label></th>
					<td>
						<input type="number" id="bw-dev-animate-delay" name="<?php echo esc_attr( $pfx ); ?>[delay]" value="<?php echo esc_attr( (string) $this->get( 'delay' ) ); ?>" min="0" max="3000" step="50" class="small-text" />
						<span class="description"><?php esc_html_e( 'Delay before the animation starts.', 'bw-dev' ); ?></span>
					</td>
				</tr>
				<tr>
					<th scope="row"><label for="bw-dev-animate-offset"><?php esc_html_e( 'Trigger offset (px)', 'bw-dev' ); ?></label></th>
					<td>
						<input type="number" id="bw-dev-animate-offset" name="<?php echo esc_attr( $pfx ); ?>[offset]" value="<?php echo esc_attr( (string) $this->get( 'offset' ) ); ?>" min="0" max="500" step="10" class="small-text" />
						<span class="description"><?php esc_html_e( 'Distance from the viewport bottom before an element animates in.', 'bw-dev' ); ?></span>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php esc_html_e( 'Animate once', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[once]" value="1" <?php checked( $this->get( 'once' ), 1 ); ?> />
							<?php esc_html_e( 'Only animate each element once (don\'t re-animate when scrolling back up)', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
			</tbody>
		</table>

		<h3><?php esc_html_e( 'Target elements', 'bw-dev' ); ?></h3>
		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row"><?php esc_html_e( 'Kadence Rows', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[target_rows]" value="1" <?php checked( $this->get( 'target_rows' ), 1 ); ?> />
							<?php esc_html_e( 'Apply to Kadence Row Layout blocks', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php esc_html_e( 'Kadence Columns', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[target_columns]" value="1" <?php checked( $this->get( 'target_columns' ), 1 ); ?> />
							<?php esc_html_e( 'Apply to top-level Kadence Column blocks', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
				<tr>
					<th scope="row"><?php esc_html_e( 'Kadence Sections', 'bw-dev' ); ?></th>
					<td>
						<label>
							<input type="checkbox" name="<?php echo esc_attr( $pfx ); ?>[target_sections]" value="1" <?php checked( $this->get( 'target_sections' ), 1 ); ?> />
							<?php esc_html_e( 'Apply to Kadence Section blocks', 'bw-dev' ); ?>
						</label>
					</td>
				</tr>
			</tbody>
		</table>
		<?php
	}

	public function uninstall(): void {
		// No-op. Root option drop handles persisted state.
	}
}
