<?php

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

use Drupal\activity_creator\ActivityInterface;
use Drupal\activity_send_email\Plugin\ActivityDestination\EmailActivityDestination;
use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;

/**
 * Email frequencies.
 *
 * We disable the constant naming convention because it would be a breaking
 * change for our notification system.
 * @phpcs:disable Drupal.Semantics.ConstantName.ConstConstantStart
 */
const FREQUENCY_DAILY = 'daily';
const FREQUENCY_IMMEDIATELY = 'immediately';
const FREQUENCY_NONE = 'none';
const FREQUENCY_WEEKLY = 'weekly';

/**
 * Implements hook_cron().
 *
 * This cronjob handles creating digest queue items to process.
 */
function activity_send_email_cron() {
  // Get plugins and their intervals.
  $emailfrequencymanager = \Drupal::service('plugin.manager.emailfrequency');
  $plugins = $emailfrequencymanager->getDefinitions();

  // Fill a sortable array with the data about the email frequency.
  foreach ($plugins as $frequency) {
    $instance = $emailfrequencymanager->createInstance($frequency['id']);
    /** @var \Drupal\activity_send_email\EmailFrequencyInterface $instance */
    $interval = $instance->getInterval();

    // If the interval of the EmailFrequency plugin is more than 0, we should
    // consider it to be a digest email.
    if ($interval > 0) {
      // Get last run time.
      $last_run = \Drupal::state()
        ->get('digest.' . $frequency['id'] . '.last_run', 0);

      // If interval of frequency passed since last time, try to create queue
      // items.
      if ((time() - $last_run) > $interval) {
        // Query to get the data to process per user per frequency. And we make
        // sure to check only for items that need to be sent.
        $db = Database::getConnection();
        $query = $db->select('user_activity_digest', 'uad')
          ->fields('uad', ['uid', 'activity'])
          ->condition('uad.frequency', $frequency['id'])
          ->orderBy('uad.timestamp', 'DESC');
        $activitities = $query->execute()->fetchAll();

        if (!empty($activitities)) {
          $queue_items = [];

          // Fill the queue items.
          foreach ($activitities as $activitity) {
            $queue_items[$activitity->uid]['uid'] = $activitity->uid;
            $queue_items[$activitity->uid]['frequency'] = $frequency['id'];
            $queue_items[$activitity->uid]['activities'][] = $activitity->activity;
          }

          // Add queue items to the queue worker.
          foreach ($queue_items as $queue_item) {
            // Add the item to the queue.
            $queue = \Drupal::queue('activity_digest_worker');
            $queue->createItem($queue_item);

            // Remove activities from digest table that we just put it in the
            // queue.
            $db->delete('user_activity_digest')
              ->condition('uid', $queue_item['uid'])
              ->condition('activity', $queue_item['activities'], 'IN')
              ->execute();
          }
        }

        // Update last run.
        \Drupal::state()
          ->set('digest.' . $frequency['id'] . '.last_run', time());
      }
    }
  }
}

/**
 * Implements hook_theme().
 */
function activity_send_email_theme() {
  $items = [
    'digestmail' => [
      'template' => 'digestmail',
      'variables' => [
        'notification_count' => NULL,
        'notifications' => NULL,
        'notification_settings' => NULL,
      ],
    ],
    'directmail' => [
      'template' => 'directmail',
      'variables' => [
        'notification' => NULL,
        'notification_settings' => NULL,
      ],
    ],
  ];
  return $items;
}

/**
 * Implements hook_form_FORM_ID_alter() for user_form().
 */
function activity_send_email_form_user_form_alter(&$form, FormStateInterface $form_state) {
  /** @var \Drupal\social_user\Entity\User $account */
  $account = $form_state->getFormObject()->getEntity();

  // Only expose these settings to existing users so it's not shown on the
  // user create form.
  if ($account->isNew()) {
    return;
  }

  $form['email_notifications'] = [
    '#type' => 'fieldset',
    '#title' => new TranslatableMarkup('Email notifications'),
    '#description' => new TranslatableMarkup('For each email notification below, you can choose to turn it off, receive it immediately or in a daily or weekly digest. Email notifications will only be sent when you are not active in the platform.'),
    '#tree' => TRUE,
    '#attributes' => [
      'class' => [
        'form-horizontal',
        'form-email-notification',
      ],
    ],
  ];

  $items = _activity_send_email_default_template_items();

  $email_message_templates = EmailActivityDestination::getSendEmailMessageTemplates();

  // Give other modules the chance to add their own email notifications or
  // change the title or order of the e-mail notifications on this form.
  // Copy templates so that they can't be altered (arrays are assigned by copy).
  $context = $email_message_templates;
  \Drupal::moduleHandler()->alter('activity_send_email_notifications', $items, $context);

  // Sort a list of email frequencies by weight.
  $email_frequencies = sort_email_frequency_options();

  $notification_options = [];

  // Place the sorted data in an actual form option.
  foreach ($email_frequencies as $option) {
    $notification_options[$option['id']] = $option['name'];
  }

  $user_email_settings = EmailActivityDestination::getSendEmailUserSettings($account);

  foreach ($items as $item_id => $item) {
    // Don't render the fieldset when there are no templates.
    if (empty($item['templates'])) {
      continue;
    }

    $form['email_notifications'][$item_id] = [
      '#type' => 'fieldset',
      '#title' => [
        'text' => [
          '#markup' => $item['title'],
        ],
        'icon' => [
          '#markup' => '<svg class="icon icon-expand_more"><use xlink:href="#icon-expand_more" /></svg>',
          '#allowed_tags' => ['svg', 'use'],
        ],
      ],
      '#attributes' => [
        'class' => ['form-fieldset'],
      ],
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#open' => TRUE,
    ];

    $mail_configs = Drupal::config('social_swiftmail.settings');
    $template_frequencies = $mail_configs->get('template_frequencies') ?: [];

    foreach ($item['templates'] as $template) {
      $default_frequency = $template_frequencies[$template] ?? FREQUENCY_IMMEDIATELY;
      $form['email_notifications'][$item_id][$template] = [
        '#type' => 'select',
        '#title' => $email_message_templates[$template],
        '#options' => $notification_options,
        '#default_value' => $user_email_settings[$template] ?? $default_frequency,
      ];
    }
  }

  // Submit function to save send email settings.
  $form['actions']['submit']['#submit'][] = '_activity_send_email_form_user_form_submit';

  // Attach library.
  $form['#attached']['library'][] = 'activity_send_email/admin';
}

/**
 * Form submit for user_form.
 *
 * @param array $form
 *   Commnent on a post form.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Form state interface.
 */
function _activity_send_email_form_user_form_submit(array $form, FormStateInterface $form_state) {
  $account = \Drupal::routeMatch()->getParameter('user');
  $values = $form_state->getValue('email_notifications');

  $values = array_merge(
    $values['message_to_me'],
    $values['what_manage'],
    $values['what_follow'],
    $values['system_notifications']
  );

  if (is_object($account) && !empty($values)) {
    EmailActivityDestination::setSendEmailUserSettings($account, $values);
  }

}

/**
 * Sort the email frequencies by weight.
 *
 * @return array
 *   A sorted array of frequency options by weight.
 */
function sort_email_frequency_options() {
  $emailfrequencymanager = \Drupal::service('plugin.manager.emailfrequency');
  $plugins = $emailfrequencymanager->getDefinitions();

  $emailfrequencies = [];

  // Fill a sortable array with the data about the email frequency.
  foreach ($plugins as $frequency) {
    /** @var \Drupal\activity_send_email\EmailFrequencyInterface $instance */
    $instance = $emailfrequencymanager->createInstance($frequency['id']);
    $emailfrequencies[] = [
      'id' => $frequency['id'],
      'name' => $instance->getName(),
      'weight' => $instance->getWeight(),
    ];
  }

  // Sort the email frequencies by their weight.
  uasort($emailfrequencies, [
    'Drupal\Component\Utility\SortArray',
    'sortByWeightElement',
  ]);

  return $emailfrequencies;
}

/**
 * Implements hook_ENTITY_TYPE_insert().
 */
function activity_send_email_activity_insert(ActivityInterface $activity) {
  if (!in_array('email', $activity->getDestinations())) {
    return;
  }

  /** @var \Drupal\activity_send\Plugin\ActivitySendManager $activity_send_factory */
  $activity_send_factory = \Drupal::service('plugin.manager.activity_send.processor');

  // Trigger the create action for entities.
  if ($activity_send_factory->hasDefinition('email_activity_send')) {
    /** @var \Drupal\activity_send_email\Plugin\ActivitySend\EmailActivitySend $create_action */
    $create_action = $activity_send_factory->createInstance('email_activity_send');
    $create_action->process($activity);
  }
}

/**
 * Returns default templates grouped by specific category.
 *
 * @return array[]
 *   Grouped default templates.
 */
function _activity_send_email_default_template_items() {
  return [
    'message_to_me' => [
      'title' => t('Message to me'),
      'templates' => [
        'create_post_profile',
        'create_mention_post',
        'create_mention_comment',
        'create_comment_reply_mention',
        'create_comment_reply',
        'create_comment_post_profile',
        'create_like_node_or_post',
      ],
    ],
    'what_manage' => [
      'title' => t('What I manage'),
      'templates' => [
        'create_comment_author_node_post',
        'join_to_group',
        'request_event_enrollment',
      ],
    ],
    'what_follow' => [
      'title' => t('What I follow'),
      'templates' => [
        'create_comment_following_node',
        'create_content_in_joined_group',
      ],
    ],
    'system_notifications' => [
      'title' => t('System notifications'),
      'templates' => [],
    ],
  ];
}
