<?php

/**
 * @file
 * The Social event AN enroll module.
 */

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\social_event\Entity\Node\Event;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\cache\CachePluginBase;
use Drupal\node\Entity\Node;
use Drupal\file\Entity\File;

/**
 * Create and send a invitation email on the given user account.
 */
function social_event_an_enroll_send_mail($params) {
  if (!empty($params['field_event']) && !empty($params['field_email'])) {
    $node = Node::load($params['field_event']);
    $params['node'] = $node;
    $params['token'] = $params['field_token'];

    $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $site_mail = \Drupal::config('system.site')->get('mail');

    $mail = \Drupal::service('plugin.manager.mail')
      ->mail('social_event_an_enroll', 'social_event_an_enroll', $params['field_email'], $langcode, $params, $site_mail);

    return empty($mail) ? NULL : $mail['result'];
  }
}

/**
 * Implements hook_theme().
 */
function social_event_an_enroll_theme() {
  return [
    'event_an_enroll_dialog' => [
      'variables' => [
        'links' => NULL,
      ],
    ],
    'event_an_enroll_guest' => [
      'variables' => [
        'name' => NULL,
        'url' => NULL,
      ],
    ],
  ];
}

/**
 * Implements hook_preprocess_HOOK().
 */
function social_event_an_enroll_preprocess_views_view_field(&$variables) {
  /** @var \Drupal\views\ViewExecutable $view */
  $view = &$variables['view'];

  if ($view->id() === 'event_manage_enrollments' && $variables['field']->field === 'profile_entity_sortable') {
    $entity = &$variables['row']->_entity;

    /** @var \Drupal\social_event_an_enroll\EventAnEnrollManager $service */
    $service = \Drupal::service('social_event_an_enroll.manager');

    if ($service->isGuest($entity)) {
      $url = Url::fromUserInput('/' . \Drupal::service('extension.list.module')->getPath('social_event_an_enroll') . '/images/icon.svg');

      $variables['output'] = [
        '#theme' => 'event_an_enroll_guest',
        '#name' => $service->getGuestName($entity),
        '#url' => $url,
      ];
    }
  }
}

/**
 * Override variables for the social page hero data.
 */
function social_event_an_enroll_preprocess_node(array &$variables) {
  $account = \Drupal::currentUser();
  if ($account->isAnonymous() && !empty($variables['event_enrollment'])) {

    $node = $variables['node'];

    if ($variables['view_mode'] === 'hero' && social_event_an_enroll_is_enabled($node)) {
      $form = \Drupal::formBuilder()->getForm('Drupal\social_event_an_enroll\Form\EventAnEnrollActionForm', $node);

      $variables['event_enrollment'] = [
        'enroll_action_form' => $form,
      ];

      $an_enroll_routes = [
        'social_event_an_enroll.enroll_dialog',
        'social_event_an_enroll.enroll_form',
      ];

      if (in_array(\Drupal::routeMatch()->getRouteName(), $an_enroll_routes)) {
        unset($variables['event_enrollment']);
      }

      // Add caching context to anonymous users.
      // This is custom context. We added it in order to vary page cache
      // of routes given in $an_enroll_routes.
      $variables['#cache']['contexts'][] = 'event_an_enroll_route';
    }
  }
}

/**
 * Implements hook_views_post_render().
 *
 * Alter "Event enrollments" views. Add number of anonymous enrollments.
 */
function social_event_an_enroll_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) {
  if ($view->id() == 'event_enrollments' && $view->current_display == 'event_enrollments') {
    if (isset($output['#rows']) && !empty($view->args[0])) {
      $nid = $view->args[0];
      $an_count = \Drupal::service('social_event_an_enroll.service')->enrollmentCount($nid);
      if ($an_count && $an_count > 0) {
        // Fix counter in block title.
        $view->total_rows += $an_count;
        // Add default avatar image with counter.
        if (empty($output['#rows'])) {
          $output['#rows'][0]['#theme'] = $output['#theme'];
          $output['#rows'][0]['#view'] = $output['#view'];
          $output['#rows'][0]['#grouping_level'] = 0;
          $output['#rows'][0]['#title'] = '';
        }
        // Get default profile image uri.
        $default_image = social_profile_get_default_image();
        if (!empty($default_image['id'])) {
          $file = File::load($default_image['id']);
          $uri = $file->getFileUri();
          $output['#rows'][0]['#rows'][] = [
            '#prefix' => '<div class="avatar">',
            '#theme' => 'image_style',
            '#style_name' => 'social_medium',
            '#uri' => $uri,
            '#suffix' => '<span class="badge badge--pill">' . $an_count . '</span></div>',
          ];
        }
        $output['#attached']['library'][] = 'social_event_an_enroll/event_an_enroll';
      }
    }
  }
}

/**
 * Implements hook_menu_local_tasks_alter().
 *
 * Check and display "Anonymous Enrollments" tab only for events.
 */
function social_event_an_enroll_menu_local_tasks_alter(&$data, $route_name) {
  $can_show_an_enrollments_link = FALSE;
  $routes_to_check = [
    'view.event_enrollments.view_enrollments',
    'entity.node.canonical',
    'view.managers.view_managers',
    'view.manage_enrollments.page',
    'view.event_manage_enrollments.page_manage_enrollments',
  ];
  if (in_array($route_name, $routes_to_check)) {
    $node = \Drupal::service('current_route_match')->getParameter('node');
    if (!is_null($node) && (!$node instanceof Node)) {
      $node = Node::load($node);
    }
    if (($node instanceof Node) && $node->getType() === 'event' && $node->get('field_content_visibility')->getString() === 'public'
    ) {
      $can_show_an_enrollments_link = TRUE;
    }
  }
  // Place this here, since hiding it should happen
  // always and not only on the mentioned routes.
  if (!$can_show_an_enrollments_link) {
    unset($data['tabs'][0]['views_view:view.manage_enrollments.page']);
  }
}

/**
 * Check if anonymous enrollment is allowed for given event.
 */
function social_event_an_enroll_is_enabled(Node $node) {
  $config = \Drupal::config('social_event_an_enroll.settings');
  $is_global_enabled = $config->get('event_an_enroll');
  $is_event = $node instanceof Event;
  $is_public = $node->get('field_content_visibility')->getString() === 'public';
  $is_event_an_enroll = !empty($node->get('field_event_an_enroll')->value);
  $is_event_enroll = $is_event && $node->isEnrollmentEnabled();
  return $is_global_enabled && $is_event && $is_public && $is_event_an_enroll && $is_event_enroll;
}

/**
 * Implements hook_form_alter().
 *
 * Check and display "Allow anonymous enrollments" checkbox for public events.
 */
function social_event_an_enroll_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $event_forms = [
    'node_event_form',
    'node_event_edit_form',
  ];

  if (in_array($form_id, $event_forms)) {
    $config = \Drupal::config('social_event_an_enroll.settings');
    // Show the checkbox only when AN enroll is enabled.
    $form['field_event_an_enroll']['#states'] = [
      'visible' => [
        ':input[name="field_content_visibility"]' => ['value' => 'public'],
        ':input[name="field_event_enroll[value]"]' => ['checked' => TRUE],
        ':input[name="field_enroll_method"]' => ['value' => '1'],
      ],
    ];
    // Set default value on event creation form.
    if ($form_id === 'node_event_form') {
      $form['field_event_an_enroll']['widget']['value']['#default_value'] = $config->get('event_an_enroll_default_value');
    }
    // Set ability to change default value.
    $form['field_event_an_enroll']['widget']['value']['#disabled'] = $config->get('event_an_enroll_default_value') && !$config->get('event_an_enroll_allow_edit');
    // Hide checkbox if feature is disabled globally.
    $form['field_event_an_enroll']['#access'] = $config->get('event_an_enroll');
  }
}

/**
 * Implements hook_ENTITY_TYPE_update().
 *
 * Display warning if visibility was changed for already enabled AN enroll.
 */
function social_event_an_enroll_node_update(Node $node) {
  if ($node->getType() === 'event') {
    $is_event_an_enroll = !empty($node->get('field_event_an_enroll')->value);
    $new_visibility = $node->get('field_content_visibility')->getString();
    $old_visibility = $node->original->get('field_content_visibility')->getString();

    if ($is_event_an_enroll && $old_visibility === 'public' && $new_visibility !== 'public') {
      \Drupal::messenger()->addWarning(t('Enrollment without account can only be enabled when the visibility of the event is Public.'));
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_presave().
 *
 * Set the correct value for AN enroll when enroll method is set to request.
 */
function social_event_an_enroll_node_presave(EntityInterface $entity) {
  // If the enroll method is request then anonymous must be off.
  if ($entity->getType() === 'event' && $entity->get('field_enroll_method')->value === '2') {
    $entity->set('field_event_an_enroll', '0');
  }
}

/**
 * Implements hook_social_event_action_ACTION_ID_finish().
 */
function social_event_an_enroll_social_event_managers_action_social_event_an_enroll_send_email_action_finish($success) {
  return social_event_managers_social_event_managers_action_social_event_managers_send_email_action_finish($success);
}
