<?php

/**
 * @file
 * The Social activity module.
 */

use Drupal\Core\Link;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\menu_link_content\MenuLinkContentInterface;
use Drupal\node\NodeInterface;
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_plugins_display_alter().
 */
function social_activity_views_plugins_display_alter(array &$plugins) {
  $plugins['block']['class'] = 'Drupal\social_activity\Plugin\views\display\ModeBlock';
}

/**
 * Implements hook_social_user_account_header_items().
 *
 * Adds the Notification Center to the account header block.
 */
function social_activity_social_user_account_header_items(array $context) {
  // We require a valid user to load the notifications for.
  if (empty($context['user'])) {
    return [];
  }

  // Get the total amount of notifications for the user.
  $num_notifications = social_activity_social_account_notifications_counter($context['user']);

  return [
    'notifications' => [
      '#type' => 'account_header_element',
      '#wrapper_attributes' => [
        'class' => ['desktop', 'notification-bell'],
      ],
      '#title' => new TranslatableMarkup('Notification Center'),
      '#icon' => $num_notifications > 0 ? 'notifications' : 'notifications_none',
      '#label' => new TranslatableMarkup('Notifications'),
      '#url' => Url::fromRoute('view.activity_stream_notifications.page_1'),
      '#notification_count' => $num_notifications,
      '#weight' => 800,
      'header' => [
        '#wrapper_attributes' => ['class' => 'dropdown-header'],
        '#markup' => new TranslatableMarkup('Notification Center'),
      ],
      'header-divider' => [
        '#wrapper_attributes' => ['class' => 'divider'],
        '#markup' => '',
      ],
      // Element to contain the link for ajaxified view for notifications.
      'load_link' => [
        '#title' => '',
        '#type' => 'link',
        '#url' => Url::fromRoute('activity_creator.stream.notifications'),
        '#attributes' => ['class' => 'use-ajax'],
      ],
      'notifications' => [
        '#wrapper_attributes' => ['class' => 'js-notification-center-wrapper'],
        // @todo Change ajax throbber to opensocial spinner.
        // @see: https://www.drupal.org/project/social/issues/3074740
        '#markup' => '<div className="spinner">
      <div className="bounce1"></div>
      <div className="bounce2"></div>
      <div className="bounce3"></div>
    </div>',
        '#attached' => [
          'library' => [
            'core/drupal.ajax',
            'activity_creator/activity_creator.notifications',
          ],
        ],
        '#cache' => [
          'max-age' => 0,
        ],
      ],
      'footer-divider' => [
        '#wrapper_attributes' => ['class' => 'divider'],
        '#markup' => '',
      ],
      'footer' => [
        '#wrapper_attributes' => ['class' => 'dropdown-header'],
        '#type' => 'link',
        '#title' => [
          '#type' => 'inline_template',
          '#template' => "{% trans %}All notifications{% endtrans %} <svg class='btn-icon icon-black pull-right'><use xlink:href='#icon-navigate_next'></use></svg>",
          '#allowed_tags' => ['use', 'svg'],
        ],
        '#url' => Url::fromRoute('view.activity_stream_notifications.page_1'),
        '#attributes' => [
          'title' => new TranslatableMarkup('View all notifications'),
          'class' => ['block', 'clearfix'],
        ],
        // The link is wrapped in a container to avoid .dropdown-menu > li > a
        // styling.
        '#prefix' => '<div>',
        '#suffix' => '</div>',
      ],
    ],
  ];
}

/**
 * Implements hook_social_user_account_header_account_links().
 *
 * Adds the mobile indicator for activity notifications under the profile icon
 * menu.
 */
function social_activity_social_user_account_header_account_links(array $context) {
  // We require a logged in user for this indicator.
  if (empty($context['user']) || !$context['user']->isAuthenticated()) {
    return [];
  }

  // Get the total amount of notifications for the user.
  $num_notifications = social_activity_social_account_notifications_counter($context['user']);
  // Depending on the amount of notifications, set a class for the indicator.
  $label_classes = 'hidden';
  if ($num_notifications > 0) {
    $label_classes = 'badge badge-accent badge--pill';
    // When there are more than 99 notifications, display this and not
    // the exact amount.
    if ($num_notifications > 99) {
      $num_notifications = '99+';
    }
  }

  $title_link = [
    '#type' => 'inline_template',
    '#template' => '<span>{% trans %}Notification Center{% endtrans %}</span><span{{ attributes }}>{{ icon }}</span>',
    '#context' => [
      'attributes' => new Attribute(['class' => $label_classes]),
      'icon' => (string) $num_notifications,
    ],
  ];

  $link = Link::createFromRoute($title_link, 'view.activity_stream_notifications.page_1');

  return [
    'notification_mobile' => [
      '#wrapper_attributes' => [
        'class' => ['mobile notification-bell'],
      ],
      '#weight' => 300,
      '#type' => 'link',
      '#attributes' => [
        'title' => new TranslatableMarkup('Notification Center'),
      ],
      '#access' => $link->getUrl()->access(),
    ] + $link->toRenderable(),
  ];
}

/**
 * Implements hook_social_user_account_header_items().
 *
 * Adds an indicator to the user account menu on mobile.
 */
function social_activity_social_user_account_header_items_alter(array &$menu_links, array $context) {
  // We require a logged in user for this indicator.
  if (empty($context['user']) || !$context['user']->isAuthenticated()) {
    return;
  }

  // If the account_box link was removed we have nothing to do.
  if (!isset($menu_links['account_box'])) {
    return;
  }

  // Get the total amount of notifications for the user.
  $num_notifications = social_activity_social_account_notifications_counter($context['user']);
  if ($num_notifications > 0) {
    $menu_links['account_box']['#wrapper_attributes']['class'][] = 'has-alert';
  }
}

/**
 * Implements hook_theme().
 */
function social_activity_theme($existing, $type, $theme, $path) {
  return [
    'message_post_teaser' => [
      'variables' => [
        'link' => '',
        'name' => '',
        'date' => '',
        'summary' => '',
      ],
    ],
    'message_node_teaser' => [
      'variables' => [
        'link' => '',
        'type' => '',
      ],
    ],
    'message_post_comment_preview' => [
      'variables' => [
        'summary' => '',
      ],
    ],
    'message_content_preview' => [
      'variables' => [
        'link' => '',
        'author_name' => '',
        'date' => '',
        'title' => '',
        'type' => '',
      ],
    ],
    'message_cta_button' => [
      'variables' => [
        'link' => '',
        'text' => '',
      ],
    ],
    'message_user_profile_preview' => [
      'variables' => [
        'profile_name' => '',
        'profile_home' => '',
        'profile_image' => '',
        'profile_class' => '',
        'profile_function' => '',
        'profile_organization' => '',
      ],
    ],
    'message_group_preview' => [
      'variables' => [
        'group_title' => '',
        'group_type' => '',
        'group_members' => '',
      ],
    ],
  ];
}

/**
 * Wrapper method to get the number of unread notifications.
 *
 * @param \Drupal\Core\Session\AccountInterface $account
 *   Account object to get notifications for.
 * @param array $status
 *   Filter by status.
 *
 * @return int
 *   The amount of notifications.
 *
 * @see \Drupal\activity_creator\ActivityNotifications
 */
function social_activity_social_account_notifications_counter(AccountInterface $account, array $status = [ACTIVITY_STATUS_RECEIVED]) : int {
  $account_notifications = \Drupal::service('activity_creator.activity_notifications');

  return count($account_notifications->getNotifications($account, $status)) ?? 0;
}

/**
 * Implements hook_views_post_build().
 */
function social_activity_views_post_build(ViewExecutable $view) {
  $override_displays = [
    'block_stream_explore',
    'block_stream_homepage',
    'block_stream_homepage_without_post',
  ];

  if ($view->id() == "activity_stream" && in_array($view->current_display, $override_displays)) {
    if (isset($view->filter_type) && $view->filter_type === 'dashboard') {
      // Override default view mode for activity stream views block if it was
      // added via layout builder.
      $view->rowPlugin->options['view_mode'] = 'featured';

      // Attach and use featured styles for activity stream on dashboard.
      $view->element['#attached']['library'][] = 'social_featured_content/paragraph.featured';
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function social_activity_preprocess_block(&$variables) {
  $route_match = \Drupal::routeMatch();
  $allowed_routes = [
    'entity.node.canonical',
    'layout_builder.overrides.node.view',
  ];
  $allowed_bundles = [
    'dashboard',
    'landing_page',
  ];
  $allowed_content_names = [
    'activity_stream',
    'community_activities',
    'activity_stream_profile',
    'activity_stream_group',
  ];

  if (($node = $route_match->getParameter('node')) && $node instanceof NodeInterface) {
    // Use lazy builder for stream blocks only if:
    // 1. It on the node or landing builder page.
    // 2. Node is a Dashboard or a Landing page
    // 3. This block is from views.
    // 4. View one of the stream views.
    if (
      in_array($route_match->getRouteName(), $allowed_routes) &&
      in_array($node->bundle(), $allowed_bundles) &&
      $variables['base_plugin_id'] === 'views_block' &&
      isset($variables['content']['#name']) &&
      in_array($variables['content']['#name'], $allowed_content_names)
    ) {
      if ($node->bundle() === 'dashboard') {
        $variables['attributes']['class'][] = 'block-dashboard-activity-stream card';
      }
      /** @var \Drupal\views\ViewExecutable $view */
      $view = $variables['content']['#view'];
      $variables['content'] = [
        '#create_placeholder' => TRUE,
        '#lazy_builder' => [
          'social_activity.lazy_builder:viewsLazyBuild',
          [
            $variables['content']['#name'],
            $variables['content']['#display_id'],
            $node->bundle(),
            $view->getItemsPerPage(),
          ],
        ],
      ];

      // Set vocabulary ID from views filter.
      if (isset($view->filter_vocabulary)) {
        $variables['content']['#lazy_builder'][1] = array_merge(
          $variables['content']['#lazy_builder'][1],
          [$view->filter_vocabulary]
        );
      }

      // Set taxonomy IDs from views filter.
      if (isset($view->filter_tags) && is_array($view->filter_tags)) {
        $variables['content']['#lazy_builder'][1] = array_merge(
          $variables['content']['#lazy_builder'][1],
          array_keys($view->filter_tags)
        );
      }
    }
  }
}

/**
 * Implements hook_social_core_default_main_menu_links_alter().
 */
function social_activity_social_core_default_main_menu_links_alter(array &$links) {
  $link = \Drupal::entityTypeManager()->getStorage('menu_link_content')
    ->loadByProperties([
      'title' => 'Community',
      'menu_name' => 'main',
      'link' => 'internal:/explore',
    ]);
  $link = end($link);

  // Ensure that the end() doesn't return FALSE, and we have link instance.
  if ($link instanceof MenuLinkContentInterface) {
    $links[] = $link;
  }
}
