<?php

use WPML\FP\Obj;
use WPML\FP\Str;
use WPML\FP\Fns;
use function WPML\FP\pipe;

/**
 * Class WPML_Elementor_Translate_IDs
 */
class WPML_Elementor_Translate_IDs implements IWPML_Action {

	/** @var \WPML\Utils\DebugBackTrace */
	private $debug_backtrace;

	/**
	 * WPML_Elementor_Translate_IDs constructor.
	 *
	 * @param \WPML\Utils\DebugBackTrace $debug_backtrace
	 */
	public function __construct( \WPML\Utils\DebugBackTrace $debug_backtrace ) {
		$this->debug_backtrace = $debug_backtrace;
	}

	public function add_hooks() {
		add_filter( 'elementor/theme/get_location_templates/template_id', array( $this, 'translate_theme_location_template_id' ) );
		add_filter( 'elementor/theme/get_location_templates/condition_sub_id', array( $this, 'translate_location_condition_sub_id' ), 10, 2 );
		add_filter( 'elementor/documents/get/post_id', array(
			$this,
			'translate_template_id'
		) );
		add_filter( 'elementor/frontend/builder_content_data', array( $this, 'translate_global_widget_ids' ), 10, 2 );
		add_filter( 'elementor/frontend/builder_content_data', array( $this, 'translate_product_ids' ), 10, 2 );
	}

	public function translate_theme_location_template_id( $template_id ) {
		return $this->translate_id( $template_id );
	}

	/**
	 * @param int|string $sub_id
	 * @param array      $parsed_condition
	 *
	 * @return int|string
	 */
	public function translate_location_condition_sub_id( $sub_id, $parsed_condition ) {
		/**
		 * `$sub_name` gives a context for the `$sub_id`, it can be either:
		 * - `child_of`
		 * - `in_{taxonomy}`
		 * - `in_{taxonomy}_children`
		 * - `{post_type}`
		 * - `{taxonomy}`
		 */
		$sub_name = isset( $parsed_condition['sub_name'] ) ? $parsed_condition['sub_name'] : null;

		if ( (int) $sub_id > 0 && $sub_name ) {
			$startsWith = Str::startsWith( Fns::__, $sub_name );
			$getType    = Str::pregReplace( Fns::__, '', $sub_name );

			$findReplace = wpml_collect( [
				'in_'           => '/^in_|_children$/',
				'child_of_'     => '/^child_of_/',
				'any_child_of_' => '/^any_child_of_/',
			] );

			if ( 'child_of' === $sub_name ) {
				$element_type = get_post_type( $sub_id );
			} else {
				$element_type = $findReplace
					->filter( pipe( Fns::nthArg( 1 ), $startsWith ) )
					->map( $getType )
					->first( Fns::identity(), $sub_name );
			}

			$sub_id = $this->translate_id( $sub_id, $element_type );
		}

		return $sub_id;
	}

	public function translate_template_id( $template_id ) {
		if ( $this->is_WP_widget_call() || $this->is_shortcode_call() || $this->is_template_widget_call() ) {
			$template_id = $this->translate_id( $template_id );
		}

		return $template_id;
	}

	private function is_WP_widget_call() {
		return $this->debug_backtrace->is_class_function_in_call_stack(
			'ElementorPro\Modules\Library\WP_Widgets\Elementor_Library',
			'widget' );
	}

	private function is_shortcode_call() {
		return $this->debug_backtrace->is_class_function_in_call_stack(
			'ElementorPro\Modules\Library\Classes\Shortcode',
			'shortcode' );
	}

	private function is_template_widget_call() {
		return $this->debug_backtrace->is_class_function_in_call_stack(
			'ElementorPro\Modules\Library\Widgets\Template',
			'render' );
	}

	public function translate_global_widget_ids( $data_array, $post_id ) {
		foreach ( $data_array as &$data ) {
			if ( isset( $data['elType'] ) && 'widget' === $data['elType'] ) {
				if ( 'global' === $data['widgetType'] ) {
					$data['templateID'] = $this->translate_id( $data['templateID'] );
				} elseif ( 'template' === $data['widgetType'] ) {
					$data['settings']['template_id'] = $this->translate_id( $data['settings']['template_id'] );
				}
			}
			$data['elements'] = $this->translate_global_widget_ids( $data['elements'], $post_id );
		}

		return $data_array;
	}

	/**
	 * @param array $data_array
	 * @param int   $post_id
	 *
	 * @return array
	 */
	public function translate_product_ids( $data_array, $post_id ) {
		foreach ( $data_array as &$data ) {
			if ( Obj::prop( 'elType', $data ) === 'widget' && Obj::prop( 'widgetType', $data ) === 'wc-add-to-cart' ) {
				$data['settings']['product_id'] = $this->translate_id( $data['settings']['product_id'] );
			}

			$data['elements'] = $this->translate_product_ids( $data['elements'], $post_id );
		}

		return $data_array;
	}

	/**
	 * @param int|string $element_id
	 * @param string     $element_type
	 *
	 * @return int
	 */
	private function translate_id( $element_id, $element_type = null ) {
		if ( ! $element_type || $element_type === "any_child_of" ) {
			$element_type = get_post_type( $element_id );
		}

		$translated_id = apply_filters( 'wpml_object_id', $element_id, $element_type, true );

		if ( is_string( $element_id ) ) {
			$translated_id = (string) $translated_id;
		}

		return $translated_id;
	}

}
