<?php
/**
 * Screen label formatter using a field of the trackable/deployment item to format.
 *
 * @package Ealab\Deployer
 */

namespace Ealab\Deployer\Tracking\ScreenLabelFormatter;

use Ealab\Deployer\Tracking\TrackableItem;
use Symfony\Component\Yaml\Yaml;

/**
 * Screen label formatter using a field of the deployment item to format.
 */
class FieldScreenLabelFormatter extends ScreenLabelFormatterBase {
	/**
	 * {@inheritDoc}
	 */
	public function formatFromFileItem( string $bundle_subdirectory, array $file_item, ?array $config = null ): string {
		// Use the tracker's default configuration if none is provided.
		$config = $config ?? ( function ( array $file_item ): ?array {
			// Determine the tracker of the item.
			$tracker = $this->tracking_manager->getItemTrackerByTrackerId( $file_item['tracker'] ?? null ) ?? null;

			if ( empty( $tracker ) ) {
				// The tracker is not (yet) available.
				return null;
			}

			return $tracker->getScreenLabelFormatterConfig();
		} )( $file_item ) ?? array();

		$prefix_field_name = $config['prefix_field_name'] ?? '';

		if ( ! empty( $prefix_field_name ) ) {
			$prefix = $file_item['fields'][ $file_item['tracker'] . '.' . $prefix_field_name ] ?? '';
		}

		$field_name = $config['field_name'] ?? '';

		if ( empty( $field_name ) ) {
			// The configuration is invalid.
			// At least attempt to show a basic label.
			return $this->prefixValue( parent::formatFromFileItem( $bundle_subdirectory, $file_item, $config ), $prefix ?? '' );
		}

		$field_value = $file_item['fields'][ $file_item['tracker'] . '.' . $field_name ] ?? '';

		if ( empty( $field_value ) ) {
			// The field is empty.
			// At least attempt to show a basic label.
			return $this->prefixValue( parent::formatFromFileItem( $bundle_subdirectory, $file_item, $config ), $prefix ?? '' );
		}

		return $this->prefixValue( $field_value, $prefix ?? '' );
	}

	/**
	 * {@inheritDoc}
	 */
	public function formatFromTrackableItem( TrackableItem $item, ?array $config = null ): string {
		// Use the tracker's default configuration if none is provided.
		$config = $config ?? $item->getRegistry()->getItemTracker()->getScreenLabelFormatterConfig() ?? array();

		$prefix_field_name = $config['prefix_field_name'] ?? '';

		if ( ! empty( $prefix_field_name ) ) {
			$prefix = $item->getRawDataFields()[ $prefix_field_name ] ?? '';
		}

		$field_name = $config['field_name'] ?? '';

		if ( empty( $field_name ) ) {
			// The given config is invalid.
			return $this->prefixValue( parent::formatFromTrackableItem( $item, $config ), $prefix ?? '' );
		}

		$field_value = $item->getRawDataFields()[ $field_name ] ?? '';

		if ( empty( $field_value ) ) {
			// The field is empty.
			return $this->prefixValue( parent::formatFromTrackableItem( $item, $config ), $prefix ?? '' );
		}

		return $this->prefixValue( $field_value, $prefix ?? '' );
	}

	/**
	 * {@inheritDoc}
	 */
	public static function getFormBuild(): ?array {
		$build = Yaml::parse(
			<<<YAML
			field_name:
			  label:
			    load: field_label
			    content: Field name
			  select:
			    type: SelectField
			    dataLocation: ~.screen_label_formatter.config.field_name
			    dynamicOptions: ~._meta.column_names
			
			prefix_field_name:
			  label:
			    load: field_label
			    content: Field name for the prefix (optional)
			  select:
			    type: SelectField
			    dataLocation: ~.screen_label_formatter.config.prefix_field_name
			    dynamicOptions: ~._meta.column_names
			YAML
		);

		// Translations.
		$build['field_name']['label']['content']        = _dpgettext( 'deployer-core', 'screen label formatter', 'Field name' );
		$build['prefix_field_name']['label']['content'] = _dpgettext( 'deployer-core', 'screen label formatter', 'Field name for the prefix (optional)' );

		return $build;
	}

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

	/**
	 * {@inheritDoc}
	 */
	public static function getLabel(): string {
		return _dpgettext( 'deployer-core', 'screen label formatter', 'Field' );
	}

	/**
	 * Prefixes the given value with the given prefix content.
	 *
	 * @param string $value The value to prefix.
	 * @param string $prefix_content The prefix content. Will be formatted.
	 *
	 * @return string The prefixed value.
	 */
	private function prefixValue( string $value, string $prefix_content ): string {
		return '' === $prefix_content ? $value : '[' . $prefix_content . '] ' . $value;
	}
}
