<?php

/**
 * @file
 * Support ticket references.
 */

/**
 * Implements hook_menu().
 */
function support_reference_menu() {
  $items = array();

  $items['support_reference/autocomplete/%support_client/%'] = array(
    'title' => 'Autocomplete ticket reference',
    'page callback' => 'support_reference_autocomplete',
    'page arguments' => array(2, 3),
    'access callback' => 'user_access',
    'access arguments' => array('edit support ticket references'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Implements hook_permission().
 */
function support_reference_permission() {
  return array(
    'edit support ticket references' => array(
      'title' => t('Edit support ticket references'),
    ),
    'view support ticket references' => array(
      'title' => t('View support ticket references'),
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function support_reference_block_info() {
  return array(
    'support_reference_references' => array(
      'info' => t('Support ticket references'),
      // Turn off caching because the user MIGHT have access to the form.
      // We don't have sufficient control over things to do any better.
      // If we want to be more agressive, we could turn off
      // XSRF protection by setting $form['#token'] = FALSE in the
      // builder, but it's probably a bad idea for this form, which doesn't
      // have confirm page protection.
      'cache' => DRUPAL_NO_CACHE,
    ),
  );
}

/**
 * Implements hook_block_view().
 */
function support_reference_block_view($delta = '') {
  global $user;
  $block = array();
  if ($delta == 'support_reference_references' && arg(0) == 'node' && is_numeric(arg(1))) {
    if ($node = node_load(arg(1))) {
      if ($node->type == 'support_ticket') {
        $view = $edit = '';
        if (user_access('view support ticket references')) {
          $result = db_query('SELECT rnid FROM {support_reference} WHERE nid = :nid ORDER BY rnid DESC', array(':nid' => $node->nid))->fetchCol();
          $nodes = node_load_multiple($result);
          $references = array();
          foreach ($nodes as $reference) {
            // Only list reference if user viewing page has access.
            $client = support_client_load($reference->client);
            if (support_access_clients($client, $user)) {
              $state = _support_state($reference->state);
              $priority = _support_priorities($reference->priority);
              $class = "support-reference state-$state priority-$priority";
              if ($node->client != $reference->client) {
                $class .= ' crossclient';
              }
              $references[$reference->nid] = '<span class="' . check_plain($class) . '">' . l(t('#!nid: !title', array('!nid' => $reference->nid, '!title' => $reference->title)), "node/$reference->nid", array('attributes' => array('title' => t('!state !priority priority ticket.', array('!state' => ucfirst($state), '!priority' => $priority))))) . '</span>';
            }
          }
          $view = theme('item_list', array('items' => $references));
        }
        if (user_access('edit support ticket references')) {
          $edit = drupal_get_form('support_reference_block_form', $node->client, $node);
        }
        $block['content'][] = array('#markup' => $view);
        $block['content'][] = $edit;
        $block['subject'] = t('Support ticket references');
      }
    }
  }
  return $block;
}

function support_reference_block_form($form, &$form_state, $client, $node) {
  $path = drupal_get_path('module', 'support_reference');
  $form['#attached']['library'][] = array('system', 'ui.autocomplete');
  $form['#attached']['css'][] = "$path/support_reference.css";
  $form['#attached']['js'][] = "$path/support_reference.js";
  $form['#attached']['js'][] = array(
    'data' => array('supportReferenceAutoCompletePath' => base_path() . "support_reference/autocomplete/$client/$node->nid"),
    'type' => 'setting',
  );

  $form['#nid'] = $node->nid;

  $form['reference'] = array(
    '#type' => 'textfield',
    '#title' => t('Add / Remove Reference'),
    '#default_value' => '',
    '#required' => TRUE,
  );

  // This gets hidden by the css.
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Change'),
  );

  return $form;
}

function support_reference_block_form_submit($form, &$form_state) {
  $nid = $form['#nid'];

  $node = node_load($nid);
  $client = support_client_load($node->client);
  // Make sure the user is allowed to do this.
  if (user_access('edit support ticket references') && support_access_clients($client)) {
    $match = array();
    if (preg_match_all('/\[#(\d+)\]/', $form_state['values']['reference'], $match)) {
      foreach ($match[1] as $rnid) {
        $rnode = node_load($rnid);
        $rclient = support_client_load($rnode->client);
        // Additional access control check to ignore messing with any references
        // to tickets belonging to clients that the user doesn't have access to.
        if (support_access_clients($rclient)) {
          // If it already exists, delete instead.
          if (db_query('SELECT 1 FROM {support_reference} WHERE nid = :nid AND rnid = :rnid', array(':nid' => $nid, ':rnid' => $rnid))->fetchField()) {
            db_delete('support_reference')->condition('nid', $nid)->condition('rnid', $rnid)->execute();
            db_delete('support_reference')->condition('nid', $rnid)->condition('rnid', $nid)->execute();
          }
          else {
            db_insert('support_reference')->fields(array('nid' => $nid, 'rnid' => $rnid))->execute();
            db_insert('support_reference')->fields(array('nid' => $rnid, 'rnid' => $nid))->execute();
          }
        }
      }
    }
  }
}

/**
 * @todo: should we allow cross-client references?
 */
function support_reference_autocomplete($client = NULL, $skipnid = 0) {
  $matches = array();
  if (is_object($client) && isset($client->clid) && support_access_clients($client)) {
    $result = db_query('SELECT n.nid, n.title, r.rnid FROM {support_ticket} s INNER JOIN {node} n ON s.nid = n.nid LEFT JOIN {support_reference} r ON (r.nid = :skipnid AND r.rnid = s.nid) WHERE s.client = :client AND s.nid <> :skipnid ORDER BY n.nid DESC', array(':skipnid' => $skipnid, ':client' => $client->clid));
    foreach ($result as $ticket) {
      // We are using the titles directly from the database instead of using node_load() for speed / memory reasons.
      if (!empty($ticket->rnid)) {
        // If rnid is non null, there's a reference already, so indicate that choosing it will cause removal.
        // NOTE: check_plain() here causes double escaping on Drupal 7. (But not Drupal 6!)
        $matches[] = t('[#!nid]: !title (remove)', array('!nid' => $ticket->nid, '!title' => $ticket->title));
      }
      else {
        // NOTE: check_plain() here causes double escaping on Drupal 7. (But not Drupal 6!)
        $matches[] = t('[#!nid]: !title', array('!nid' => $ticket->nid, '!title' => $ticket->title));
      }
    }
  }
  drupal_json_output($matches);
}
