<?php

/**
 * @file queue_ui.module
 */

/**
 * Implements hook_permission().
 */
function queue_ui_permission() {
  return array(
    'admin queue_ui' => array(
      'title' => t('Administer queues'),
      'description' => t('View, run, and delete queues'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function queue_ui_menu() {
  $items['admin/config/system/queue-ui'] = array(
    'title' => 'Queue manager',
    'description' => 'View and manage queues',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('queue_ui_page'),
    'access arguments' => array('admin queue_ui'),
    'file' => 'queue_ui.pages.inc',
  );
  
  return $items;
}

/**
 * Menu loader for queue_ui_queue.
 */
function queue_ui_queue_load($name) {
  return DrupalQueue::get($name);
}

// @todo remove before prod
function queue_ui_test() {
  $queue = DrupalQueue::get('queue ui test_me');
  $queue->createQueue();
  $num = mt_rand(0,99);
  for ($i = 0; $i < $num; $i++) {
    $queue->createItem(time());
  }
}

/**
 * Get the names of queues.
 *
 * @param Array of queue names suitable for DrupalQueue::get();
 */
function queue_ui_queue_names() {
  $result = db_query("SELECT DISTINCT name FROM {queue}");
  return $result->fetchAll();
}

/**
 * Get queues.
 *
 * @return Array of queues indexed by name and containing queue object and number
 * of items.
 */
function queue_ui_queues() {
  $queues = array();
  $queue_names = queue_ui_queue_names();
  if (!empty($queue_names)) {
    // Build array of queues indexed by name with number of items.
    foreach ($queue_names as $name) {
      $queue = DrupalQueue::get($name->name);
      $queues[$name->name] = array(
        'queue' => $queue,
        'items' => $queue->numberOfItems(),
      );
    }
  }
  return $queues;
}

/**
 * Get queues defined with hook_queue_info().
 *
 * @return Array of queues indexed by name and containing
 */
function queue_ui_defined_queues() {
  $queues = &drupal_static(__FUNCTION__);
  if (!isset($queues)) {
    // Invoke hook_queue_info().
    $queues = module_invoke_all('queue_info');
  }
  return $queues;
}

/**
 * Implements hook_cron().
 */
function queue_ui_cron() {
  // Retrieve queues set for cron processing.
  $defs = queue_ui_defined_queues();
  if (!empty($defs)) {
    foreach ($defs as $name => $definition) {
      $queue = DrupalQueue::get($name);
      // A cron callback must be defined and there must be items in the queue.
      if (isset($definition['cron']) && is_object($queue) && $queue->numberOfItems()) {
        $active = variable_get('queue_ui_cron_' . $name, FALSE);
        if ($active) {
          // Pass $queue to cron callback for processing.
          $function = $definition['cron']['callback'];
          // Definitions can define arguments.
          $args = isset($definition['cron']['callback']) ? $definition['cron']['callback'] : NULL;
          $function($queue, $args);
        }
      }
    }
  }
}

// @todo remove before prod
function queue_ui_queue_info() {
  return array(
    'queue ui test_me' => array(
      'title' => t('Test queue'),
      'batch' => array(
        'operations' => array(array('queue_ui_batch_test', array())),
        'finished' => 'queue_ui_batch_finished',
        'title' => t('Processing test queue'),
      ),
      'cron' => array(
        'callback' =>'queue_ui_test_process',
      ),
    ),
  );
}

function queue_ui_test_process($queue) {
  $count = $queue->numberOfItems();
  for ($i = 0; $i < 20 && $count > 0; $i++) {
    $item = $queue->claimItem(20); // Lease time.
    if ($item) {
      // We would do some processing, if this were REAL.
      $queue->deleteItem($item);
      $count--;
    }
  }
}

function queue_ui_batch_test($queue, &$context) {
  if (empty($context['sandbox'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current'] = 0;
    $context['sandbox']['max'] = $queue->numberOfItems();
  }
  for ($i = 0; $i < 20 && $context['sandbox']['current'] < $context['sandbox']['max']; $i++) {
    $item = $queue->claimItem(20); // Lease time.
    if ($item) {
      // We would do some processing, if this were REAL.
      $queue->deleteItem($item);
    }
    $context['sandbox']['progress']++;
    $context['sandbox']['current']++;
  }
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}

function queue_ui_batch_finished($success, $results, $operations) {
  if ($success) {
    $message = 'success';
  }
  else {
    $message = t('An error occured @todo.');
  }
  drupal_set_message($message);
}