<?php
/**
 * Value handler for WPML element_id field.
 *
 * @package Ealab\Deployer
 */

namespace EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\ItemValueHandler\Compatibility\sitepress_multilingual_cms;

use EaLab\WP_Deployer\vendor\Ealab\Deployer\Exception\WpDeployException;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\FieldConfig;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\ItemValueHandler\ItemValueHandlerBase;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\ItemValueHandler\ReferenceItemValueHandler;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\ItemValueHandler\ReferenceItemValueHandlerInterface;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\TrackableItem;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Utility\Plugin;

/**
 * Value handler for WPML element_id field.
 */
class WpmlElementIdItemValueHandler extends ReferenceItemValueHandler implements ReferenceItemValueHandlerInterface {
	/**
	 * {@inheritDoc}
	 */
	public static function getFormBuild(): ?array {
		// No need for a form; the element type is determined
		// automatically using the "element_type" column.
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	public static function getHandlerBaseId(): string {
		return 'wpml_element_id';
	}

	/**
	 * {@inheritDoc}
	 */
	public static function getLabel(): string {
		return _dpgettext( 'deployer-core', 'processor label', 'WPML element_id' );
	}

	/**
	 * {@inheritDoc}
	 */
	public static function getReferencedItemTrackerIdFromRawValues( array $context = array() ): ?string {
		$element_type = $context['getContentRow']()['element_type'];

		return static::getTrackerIdByElementType( $element_type );
	}

	/**
	 * {@inheritDoc}
	 */
	public function getUnprocessedValue( int $operation, ?callable $progress_callback = null ) {
		if ( ! Plugin::isPluginActive( 'sitepress-multilingual-cms/sitepress.php' ) ) {
			// The plugin is not enabled, do not process anything.
			return $this->value;
		}

		return parent::getUnprocessedValue( $operation, $progress_callback );
	}

	/**
	 * Gets the tracker ID by WPML element type.
	 *
	 * @param string $element_type The element type given by WPML.
	 *
	 * @return string|null The tracker ID, or null if not found.
	 */
	private static function getTrackerIdByElementType( string $element_type ): ?string {
		// TODO: make this mapping hookable?
		$mapping = array(
			'comment'  => 'comments',
			'package_' => 'icl_string_packages',
			'post_'    => 'posts',
			'tax_'     => 'terms',
		);

		foreach ( $mapping as $prefix => $tracker_id ) {
			if ( $prefix === substr( $element_type, 0, strlen( $prefix ) ) ) {
				return $tracker_id;
			}
		}

		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	public function init( TrackableItem $holder_item, string $full_field_name, $value, int $origin, FieldConfig $field_config ): void {
		// Use the base init implementation, not the reference one.
		ItemValueHandlerBase::init($holder_item, $full_field_name, $value, $origin, $field_config );

		if ( ! isset( $value ) ) {
			// Reference values are always set.
			// But actually, there is a bug in the core code of WPML which creates rows with element_id as NULL,
			// which should never happen due to the NOT NULL flag.
			// Let's put the value to 0 to not break the script.
			$this->reference_value = 0;
			$this->value           = 0;

			return;
		}

		switch ( $origin ) {
			case ItemValueHandlerBase::ORIGIN__DATABASE:
				// The value is a local ID.
				$this->value = $value;
				break;

			case ItemValueHandlerBase::ORIGIN__IMPORT_FILE:
				// The value is in the form: "<tracker_id>.<uuid>".
				$this->reference_value = $value;
				break;

			default:
				throw new WpDeployException( 'Invalid value origin: ' . $origin . '.' );
		}

		// Unlike the reference item value handler, the target type is located in another field
		// of the content: element_type.
		$holder_values = $holder_item->getRawDataFields();

		if ( empty( $holder_values['element_type'] ) ) {
			// Nothing special can be done here.
			$this->target_type = null;
		} else {
			$this->target_type = static::getTrackerIdByElementType( $holder_values['element_type'] );
		}
	}
}
