<?php

/**
 * @file
 * Contains Social Add To Calendar module.
 */

use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Link;
use Drupal\Core\Template\Attribute;
use Drupal\node\NodeInterface;
use Drupal\social_event_addtocal\Plugin\SocialAddToCalendarInterface;

/**
 * Implements hook_entity_extra_field_info().
 */
function social_event_addtocal_entity_extra_field_info() {
  // Add the 'Add to Calendar' field.
  $extra['node']['event']['display']['field_event_addtocal'] = [
    'label' => t('Add to calendar'),
    'description' => t('Allow users to add the event to the calendar'),
    'weight' => 100,
    'visible' => FALSE,
  ];

  return $extra;
}

/**
 * Implements hook_theme().
 */
function social_event_addtocal_theme(): array {
  return [
    'event_enrollment_confirmation_add_to_cal' => [
      'base hook' => 'event_enrollment_confirmation',
    ],
  ];
}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function social_event_addtocal_theme_suggestions_node_alter(array &$suggestions, array $variables): void {
  if ($variables['theme_hook_original'] === 'event_enrollment_confirmation') {
    $suggestions[] = 'event_enrollment_confirmation_add_to_cal';
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function social_event_addtocal_preprocess_event_enrollment_confirmation_add_to_cal(array &$variables): void {
  $addtocal_config = \Drupal::config('social_event_addtocal.settings');
  $variables['add_to_cal'] = FALSE;
  if ($addtocal_config->get('enable_add_to_calendar')) {
    /** @var \Drupal\node\NodeInterface $node */
    $node = $variables['node'];
    $variables['add_to_cal'] = TRUE;
    // Get calendar links.
    $items = [];
    foreach (_social_event_addtocal_get_links($node) as $link) {
      $items[] = [
        '#type' => 'html_tag',
        '#tag' => 'span',
        '#value' => Link::fromTextAndUrl(
          t('@calendar calendar', ['@calendar' => $link['title']]),
          $link['url']
        )->toString(),
        '#attributes' => [
          'class' => [
            'calendar-link',
            'calendar-' . Html::getId($link['plugin_id']),
          ],
        ],
      ];
    }
    $variables['calendar_items'] = [
      '#theme' => 'item_list',
      '#list_type' => 'ul',
      '#items' => $items,
      '#attributes' => [
        'class' => [
          'addtocal-list',
        ],
      ],
    ];
  }
}

/**
 * Implements hook_ENTITY_TYPE_view().
 *
 * Uses for node entity type.
 */
function social_event_addtocal_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
  if ($node->bundle() !== 'event') {
    return;
  }

  // Get 'Add to calendar' configuration.
  $addtocal_config = Drupal::config('social_event_addtocal.settings');

  // Set render array if the 'Add to calendar' feature enabled.
  if ($addtocal_config->get('enable_add_to_calendar')) {
    // Get calendar links.
    $links = _social_event_addtocal_get_links($node);
    // Skip if no calendar was selected in settings.
    if (!empty($links)) {
      $link = reset($links);

      // Update the 'Add to calendar' field rendering.
      $calendar_link = Link::fromTextAndUrl(
        t('@calendar calendar', ['@calendar' => $link['title']]),
        $link['url']
      );
      $build['field_event_addtocal'] = [
        '#markup' => '<span class="addtocal--one-link">' . t('Add to')->__toString() . ' ' . $calendar_link->toString() . '</span>',
      ];
      // Split links if there is more than one.
      if (count($links) > 1) {
        $items = [];
        foreach ($links as $link) {
          // Update classes in calendar links.
          /** @var \Drupal\Core\Url $url */
          $url = $link['url'];
          $options = $url->getOptions();
          $options['attributes']['class'][] = 'calendar-link';
          $options['attributes']['class'][] = 'calendar-' . Html::getId($link['plugin_id']);
          $url->setOptions($options);

          $link_title = [
            [
              '#type' => 'html_tag',
              '#tag' => 'img',
              '#attributes' => [
                'src' => $link['icon'],
                'class' => ['no-b-lazy'],
              ],
            ],
            [
              '#type' => 'html_tag',
              '#tag' => 'span',
              '#value' => t('@cal calendar', ['@cal' => $link['title']]),
            ],
          ];

          $items[] = [
            'value' => Link::fromTextAndUrl($link_title, $url)
              ->toRenderable(),
          ];
        }
        $build['field_event_addtocal'] = [
          '#type' => 'container',
          '#attributes' => [
            'class' => [
              'add-to-calendar',
              'btn-group',
              'dropdown',
              'btn-group--primary',
            ],
            'no-split' => [
              'title' => t('Add to calendar'),
              'alignment' => 'right',
            ],
          ],
          'dropdown_button' => [
            '#type' => 'button',
            '#value' => t('Add to calendar'),
            '#split' => TRUE,
            '#attributes' => [
              'class' => ['btn--add-to-calendar'],
            ],
          ],
          'dropdown_links' => [
            '#theme' => 'item_list__dropdown',
            '#items' => $items,
            '#context' => [
              'alignment' => 'left',
            ],
            '#attributes' => [
              'class' => [
                'addtocal-list',
              ],
            ],
          ],
        ];
      }
    }

    // Make sure we clear the cache if the settings is submitted.
    $build['#cache']['tags'][] = 'config:social_event_addtocal.settings';

    // Add styles for the 'Add to calendar' links.
    $build['#attached']['library'][] = 'social_event_addtocal/event_addtocal';
  }
}

/**
 * Implements hook_preprocess_HOOK() for "input--button--split.html.twig".
 */
function social_event_addtocal_preprocess_input__button__split(array &$variables): void {
  if (empty($variables['element']['#attributes']['class'])
    || !in_array('btn--add-to-calendar', $variables['element']['#attributes']['class'])
  ) {
    return;
  }

  if ($variables['split_button_attributes'] instanceof Attribute) {
    $variables['split_button_attributes']->removeClass('btn-default');
    $variables['split_button_attributes']->addClass('btn-link');
  }
}

/**
 * Adds links for the 'Add to Calendar' button.
 *
 * @param \Drupal\node\NodeInterface $node
 *   The node entity.
 *
 * @return array[]
 *   Array of links for render.
 */
function _social_event_addtocal_get_links(NodeInterface $node) {
  // Links for Add to calendar button.
  $links = [];

  // Get 'Add to calendar' configuration.
  $addtocal_config = Drupal::config('social_event_addtocal.settings');

  // Get plugin instance and set links array.
  /** @var \Drupal\social_event_addtocal\Plugin\SocialAddToCalendarManager $social_add_to_calendar */
  $social_add_to_calendar = Drupal::service('plugin.manager.social_add_to_calendar');

  // Get allowed calendars.
  $allowed_calendars = $addtocal_config->get('allowed_calendars');

  if (is_array($allowed_calendars)) {
    // Set links for dropdown.
    foreach ($allowed_calendars as $allowed_calendar) {
      // Check if calendar plugin enabled in config.
      if ($social_add_to_calendar->hasDefinition($allowed_calendar)) {
        /** @var \Drupal\social_event_addtocal\Plugin\SocialAddToCalendarInterface $calendar */
        $calendar = $social_add_to_calendar->createInstance($allowed_calendar);

        // Exit if calendar plugin nor exist.
        if (!$calendar instanceof SocialAddToCalendarInterface) {
          continue;
        }

        // Set link for plugin instance.
        $links[] = [
          'title' => $calendar->getName(),
          'icon' => $calendar->getIcon(),
          'url' => $calendar->generateUrl($node),
          'plugin_id' => $calendar->getPluginId(),
        ];
      }
    }
  }

  return $links;
}

/**
 * Implements theme_preprocess_HOOK() for email.
 */
function social_event_addtocal_preprocess_email(array &$variables): void {
  // Add library with styles for event.
  $variables['#attached']['library'][] = 'social_event_addtocal/event_addtocal';

  if (\Drupal::service('theme.manager')->getActiveTheme()->getName() === 'socialblue') {
    $variables['#attached']['library'][] = 'socialblue/dropdown';
  }
}
