<?php
/**
 * @file
 * Code for the Commons Q&A feature.
 */

include_once 'commons_q_a.features.inc';

/**
 * Implements hook_theme().
 */
function commons_q_a_theme() {
  return array(
    'rate_template_commons_thumbs_up_down' => array(
      'variables' => array('links' => NULL, 'results' => NULL, 'mode' => NULL, 'just_voted' => FALSE, 'content_type' => NULL, 'content_id' => NULL, 'display_options' => NULL),
      'template' => 'commons-thumbs-up-down',
    ),
  );
}

/**
 * Implements hook_node_view().
 *
 * Provides an answer button to bring a user down to the answer form.
 */
function commons_q_a_node_view($node, $view_mode) {
  if ($node->type == 'question' && $view_mode == 'full') {
    // Remove add comment link.
    unset($node->content['links']['comment']);
    // Add the answer link below.
    if (commons_q_a_check_answer_access($node)) {
      $node->content['links']['answer'] = array(
        '#theme' => 'links__node__answer',
        '#links' => array(
          'answer-add' => array(
            'title' => t('Answer'),
            'attributes' => array(
              'title' => t('Answer this question'),
            ),
            'href' => 'node/' . $node->nid,
            'fragment' => 'answer',
          ),
        ),
      );
    }
    return $node;
  }
}

/**
 * Implements hook_form_FROM_ID_alter().
 */
function commons_q_a_form_commons_bw_partial_node_form_alter(&$form, &$form_state) {
  if (empty($form['#entity']) || $form['#entity']->type != 'question') {
    return;
  }

  $form['title']['#markup'] = t('Ask a question');

  $language = $form['body']['#language'];
  $form['body'][$language][0]['#title_display'] = 'invisible';
  $form['body'][$language][0]['#required'] = TRUE;
  $form['body'][$language][0]['#placeholder'] = t('Ask anything. Let the community answer openly.');
  $form['body'][$language][0]['#resizable'] = FALSE;

  // Set fields as hideable so the forms can be compacted.
  $form['body']['#attributes']['class'][] = 'trigger-field';
  foreach (array('field_media', 'field_image', 'og_group_ref', 'choice_wrapper', 'actions') as $field) {
    if (isset($form[$field])) {
      $form[$field]['#attributes']['class'][] = 'hideable-field';
    }
  }

  $form['actions']['submit']['#value'] = t('Ask');
  $form['#pre_render'][] = 'commons_q_a_form_commons_bw_partial_node_form_after_build';
}

/**
 * After-build call-back.
 * See commons_q_a_form_commons_bw_partial_node_form_alter().
 */
function commons_q_a_form_commons_bw_partial_node_form_after_build($form) {
  $language = $form['body']['#language'];
  $form['body'][$language][0]['#pre_render'] = array();
  $form['body'][$language][0]['format']['#access'] = FALSE;
  $form['body'][$language][0]['value']['#rows'] = 3;

  return $form;
}

/*
 * Run an access check to see if the current user can create answer nodes based
 * off of the question node.
 */
function commons_q_a_check_answer_access($question) {
  $group_ref = array();
  if (!empty($question->og_group_ref[LANGUAGE_NONE])) {
    foreach ($question->og_group_ref[LANGUAGE_NONE] as $key => $value) {
      // Check to see the user has access to the group the question is in, only attach to those groups they have permission to post in.
      if (og_user_access('node', $value['target_id'], 'create answer content')) {
        $group_ref[] = $value['target_id'];
        return TRUE;
      }
    }
  }
  // If user belongs to no groups, or no groups are assigned to the Question, check node_access for user.
  else {
    if (node_access('create', 'answer')) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Implements hook_views_pre_render().
 */
function commons_q_a_views_pre_render(&$view) {
  // Improve the browsing widget empty text when displayed outside of a group.
  // TODO: Enable og_context and check group context instead of looking for an
  // empty first argument.
  if (empty($view->args[0]) && $view->name == 'commons_bw_q_a') {
    $view->display_handler->handlers['empty']['area']->options['content'] = t('No questions have been created.');
  }

  if ($view->name == 'commons_question_answers' && !empty($view->args[0])) {
    // If the user has access to post into any of the groups associated
    // with the question, embed a simplified answer node form.
    global $user;

    if (user_is_anonymous()) {
      $account = drupal_anonymous_user();
    }
    else {
      $account = $user;
    }

    $question_nid = $view->args[0];
    $question = node_load($question_nid);

    $answer_access = commons_q_a_check_answer_access($question);
    // Check global user access before showing the answer form.
    if ($answer_access) {
      $view->empty['area']->options['content'] = t("This question hasn't been answered yet. You can be the first to answer it!");
      module_load_include('inc', 'node', 'node.pages');
      $types = node_type_get_types();
      $node = (object) array(
        'uid' => $account->uid,
        'name' => (isset($account->name) ? $account->name : ''),
        'type' => 'answer', 'language' => LANGUAGE_NONE
      );
      // Prepopulate the Related question field
      // with Entityreference Prepopulate, which looks strictly at $_GET.
      $_GET['field_related_question'] = $view->args[0];
      if (!empty($group_ref)) {
        $_GET['og_group_ref'] = implode(',', $group_ref);
      }
      $answer_form = drupal_get_form('answer_node_form', $node);
      $answer_form['header'] = array(
        '#markup' => '<h3 id="answer" name="answer">' . t('Add a new answer') . '</h3>',
        '#weight' => -10,
      );
      // Hide any vertical tabs that might be present.
      $answer_form['additional_settings']['#access'] = FALSE;
      // Hide the Related question field.
      $answer_form['field_related_question']['#access'] = FALSE;
      // Add the form to the attachment_after part of the view,
      $view->attachment_after .= drupal_render($answer_form);
      // We only need to add the form once if the user has access to
      // post questions into any of the groups associated with the parent.
      return;
    }
    // Tell Anonymous users to login.
    elseif ($account->uid === 0) {
      $view->empty['area']->options['content'] = t("This question hasn't been answered yet. !create to be the first to answer it!", array('!create' => l(t("Login or create an account"), 'user')));
      return;
    }
    // If the user is not anonymous, but cannot answer the question. Don't tell
    // them they should be the first to answer it.
    else {
      $view->empty['area']->options['content'] = t("This question hasn't been answered yet.");
      return;
    }
  }
}

/*
 * Implements hook_module_implements_alter().
 * Set commons_q_a form alter to happen after node so the title doesn't get reset.
 */
function commons_q_a_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'form_alter') {
    $group = $implementations['commons_q_a'];
    unset($implementations['commons_q_a']);
    $implementations['commons_q_a'] = $group;
  }
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function commons_q_a_form_node_form_alter(&$form, &$form_state, $form_id) {
  $node = $form['#node'];

  list(, , $bundle) = entity_extract_ids('node', $node);

  if ($bundle == 'question' && empty($node->nid)) {
    drupal_set_title(t('Ask a question'));
  }
}

/**
* Implements hook_form_alter().
*/
function commons_q_a_form_alter(&$form, &$form_state, $form_id) {
  // Unset the groups audience field. Answers programatically inherit
  // the group membership of their respective questions.
  if ($form_id == 'answer_node_form') {
    $form['og_group_ref']['#access'] = FALSE;
    $form['actions']['submit']['#submit'][] = 'commons_q_a_answer_submit';
    // Ensure that the answer node inherits group membership from the
    // parent question by preventing users from changing the audience through
    // the Trusted Contacts toggle when commons_trusted_contacts.module
    // is enabled.
    $form_state['hide_audience_toggle'] = TRUE;
  }
  if ($form_id == 'comment_node_question_form' || $form_id == 'comment_node_answer_form') {
    $form['container'] = array(
      '#type' => 'fieldset',
      '#title' => t('Add new comment'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#weight' => 2,
    );
    $form['container']['author'] = $form['author'];
    $form['container']['comment_body'] = $form['comment_body'];
    $form['container']['actions'] = $form['actions'];
    unset($form['author']);
    unset($form['subject']);  // We don't need a subject, they're pointless within comments.
    unset($form['comment_body']);
    unset($form['actions']);
  }
}

/**
 * Implements hook_field_attach_submit().
 */
function commons_q_a_field_attach_submit($entity_type, &$entity, $form, &$form_state) {
  // Questions should inherit the group membership of the related question.
  if ($entity_type == 'node' && $entity->type == 'answer' && empty($entity->nid)) {
    $question = node_load($entity->field_related_question[LANGUAGE_NONE][0]['target_id']);
    $entity->og_group_ref = $question->og_group_ref;
  }
}

/**
 * Submit handler for the submit button on the answer node form.
 */
function commons_q_a_answer_submit($form, &$form_state) {
  // Redirect the user back to the related question.
  $form_state['redirect'] = 'node/' . $form_state['values']['field_related_question'][LANGUAGE_NONE][0]['target_id'];
}

/**
 * Implements hook_commons_activity_streams_message_selection_alter().
 */
function commons_q_a_commons_activity_streams_message_selection_alter(&$message_type, $hook, $node) {
    // Provide a special message type that uses "User asked the question"
    // phrasing when a new question node is created.
    if ($hook == 'node_insert' && $node->type == 'question') {
    $message_type = 'commons_q_a_question_asked';
  }

  // Provide a special message type that uses "User answered the question"
  // phrasing when a new answer node is created.
  if ($hook == 'node_insert' && $node->type == 'answer') {
    $message_type = 'commons_q_a_question_answered';
  }
}

/**
 * Preprocess function for the commons_like template.
 */
function commons_q_a_preprocess_rate_template_commons_thumbs_up_down(&$variables) {
  extract($variables);

  $up_classes = 'rate-number-up-down-btn-up';
  $down_classes = 'rate-number-up-down-btn-down';
  if (isset($results['user_vote'])) {
    switch ($results['user_vote']) {
      case $links[0]['value']:
        $up_classes .= ' rate-voted';
        break;
      case $links[1]['value']:
        $down_classes .= ' rate-voted';
        break;
    }
  }

  $variables['up_button'] = theme('rate_button', array('text' => $links[0]['text'], 'href' => $links[0]['href'], 'class' => $up_classes));
  $variables['down_button'] = theme('rate_button', array('text' => $links[1]['text'], 'href' => $links[1]['href'], 'class' => $down_classes));
  if ($results['rating'] > 0) {
    $score = $results['rating'];
    $score_class = 'positive';
  }
  elseif ($results['rating'] < 0) {
    $score = $results['rating'];
    $score_class = 'negative';
  }
  else {
    $score = 0;
    $score_class = 'neutral';
  }
  $variables['score'] = $score;
  $variables['score_class'] = $score_class;

  $info = array();
  if ($mode == RATE_CLOSED) {
    $info[] = t('Voting is closed.');
  }
  if ($mode != RATE_COMPACT && $mode != RATE_COMPACT_DISABLED) {
    if (isset($results['user_vote'])) {
      $info[] = t('You voted \'@option\'.', array('@option' => $results['user_vote'] == 1 ? $links[0]['text'] : $links[1]['text']));
    }
  }
  $variables['info'] = implode(' ', $info);
}

/**
 * Implements hook_rate_templates().
 */
function commons_q_a_rate_templates() {
  $templates = array();

  $templates['commons_thumbs_up_down'] = new stdClass();
  $templates['commons_thumbs_up_down']->value_type = 'points';
  $templates['commons_thumbs_up_down']->options = array(
    array(1, 'up'),
    array(-1, 'down'),
  );
  $templates['commons_thumbs_up_down']->theme = 'rate_template_commons_thumbs_up_down';
  $templates['commons_thumbs_up_down']->css = drupal_get_path('module', 'commons_q_a') . '/commons-thumbs-up-down.css';
  $templates['commons_thumbs_up_down']->customizable = FALSE;
  $templates['commons_thumbs_up_down']->translate = TRUE;
  $templates['commons_thumbs_up_down']->use_source_translation = TRUE;
  $templates['commons_thumbs_up_down']->template_title = t('Commons Thumbs up / down');

  return $templates;
}

/**
 * Implements hook_strongarm_alter().
 */
function commons_q_a_strongarm_alter(&$items) {
  // The Rate module stores all of its configuration data in a single variable.
  // Add a thumbs up/down-style 'Answer' rate widget by altering the rate
  // variable.
  if (!empty($items['rate_widgets']->value)) {
    $items['rate_widgets']->value[] = commons_q_a_rate_widget();
  }
}

/**
 * Return a Rate module widget configuration used for thumbs up/down
 * rating of answers.
 */
function commons_q_a_rate_widget() {
  return (object) array(
    'name' => 'commons_answer',
    'tag' => 'commons_thumbs_up_down',
    'title' => 'Answer',
    'node_types' => array(
      0 => 'answer',
    ),
    'comment_types' => array(),
    'options' => array(
      0 => array(
        0 => 1,
        1 => 'up',
      ),
      1 => array(
        0 => -1,
        1 => 'down',
      ),
    ),
    'template' => 'commons_thumbs_up_down',
    'node_display' => '2',
    'teaser_display' => FALSE,
    'comment_display' => '2',
    'node_display_mode' => '1',
    'teaser_display_mode' => '1',
    'comment_display_mode' => '1',
    'roles' => array(
      2 => '2',
      1 => 0,
    ),
    'allow_voting_by_author' => 1,
    'noperm_behaviour' => '3',
    'displayed' => '1',
    'displayed_just_voted' => '1',
    'description' => '',
    'description_in_compact' => TRUE,
    'delete_vote_on_second_click' => '1',
    'value_type' => 'points',
    'theme' => 'rate_template_commons_thumbs_up_down',
    'css' => 'profiles/commons/modules/contrib/commons_q_a/commons-thumbs-up-down.css',
    'translate' => TRUE,
    'use_source_translation' => TRUE,
  );
}
