<?php

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

use Drupal\Core\Session\AccountInterface;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\Core\Access\AccessResult;
use Drupal\group\Entity\GroupInterface;
use Drupal\group\Entity\Group;
use Drupal\user\UserInterface;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function social_post_form_post_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  if (
    $form_state->getFormObject()->getEntity()->isNew() &&
    ($content = \Drupal::service('social_post.helper')->buildCurrentUserImage())
  ) {
    $form['current_user_image'] = $content;
  }

  // Reset title display.
  $form['field_post']['widget'][0]['#title_display'] = "";

  // Set submit button caption to Post instead of Save.
  $form['actions']['submit']['#value'] = t('Post', [], ['context' => 'Post button']);

  if (!empty($form['field_post']) && !empty($form['field_post']['widget'][0])) {
    // For posting on the stream on the group stream.
    if (!empty(_social_group_get_current_group())) {
      $form['field_post']['widget'][0]['#placeholder'] = t('Say something to the group');
      $form['field_post']['widget'][0]['#title'] = t('Say something to the group');
    }
    // For the post on a users profile.
    elseif (!empty(\Drupal::routeMatch()->getParameter('user')) && \Drupal::routeMatch()->getParameter('user')->id() != \Drupal::currentUser()->id()) {
      $user_profile = \Drupal::routeMatch()->getParameter('user');
      $name = $user_profile->getDisplayName();
      $form['field_post']['widget'][0]['#placeholder'] = t('Leave a message to @name', ['@name' => $name]);
      $form['field_post']['widget'][0]['#title'] = t('Leave a message to @name', ['@name' => $name]);
    }
    else {
      $title = t('Say something to the Community');
      $form['field_post']['widget'][0]['#title'] = $title;
      $form['field_post']['widget'][0]['#placeholder'] = $title;
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Alter the comment_post_comment_form form.
 */
function social_post_form_comment_post_comment_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Reset title display.
  $form['field_comment_body']['widget'][0]['#title_display'] = 'invisible';

  // When ajax_comment is enabled, we need to
  // redirect the form after save to the normal ajax comment
  // included endpoint so the correct save and JS is triggered.
  if (!\Drupal::moduleHandler()->moduleExists('ajax_comments')) {
    // Set the action of the form to the current uri.
    // This needs to be done, because we cannot override $form['#action']
    // without breaking functionality.
    $uri = Url::fromRoute('<current>')->toString();
    // Store in a hidden field.
    $form['redirect_after_save'] = [
      '#type' => 'hidden',
      '#title' => t('Redir'),
      '#default_value' => $uri,
    ];

    // Submit function to retrieve the action uri and redirect to it.
    $form['actions']['submit']['#submit'][] = '_social_post_comment_post_comment_form_submit';
  }
}

/**
 * Form submit for comment_post_comment_form.
 *
 * @param array $form
 *   Commnent on a post form.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Form state interface.
 */
function _social_post_comment_post_comment_form_submit(array $form, FormStateInterface $form_state) {
  // Fetch from the form.
  $uri = $form_state->getValue('redirect_after_save');
  // Let's not trust this.
  $uri = Html::escape($uri);

  // Must be a valid URL.
  if (UrlHelper::isValid($uri)) {
    // Get the Url from the Form value and redirect to this url.
    $url = Url::fromUserInput($uri);
    // Set redirect.
    $form_state->setRedirectUrl($url);
  }
}

/**
 * Function that returns the Icon or Title data for post visibility details.
 *
 * @param string $visibility
 *   The current field_visibility value for the post.
 * @param string $return_value
 *   (optional) Icon or Title depending on what we should return.
 *
 * @return \Drupal\Core\StringTranslation\TranslatableMarkup|string
 *   Post visibility detail.
 */
function social_post_get_visibility_details($visibility, $return_value = 'icon') {

  $return = &drupal_static(__FUNCTION__ . $visibility);

  if (isset($return)) {
    $icon = $return['icon'];
    $title = $return['label'];
  }
  else {
    // Set the materialize icon.
    switch ($visibility) {
      case '1':
        $icon = 'public';
        $title = t('Public');
        break;

      case '3':
        $icon = 'lock';
        $title = t('Group members');
        break;

      default:
        $icon = 'community';
        $title = t('Community');
    }
  }

  \Drupal::moduleHandler()->alter('social_post_visibility_info_alter', $visibility, $icon, $title);

  if (!isset($return)) {
    $return = [
      'icon' => $icon,
      'label' => $title,
    ];
  }

  return $return[$return_value];
}

/**
 * Implements hook_views_data_alter().
 */
function social_post_views_data_alter(array &$data) {
  $data['post']['post_visibility_access_filter'] = [
    'title' => t('Post visibility access'),
    'filter' => [
      'title' => t('Post visibility access'),
      'help' => t('Enable post access for public and community posts.'),
      'field' => 'field_visibility',
      'id' => 'post_visibility_access',
    ],
  ];
  $data['post']['post_account_stream_filter'] = [
    'title' => t('Post account stream'),
    'filter' => [
      'title' => t('Post account stream'),
      'help' => t('Enable post for the account stream.'),
      'field' => 'field_visibility',
      'id' => 'post_account_stream',
    ],
  ];
  $data['post']['post_group_stream_filter'] = [
    'title' => t('Post group stream'),
    'filter' => [
      'title' => t('Post group stream'),
      'help' => t('Enable post for the group stream.'),
      'field' => 'field_visibility',
      'id' => 'post_group_stream',
    ],
  ];
}

/**
 * Implements hook_theme().
 */
function social_post_theme() {
  $items = [
    'post' => [
      'render element' => 'elements',
      'file' => 'post.page.inc',
      'template' => 'post',
    ],
    'post__featured' => [
      'template' => 'post--featured',
      'base hook' => 'post',
    ],
  ];
  return $items;
}

/**
 * Implements hook_preprocess_activity().
 */
function social_post_preprocess_activity(&$variables) {
  // Add visibility icon and label to activity posts.
  if (!empty($variables['elements']['field_activity_entity'][0]['#post'])) {
    $post = $variables['elements']['field_activity_entity'][0]['#post'];

    $visibility = $post->field_visibility->value;
    $variables['visibility_icon'] = social_post_get_visibility_details($visibility);
    $variables['visibility_label'] = social_post_get_visibility_details($visibility, 'label');
  }

  $activity = $variables['elements']['#activity'];
  $post = $activity->getRelatedEntity();
  if (!empty($post) && $post->getEntityTypeId() === 'post') {
    $variables['post'] = TRUE;
    $variables['published'] = $post->isPublished();
  }
}

/**
 * Implements hook_preprocess_post__activity().
 */
function social_post_preprocess_post__activity(&$variables) {
  $account = \Drupal::currentUser();

  if (!$variables["published"] && !$account->hasPermission('edit any post entities')) {
    unset($variables["content"]["links"]);
  }
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function social_post_theme_suggestions_post(array $variables) {
  $suggestions = [];
  $entity = $variables['elements']['#post'];
  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');

  $suggestions[] = 'post__' . $sanitized_view_mode;
  $suggestions[] = 'post__' . $entity->bundle();
  $suggestions[] = 'post__' . $entity->bundle() . '__' . $sanitized_view_mode;
  $suggestions[] = 'post__' . $entity->id();
  $suggestions[] = 'post__' . $entity->id() . '__' . $sanitized_view_mode;
  return $suggestions;
}

/**
 * Prepares variables for comment field templates.
 *
 * Default template: field--comment.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - element: An associative array containing render arrays for the list of
 *     comments, and the comment form. Array keys: comments, comment_form.
 *
 * @todo Rename to template_preprocess_field__comment() once
 *   https://www.drupal.org/node/939462 is resolved.
 */
function social_post_preprocess_field(array &$variables) {
  $element = $variables['element'];
  if ($element['#formatter'] === 'comment_post' || $element['#formatter'] === 'comment_post_activity') {
    // Create separate variables for the more_link.
    $variables['more_link'] = $element[0]['more_link'];
  }
}

/**
 * Implements hook_ENTITY_TYPE_create_access().
 */
function social_post_comment_create_access(AccountInterface $account, array $context, $entity_bundle) {
  if ($entity_bundle === 'post_comment') {
    $group = \Drupal::routeMatch()->getParameter('group');
    if (is_numeric($group)) {
      $group = Group::load($group);
    }
    if ($group instanceof GroupInterface) {
      if ($group->hasPermission('add post entities in group', $account)) {
        return AccessResult::allowed()->cachePerUser();
      }
      else {
        return AccessResult::forbidden()->cachePerUser();
      }
    }
  }
  return AccessResult::neutral();
}

/**
 * Implements hook_user_cancel().
 */
function social_post_user_cancel($edit, AccountInterface $account, $method) {
  $update = NULL;

  switch ($method) {
    case 'user_cancel_block_unpublish':
      // Unpublish posts.
      $update = ['status' => 0];
      break;

    case 'user_cancel_reassign':
      // Anonymize all of the posts for this old account.
      $update = ['user_id' => 0];
      break;
  }

  if (!is_null($update)) {
    $pids = \Drupal::entityQuery('post')
      ->condition('user_id', $account->id())
      ->accessCheck()
      ->execute();
    \Drupal::moduleHandler()->loadInclude('social_post', 'inc', 'social_post.admin');
    social_post_mass_update($pids, $update, NULL, TRUE);
  }
}

/**
 * Implements hook_ENTITY_TYPE_predelete().
 */
function social_post_user_predelete($account) {
  // Delete posts.
  if ($account instanceof UserInterface) {
    $pids = \Drupal::entityQuery('post')
      ->condition('user_id', $account->id())
      ->accessCheck(FALSE)
      ->execute();

    $storage_handler = \Drupal::entityTypeManager()
      ->getStorage('post');
    $entities = $storage_handler
      ->loadMultiple($pids);
    $storage_handler
      ->delete($entities);
  }
}
