<?php

declare(strict_types=1);

namespace Drupal\node_view_mode\Matcher;

use Drupal\Core\Entity\EntityInterface;
use Drupal\node\NodeInterface;
use Drupal\node_view_mode\Enum\ViewModes;
use Drupal\node_view_mode\StorageManagerInterface;

/**
 * Matches the given display mode with the target one.
 */
class DisplayModeMatcher implements DisplayModeMatcherInterface {

  /**
   * {@inheritdoc}
   */
  public function matchViewForModeAndEntity(string $mode, EntityInterface $entity): ?string {
    if (FALSE === $this->isSupportedEntity($entity)) {
      return NULL;
    }

    /** @var \Drupal\node\NodeInterface $node */
    $node = $entity;
    if (
      FALSE === $this->isAllowedMode($mode, $node)
      || FALSE === $this->hasViewModeField($node)
    ) {
      return NULL;
    }

    return $node->get(StorageManagerInterface::FIELD_NAME)->value ?: $mode;
  }

  /**
   * Checks if the matched entity is the node type.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The matched entity.
   *
   * @return bool
   *   True if is node, false otherwise.
   */
  private function isSupportedEntity(EntityInterface $entity): bool {
    return $entity instanceof NodeInterface;
  }

  /**
   * Checks if the node has view mode field.
   *
   * @param \Drupal\node\NodeInterface $node
   *   The paragraph.
   *
   * @return bool
   *   TRUE in case field is exist in paragraph object, FALSE otherwise.
   */
  private function hasViewModeField(NodeInterface $node): bool {
    return $node->hasField(StorageManagerInterface::FIELD_NAME);
  }

  /**
   * Checks if the display mode is allowed.
   *
   * @param string $mode
   *   The mode to be checked.
   * @param \Drupal\node\NodeInterface $node
   *   The paragraph.
   *
   * @return bool
   *   True if the mode is allowed, false otherwise.
   */
  private function isAllowedMode(string $mode, NodeInterface $node): bool {
    return ViewModes::tryFrom($mode) !== ViewModes::Preview;
  }

}
