<?php

declare(strict_types=1);

namespace Drupal\nodehive_visualeditor\Form;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Ajax\AjaxFormHelperTrait;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\node\NodeForm;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * The NodeEditForm class.
 */
class NodeEditForm extends NodeForm {

  use AjaxFormHelperTrait;

  /**
   * Constructs a NodeForm object.
   *
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
   *   The factory for the temp store object.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
   *   Drupal entity field manager.
   */
  public function __construct(
    EntityRepositoryInterface $entity_repository,
    PrivateTempStoreFactory $temp_store_factory,
    ?EntityTypeBundleInfoInterface $entity_type_bundle_info,
    ?TimeInterface $time,
    AccountInterface $current_user,
    DateFormatterInterface $date_formatter,
    protected EntityFieldManagerInterface $entityFieldManager,
  ) {
    parent::__construct(
      $entity_repository,
      $temp_store_factory,
      $entity_type_bundle_info,
      $time,
      $current_user,
      $date_formatter,
    );
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity.repository'),
      $container->get('tempstore.private'),
      $container->get('entity_type.bundle.info'),
      $container->get('datetime.time'),
      $container->get('current_user'),
      $container->get('date.formatter'),
      $container->get('entity_field.manager'),
    );
  }

  /**
   * {@inheritdoc}
   *
   * Overridden to store the root parent entity.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    $node = $form_state->getFormObject()->getEntity();

    $form['operations_wrapper'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => [
          'node-operations',
        ],
      ],
      '#weight' => -999,
    ];

    $form['operations_wrapper']['operations'] = [
      '#type' => 'operations',
      '#links' => [
        [
          'title' => $this->t('Edit'),
          'weight' => 10,
          'url' => Url::fromRoute(
            'entity.node.edit_form',
            [
              'node' => $node->id(),
            ],
          ),
        ],
        [
          'title' => $this->t('Clone'),
          'weight' => 10,
          'url' => Url::fromRoute(
            'quick_node_clone.node.quick_clone',
            [
              'node' => $node->id(),
            ],
          ),
        ],
        [
          'title' => $this->t('View'),
          'weight' => 10,
          'url' => Url::fromRoute(
            'entity.node.canonical',
            [
              'node' => $node->id(),
            ],
          ),
        ],
      ],
    ];

    $form['#attached']['library'][] = "nodehive_visualeditor/node_edit_form";

    // Hide Preview button.
    $form['actions']['preview']['#access'] = FALSE;
    // Hide Delete button.
    $form['actions']['delete']['#access'] = FALSE;
    // Hide advanced tab.
    $form['advanced']['#attributes']['class'][] = 'visually-hidden';
    // Add ajax callback to submit button.
    $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit';
    // @todo static::ajaxSubmit() requires data-drupal-selector to be the same
    //   between the various Ajax requests. A bug in
    //   \Drupal\Core\Form\FormBuilder prevents that from happening unless
    //   $form['#id'] is also the same. Normally, #id is set to a unique HTML
    //   ID via Html::getUniqueId(), but here we bypass that in order to work
    //   around the data-drupal-selector bug. This is okay so long as we
    //   assume that this form only ever occurs once on a page. Remove this
    //   workaround in https://www.drupal.org/node/2897377.
    $form['#id'] = Html::getId($form_state->getBuildInfo()['form_id']);

    $node = $form_state->getFormObject()->getEntity();
    $fields = $this->entityFieldManager->getFieldDefinitions("node", $node->bundle());
    $bundles = array_keys($this->entityTypeBundleInfo->getBundleInfo('paragraph'));

    foreach ($fields as $fieldName => $field) {
      if ($field->getType() === 'entity_reference_revisions') {
        $form[$fieldName]['widget']['header_actions']['#access'] = FALSE;
        foreach ($bundles as $bundle) {
          $form[$fieldName]['widget']['add_more']['operations']['#links']['add_more_button_' . $bundle]['title']['#ajax'] = NULL;
          $form[$fieldName]['widget']['add_more']['operations']['#links']['add_more_button_' . $bundle]['title']['#attributes']['data-composable-uuid'] = $node->uuid();
          $form[$fieldName]['widget']['add_more']['operations']['#links']['add_more_button_' . $bundle]['title']['#attributes']['data-composable-action'] = 'add';
          $form[$fieldName]['widget']['add_more']['operations']['#links']['add_more_button_' . $bundle]['title']['#attributes']['data-composable-storage'] = 'paragraph';
          $form[$fieldName]['widget']['add_more']['operations']['#links']['add_more_button_' . $bundle]['title']['#attributes']['data-composable-bundle'] = $bundle;
          $form[$fieldName]['widget']['add_more']['operations']['#links']['add_more_button_' . $bundle]['title']['#attributes']['data-composable-field'] = $fieldName;
        }
      }
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
    // Invoke Form lifecycle events.
    $this->submitForm($form, $form_state);
    $this->save($form, $form_state);
    $this->buildForm($form, $form_state);
    // Invoke Ajax Commands to reload iframe and dialog.
    $response = new AjaxResponse();
    $arguments = ['node', $this->entity->id(), $this->entity->language()->getId()];
    $response->addCommand(new InvokeCommand(NULL, 'iframePreviewReload', $arguments));

    return $response;
  }

}
