<?php

namespace PrimeSlider\Includes;

defined('ABSPATH') || die();

use WPML_PB_String;
use IWPML_Page_Builders_Module;
use WPML_Elementor_Translatable_Nodes;

/**
 * Class WPML_Module_With_Items
 */
abstract class WPML_Module_With_Items implements IWPML_Page_Builders_Module {

	/**
	 * @param string $field
	 *
	 * @return string
	 */
	abstract protected function get_title( $field );

	/** @return array */
	abstract protected function get_fields();

	/**
	 * @param string $field
	 *
	 * @return string mixed
	 */
	abstract protected function get_editor_type( $field );

	/**
	 * @return string
	 */
	abstract public function get_items_field();

	/**
	 * @param string|int $node_id
	 * @param array $element
	 * @param WPML_PB_String[] $strings
	 *
	 * @return WPML_PB_String[]
	 */
	public function get( $node_id, $element, $strings ) {
		foreach ( $this->get_items( $element ) as $item ) {
			foreach ( $this->get_fields() as $key => $field ) {
				if ( ! is_array( $field ) ) {

					if ( ! isset( $item[ $field ] ) ) {
						continue;
					}

					$strings[] = new WPML_PB_String(
						$item[ $field ],
						$this->get_string_name( $node_id, $item[ $field ], $field, $element['widgetType'], $item['_id'] ),
						$this->get_title( $field ),
						$this->get_editor_type( $field )
					);
				} else {
					foreach ( $field as $inner_field ) {

						if ( ! isset( $item[ $key ][ $inner_field ] ) ) {
							continue;
						}

						$strings[] = new WPML_PB_String(
							$item[ $key ][ $inner_field ],
							$this->get_string_name( $node_id, $item[ $key ][ $inner_field ], $key . '_' . $inner_field, $element['widgetType'], $item['_id'] ),
							$this->get_title( $key ),
							$this->get_editor_type( $key )
						);
					}
				}
			}
		}
		return $strings;
	}

	/**
	 * @param int|string $node_id
	 * @param mixed $element
	 * @param WPML_PB_String $string
	 *
	 * @return mixed
	 */
	public function update( $node_id, $element, WPML_PB_String $string ) {
		// Defensive handling: ensure settings and items exist
		$settings_key = WPML_Elementor_Translatable_Nodes::SETTINGS_FIELD;
		$items_field = $this->get_items_field();
		if (
			! isset( $element[ $settings_key ] )
			|| ! isset( $element[ $settings_key ][ $items_field ] )
			|| ! is_array( $element[ $settings_key ][ $items_field ] )
		) {
			return null;
		}

		// Iterate by reference so we can write back into the element when matched
		foreach ( $element[ $settings_key ][ $items_field ] as $key => &$item ) {
			foreach ( $this->get_fields() as $field_key => $field ) {

				if ( ! is_array( $field ) ) {

					if ( ! isset( $item[ $field ] ) ) {
						continue;
					}

					if (
						$this->get_string_name(
							$node_id,
							$item[ $field ],
							$field,
							isset( $element['widgetType'] ) ? $element['widgetType'] : '',
							isset( $item['_id'] ) ? $item['_id'] : ''
						) === $string->get_name()
					) {
						$item[ $field ] = $string->get_value();

						// Attach index so WPML core can re-insert the item into the element.
						$item['index'] = $key;

						// Return both index and item so WPML core can list() them safely.
						return array( $key, $item );
					}

				} else {

					foreach ( $field as $inner_field ) {

						if (
							! isset( $item[ $field_key ] )
							|| ! isset( $item[ $field_key ][ $inner_field ] )
						) {
							continue;
						}

						if (
							$this->get_string_name(
								$node_id,
								$item[ $field_key ][ $inner_field ],
								$field_key . '_' . $inner_field,
								isset( $element['widgetType'] ) ? $element['widgetType'] : '',
								isset( $item['_id'] ) ? $item['_id'] : ''
							) === $string->get_name()
						) {
							$item[ $field_key ][ $inner_field ] = $string->get_value();

							// Attach index so WPML core can re-insert the item into the element.
							$item['index'] = $key;

							// Return both index and item so WPML core can list() them safely.
							return array( $key, $item );
						}
					}
				}
			}
		}
		// Always return an array with two elements so callers using list($key, $item)
		// won't trigger "Undefined array key" warnings when the result is empty.
		return array(null, null);
	}

	/**
	 * @param string $node_id
	 * @param string $value
	 * @param string $type
	 * @param string $key
	 * @param string $item_id
	 *
	 * @return string
	 */
	private function get_string_name($node_id, $value, $type, $key = '', $item_id = '') {
		return $key . '-' . $type . '-' . $node_id . '-' . $item_id;
	}

	/**
	 * @param $element
	 *
	 * @return mixed
	 */
	public function get_items($element) {
		return $element[WPML_Elementor_Translatable_Nodes::SETTINGS_FIELD][$this->get_items_field()];
	}
}
