<?php

/**
 * @file
 * Contains activity_basics.module.
 */

use Drupal\activity_creator\Plugin\ActivityActionInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\SynchronizableInterface;
use Drupal\group\Entity\GroupContent;
use Drupal\group\Entity\GroupContentInterface;
use Drupal\node\NodeInterface;

/**
 * Implements hook_entity_insert().
 */
function activity_basics_entity_insert(EntityInterface $entity): void {
  // Don't trigger activity creation for group content entity with
  // related UNPUBLISHED entity.
  if ($entity instanceof GroupContentInterface) {
    $related_entity = $entity->getEntity();

    if ($related_entity instanceof EntityPublishedInterface && !$related_entity->isPublished()) {
      // Don't do anything.
      return;
    }
  }

  _activity_basics_entity_action($entity, 'create_entitiy_action');

  // Check if the entity created with "published" status.
  if ($entity instanceof EntityPublishedInterface && $entity->isPublished()) {
    _activity_basics_entity_action($entity, 'publish_entity_action');
  }
}

/**
 * Implements hook_entity_update().
 */
function activity_basics_entity_update(EntityInterface $entity): void {
  _activity_basics_entity_action($entity, 'update_entity_action');
}

/**
 * Implements hook_entity_presave().
 */
function activity_basics_entity_presave(EntityInterface $entity): void {
  // Check if the entity become published.
  if (
    $entity instanceof EntityPublishedInterface &&
    !$entity->isNew()
  ) {
    // Check if entity change state from "unpublished" to "published".
    // @phpstan-ignore-next-line
    $original = $entity->original;

    if (!$original->isPublished() && $entity->isPublished()) {
      _activity_basics_entity_action($entity, 'publish_entity_action');

      // Check if entity is instance of content.
      assert($entity instanceof ContentEntityInterface);

      // Load all of the group content for this entity.
      // Check if related entity become published then trig activity creation.
      $group_contents = (array) \Drupal::entityTypeManager()
        ->getStorage('group_content')
        ->loadByEntity($entity);

      foreach ($group_contents as $group_content) {
        _activity_basics_entity_action($group_content, 'create_entitiy_action');
      }
    }
  }
}

/**
 * Implements hook_social_group_move().
 */
function activity_basics_social_group_move(NodeInterface $node): void {
  $node->setCreatedTime($node->getChangedTime());

  // If the node is placed within a new group, we add the move_entity_action
  // activity.
  $group_contents = GroupContent::loadByEntity($node);
  if (!empty($group_contents)) {
    _activity_basics_entity_action($node, 'move_entity_action');
  }
  // If the node is placed from a group in to the community, we add the
  // create_node-bundle_community activity.
  if (empty($group_contents)) {
    _activity_basics_entity_action($node, 'create_entitiy_action');
  }
}

/**
 * Create or modify some entity.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity.
 * @param string $instance
 *   The instance.
 */
function _activity_basics_entity_action(EntityInterface $entity, $instance): void {
  // During migration activities should not be created as this may flood stream.
  if ($entity instanceof SynchronizableInterface && $entity->isSyncing()) {
    return;
  }

  $plugin_manager = \Drupal::service('plugin.manager.activity_action.processor');
  if ($plugin_manager->hasDefinition($instance)) {
    $plugin = $plugin_manager->createInstance($instance);
    assert($plugin instanceof ActivityActionInterface);
    $plugin->create($entity);
  }
}
