<?php

declare(strict_types=1);

namespace Drupal\acquia_dam\Plugin\media\acquia_dam;

use Drupal\acquia_dam\Entity\ManagedImageField;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\media\MediaInterface;

/**
 * Image Media Source Type.
 *
 * @AssetMediaSource(
 *   id = "image",
 *   label = @Translation("Acquia DAM: Image"),
 *   default_thumbnail_filename = "generic.png",
 *   asset_search_key = "ft",
 *   asset_search_value = "image",
 *   field_list_item_class = "\Drupal\acquia_dam\Plugin\Field\ImageFieldItemList",
 *   field_type_class = "\Drupal\acquia_dam\Plugin\Field\FieldType\ImageFieldType",
 * )
 */
final class Image extends MediaSourceTypeBase implements MediaSourceTypeInterface {

  /**
   * {@inheritdoc}
   */
  protected string $localFileAssetField = ManagedImageField::MANAGED_IMAGE_FIELD_NAME;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->assetFieldFormatterConfiguration[$this->localFileAssetField] = [
      'type' => 'image',
      'label' => 'hidden',
      'settings' => [
        'image_link' => '',
        'image_style' => '',
        'image_loading' => ['attribute' => 'lazy'],
      ],
      'third_party_settings' => [],
      'region' => 'content',
      'weight' => 0,
    ];
  }

  /**
   * Helper function to get content region.
   *
   * @param array $content_region
   *   The content region.
   * @param string $existing_field_name
   *   Existing field to disable in the display.
   * @param string $active_field_name
   *   Name of the (newly) active field.
   * @param array $active_field
   *   Settings for the (newly) active field.
   *
   * @return array
   *   Return the active field data.
   */
  protected function setSettings(array $content_region, string $existing_field_name, string $active_field_name, array $active_field): array {
    // Get the existing field settings.
    $settings = $content_region[$existing_field_name]['settings'];

    // Get the formatter settings for the existing field.
    $responsive_formatter = $content_region[$existing_field_name]['type'];
    // If the responsive formatter is one of the responsive image types,
    // set the type for the active field accordingly.
    if (in_array($responsive_formatter, ['responsive_image', 'acquia_dam_responsive_image'], TRUE)) {
      // Set the settings for the active field.
      $active_field['settings'] = $settings;
      // Set the formatter type based on the existing responsive formatter to
      // maintain responsive image behavior when switching between Embed and
      // Local file methods.
      // Formatter mapping:
      // - Embed method uses 'acquia_dam_responsive_image'
      // - Local file method uses 'responsive_image'
      // When switching methods, we swap the formatter types to preserve
      // functionality.
      $active_field['type'] = ($responsive_formatter === 'responsive_image')
        ? 'acquia_dam_responsive_image'
        : 'responsive_image';

      return $active_field;
    }

    // Style keys.
    $styles = [
      $this->localFileAssetField => 'image_style',
      $this->embedCodeAssetField => 'embed_style',
    ];
    // Mapping of styles
    // Key is the source style,
    // value is the target style for the specified field.
    $mapping = [
      $this->embedCodeAssetField => [
        ''  => 'original',
      ],
      $this->localFileAssetField => [
        'remotely_referenced_thumbnail_image' => '',
        'original' => '',
      ],
    ];

    // Get the style value of existing field.
    $style_value = $settings[$styles[$existing_field_name]] ?? '';

    // Ensure the image style is a valid embed format.
    if ($active_field_name === $this->embedCodeAssetField && !empty($style_value)) {
      /** @var \Drupal\acquia_dam\ImageStyleHelper $image_style_helper */
      $image_style_helper = \Drupal::service('acquia_dam.image_style_support');
      $image_style_helper->addAllowedImageStyle($style_value);
    }

    // Apply mapping.
    $active_field['settings'][$styles[$active_field_name]] = $mapping[$active_field_name][$style_value] ?? $style_value;

    return $active_field;
  }

  /**
   * {@inheritdoc}
   */
  public function processTokens(array $tokens, MediaInterface $media): array {
    // Call the parent class's processTokens method.
    $replacements = parent::processTokens($tokens, $media);

    // Extend or modify the behavior specific to the Image class.
    $source = $media->getSource();
    foreach ($tokens as $name => $original) {
      if ($name === 'asset-path') {
        // Handle download and sync configuration. For local asset URL.
        if ($source->getConfiguration()['download_assets']) {
          /** @var \Drupal\file\FileInterface|null $file */
          $file = $source->getMetadata($media, 'file');
          $replacements[$original] = $file ? $file->getFileUri() : "";
          break;
        }
      }
    }

    return $replacements;
  }

  /**
   * {@inheritdoc}
   *
   * @see \Drupal\acquia_dam\Plugin\Field\FieldType\AssetItem::generateSampleValue()
   */
  public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
    if ($field_definition->getName() == 'acquia_dam_asset_id') {
      // Provide default asset value for image media source.
      // @see tests/fixtures/56ff14de-02cd-41b5-9a73-c917eab19abf.json
      return [
        'asset_id' => '56ff14de-02cd-41b5-9a73-c917eab19abf',
        'version_id' => '4f656c07-6a08-47b3-9403-16082d2fcda5',
        'external_id' => 'kcnabdscl5',
      ];
    }
    return parent::generateSampleValue($field_definition);
  }

}
