<?php

namespace ElementPack\Modules\Notation\Normalizers;

use ElementPack\Modules\Notation\Atomic\Support;

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

class Settings_Normalizer {

	public function normalize( $widget ) {
		$atomic = $this->normalize_atomic_settings( $widget );

		if ( $atomic ) {
			return $atomic;
		}

		return $this->normalize_legacy_settings( $widget );
	}

	private function normalize_atomic_settings( $widget ) {
		$candidates = [];

		if ( method_exists( $widget, 'get_atomic_setting' ) ) {
			$built = [];
			$built[ Support::ACTIVE_KEY ] = $widget->get_atomic_setting( Support::ACTIVE_KEY );

			foreach ( Support::item_setting_keys() as $key ) {
				$built[ $key ] = $widget->get_atomic_setting( $key );
			}

			$candidates[] = $built;
		}

		if ( method_exists( $widget, 'get_data' ) ) {
			$raw = $widget->get_data( 'settings' );

			if ( is_array( $raw ) ) {
				$candidates[] = $raw;
			}
		}

		foreach ( $candidates as $candidate ) {
			$normalized = $this->normalize_settings_array( $candidate, true );

			if ( $normalized ) {
				return $normalized;
			}
		}

		return null;
	}

	private function normalize_legacy_settings( $widget ) {
		if ( ! method_exists( $widget, 'get_settings_for_display' ) ) {
			return null;
		}

		$settings = [
			Support::ACTIVE_KEY => $widget->get_settings_for_display( Support::ACTIVE_KEY ),
			'ep_notation_list' => $widget->get_settings_for_display( 'ep_notation_list' ),
		];

		return $this->normalize_settings_array( $settings, false );
	}

	private function normalize_settings_array( array $settings, bool $unwrap_transformable ) {
		$active = $this->extract_value( $settings[ Support::ACTIVE_KEY ] ?? null, $unwrap_transformable );

		if ( ! $this->is_truthy( $active ) ) {
			return null;
		}

		$list = null;

		if ( isset( $settings['ep_notation_list'] ) && is_array( $settings['ep_notation_list'] ) ) {
			$list = $settings['ep_notation_list'];
		}

		if ( is_array( $list ) && ! empty( $list ) ) {
			$list = array_map( [ $this, 'finalize_list_item' ], $list );
		} elseif ( $unwrap_transformable ) {
			$item = [];

			foreach ( Support::item_setting_keys() as $key ) {
				$item[ $key ] = $this->extract_value( $settings[ $key ] ?? null, $unwrap_transformable );
			}

			$list = [ $this->finalize_list_item( $item ) ];
		} else {
			return null;
		}

		if ( empty( $list ) ) {
			return null;
		}

		return [
			'active' => 'yes',
			'list' => $list,
		];
	}

	private function finalize_list_item( array $item ) {
		$item = array_merge( $this->get_item_defaults(), $item );

		$item[ Support::STROKE_WIDTH_KEY ] = $this->normalize_slider_field( $item[ Support::STROKE_WIDTH_KEY ] ?? null, 1 );
		$item[ Support::ANIM_DURATION_KEY ] = $this->normalize_slider_field( $item[ Support::ANIM_DURATION_KEY ] ?? null, 800 );
		$item[ Support::LOOP_DELAY_KEY ] = $this->normalize_slider_field( $item[ Support::LOOP_DELAY_KEY ] ?? null, 5000 );
		$item[ Support::INFINITY_LOOP_KEY ] = $this->yes_no_from_value( $item[ Support::INFINITY_LOOP_KEY ] ?? '' );

		$item[ Support::SELECT_TYPE_KEY ] = is_string( $item[ Support::SELECT_TYPE_KEY ] ) ? $item[ Support::SELECT_TYPE_KEY ] : 'widget';
		$item[ Support::TYPE_KEY ] = is_string( $item[ Support::TYPE_KEY ] ) ? $item[ Support::TYPE_KEY ] : 'underline';
		$item[ Support::COLOR_KEY ] = is_string( $item[ Support::COLOR_KEY ] ) && '' !== $item[ Support::COLOR_KEY ] ? $item[ Support::COLOR_KEY ] : '#f23427';
		$item[ Support::BRACKET_ON_KEY ] = is_string( $item[ Support::BRACKET_ON_KEY ] ) && '' !== $item[ Support::BRACKET_ON_KEY ] ? $item[ Support::BRACKET_ON_KEY ] : 'left,right';
		$item[ Support::CUSTOM_SELECTOR_KEY ] = is_string( $item[ Support::CUSTOM_SELECTOR_KEY ] ) ? $item[ Support::CUSTOM_SELECTOR_KEY ] : '';

		return $item;
	}

	private function get_item_defaults(): array {
		return [
			Support::SELECT_TYPE_KEY => 'widget',
			Support::CUSTOM_SELECTOR_KEY => '',
			Support::TYPE_KEY => 'underline',
			Support::BRACKET_ON_KEY => 'left,right',
			Support::COLOR_KEY => '#f23427',
			Support::STROKE_WIDTH_KEY => [
				'size' => 1,
				'unit' => 'px',
			],
			Support::INFINITY_LOOP_KEY => '',
			Support::ANIM_DURATION_KEY => [
				'size' => 800,
				'unit' => 'px',
			],
			Support::LOOP_DELAY_KEY => [
				'size' => 5000,
				'unit' => 'px',
			],
			Support::WAYPOINT_OFFSET_KEY => '',
		];
	}

	private function normalize_slider_field( $value, $default_size ) {
		if ( is_array( $value ) ) {
			$size = isset( $value['size'] ) ? $value['size'] : $default_size;
			$unit = isset( $value['unit'] ) && is_string( $value['unit'] ) ? $value['unit'] : 'px';

			return [
				'size' => is_numeric( $size ) ? (float) $size : (float) $default_size,
				'unit' => $unit,
			];
		}

		if ( is_numeric( $value ) ) {
			return [
				'size' => (float) $value,
				'unit' => 'px',
			];
		}

		return [
			'size' => (float) $default_size,
			'unit' => 'px',
		];
	}

	private function yes_no_from_value( $value ) {
		if ( true === $value || 1 === $value || '1' === $value || 'yes' === $value ) {
			return 'yes';
		}

		return '';
	}

	private function extract_value( $value, bool $unwrap_transformable ) {
		if ( $unwrap_transformable && is_array( $value ) && array_key_exists( 'value', $value ) ) {
			return $this->extract_value( $value['value'], $unwrap_transformable );
		}

		return $value;
	}

	private function is_truthy( $value ): bool {
		return true === $value || 'yes' === $value || 1 === $value || '1' === $value;
	}
}
