<?php
// $Id: uc_deliverytimeslot.module,v 1.2.2.2 2009/12/01 16:46:32 mogtofu33 Exp $

/**
 * @file
 * Delivery time slot module, add a time slot selection on checkout pane with
 * full admin (date, time slot, max limit, special).
 *
 */

/******************************************************************************
 * Drupal Hooks                                                               *
 ******************************************************************************/

/**
 * Implementation of hook_help().
 */
function uc_deliverytimeslot_help($path, $arg) {
  switch ($path) {
    case 'admin/help#uc_deliverytimeslot':
      $output = '<p>'. t('First you need to set-up your default delivery timeslot table from delivery timeslot settings.') .'</p>';
      $output .= '<p>'. t('It is recommended to add token on your <a href="!url">customer invoice template</a> and <a href="!url2">Checkout messages</a>, available token are [order-delivery-date] and [order-delivery-timeslot]', array('!url' => url('admin/store/settings/orders/edit'), '!url2' => url('admin/store/settings/checkout/edit/messages'))) .'</p>';
      break;
    case 'admin/store/settings/deliverytimeslot':
      $output = '<p>'. t('First : You need to configure your timeslot list and available day from the <em>Settings</em> fieldset.');
      $output .= '<br/>'. t('Then you could generate a default timeslot table from the <em>Generate</em> fieldset and adjust your time slot table to your need.') .'</p>';
      $output .= '<p>'. t('You can create special date, on this date there can be special time slot and max limit. It could be usefull on holliday.');
      $output .= '<br/>'. t('You can set-up some checkout pane display option on <a href="!url">Checkout settings</a>.', array('!url' => url('admin/store/settings/checkout/edit/panes')));
      $output .= '<br/>'. t('You can access delivery timeslot list on <a href="!url">Delivery timeslot list</a>.', array('!url' => url('admin/store/orders/deliverytimeslot'))) .'</p>';
      $output .= '<p>'. t('It is recommended to add token on <a href="!url">Checkout messages</a> and customer/admin template, see INSTALL.txt for more information.', array('!url' => url('admin/store/settings/checkout/edit/messages')));
      break;
    case 'admin/store/orders/deliverytimeslot':
      $output = '<p>'. t('Confirmed status: list all timeslot where order status is <em>in checkout</em> or next.');
      $output .= '<br/>'. t('Unconfirmed status: list all timeslot where order status is <em>pending</em> or <em>cancel</em>.') .'</p>';
      break;
  }
  return $output;
}

/**
 * Implementation of hook_menu().
 */
function uc_deliverytimeslot_menu() {
  $items = array();
  $items['admin/store/settings/deliverytimeslot'] = array(
    'title' => 'Delivery timeslot settings',
    'description' => 'Configure the delivery timeslot table settings.',
    'page callback' => 'uc_deliverytimeslot_admin_view',
    'access arguments' => array('administer store'),
    'file' => 'uc_deliverytimeslot.admin.inc',
  );
  $items['admin/store/settings/deliverytimeslot/admin/%/%'] = array(
    'title' => 'Add a value',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_deliverytimeslot_admin_edit_form', 5, 6),
    'access arguments' => array('administer store'),
    'type' => MENU_CALLBACK,
    'file' => 'uc_deliverytimeslot.admin.inc',
  );
  $items['admin/store/orders/deliverytimeslot'] = array(
    'title' => 'Delivery timeslot list',
    'description' => 'See delivery timeslot by orders.',
    'page callback' => 'uc_deliverytimeslot_view',
    'access arguments' => array('administer store'),
    'file' => 'uc_deliverytimeslot.admin.inc',
  );
  $items['admin/store/orders/deliverytimeslot/print'] = array(
    'title' => 'Print',
    'page callback' => 'uc_deliverytimeslot_view',
    'access arguments' => array('administer store'),
    'type' => MENU_LOCAL_TASK,
    'file' => 'uc_deliverytimeslot.admin.inc',
  );
  return $items;
}

/**
 * Implementation of hook_theme().
 */
function uc_deliverytimeslot_theme() {
  return array(
    'deliverytimeslot_pane' => array(
      'arguments' => array('form' => NULL),
    ),
  );
}
/*******************************************************************************
 * Hook Functions (Ubercart)                                                   *
 *******************************************************************************/

/**
 * Implementation of hook_checkout_pane().
 */
function uc_deliverytimeslot_checkout_pane() {
  $panes[] = array(
    'id' => 'deliverytimeslot',
    'callback' => 'uc_checkout_pane_deliverytimeslot',
    'title' => t('Delivery timeslot table'),
    'desc' => t('Let customers specify a time slot of shipping.'),
    'weight' => 5,
  );
  return $panes;
}

/**
 * Implementation of hook_order().
 */
function uc_deliverytimeslot_order($op, &$arg1, $arg2) {

  switch ($op) {
    case 'save':
      if (is_numeric($arg1->deliverytimeslot['delivery_day']) && is_numeric($arg1->deliverytimeslot['delivery_sid'])) {
        db_query("UPDATE {uc_deliverytimeslot_order} SET date = %d, sid = %d "
                ."WHERE order_id = %d", $arg1->deliverytimeslot['delivery_day'], $arg1->deliverytimeslot['delivery_sid'], $arg1->order_id);
        if (db_affected_rows() == 0) {
          db_query("INSERT INTO {uc_deliverytimeslot_order} (order_id, date, sid) VALUES (%d, %d, %d)", $arg1->order_id, $arg1->deliverytimeslot['delivery_day'], $arg1->deliverytimeslot['delivery_sid']);
        }
      }
      break;

    case 'update':
      $list = uc_order_status_list('general');
      foreach ($list as $status) {
        $ids[] = $status['id'];
      }
      if (is_numeric($arg1->deliverytimeslot['delivery_day']) && is_numeric($arg1->deliverytimeslot['delivery_sid'])) {
        if (in_array($arg2, $ids)) {
          db_query("UPDATE {uc_deliverytimeslot_order} SET confirmed = 1 WHERE order_id = %d", $arg1->order_id);
        }
        if ($arg2 == 'canceled') {
          db_query("UPDATE {uc_deliverytimeslot_order} SET confirmed = 0 WHERE order_id = %d", $arg1->order_id);
        }
      }
      break;

    case 'load':
      $result = db_query("SELECT date, sid FROM {uc_deliverytimeslot_order} WHERE order_id = %d", $arg1->order_id);
      if ($data = db_fetch_object($result)) {
        $arg1->deliverytimeslot['delivery_day'] = $data->date;
        $arg1->deliverytimeslot['delivery_sid'] = $data->sid;
      }
      break;

    case 'delete':
      db_query("DELETE FROM {uc_deliverytimeslot_order} WHERE order_id = %d", $arg1->order_id);
      break;

  }
}

/**
 * Implementation of hook_order_pane().
 */
function uc_deliverytimeslot_order_pane() {
  $panes[] = array(
    'id' => 'deliverytimeslot',
    'callback' => 'uc_order_pane_deliverytimeslot',
    'title' => t('Delivery timeslot'),
    'desc' => t('Let the customer specify a date and time slot of shipping.'),
    'class' => 'pos-left',
    'weight' => 5,
    'show' => array('view', 'edit', 'customer'),
  );
  return $panes;
}

/**
 * Implementation of hook_order_actions().
 */
function uc_deliverytimeslot_order_actions($order) {
  $actions = array();
  $module_path = base_path() . drupal_get_path('module', 'uc_deliverytimeslot');
  $timeslot = _uc_deliverytimeslot_timeslot();
  if (user_access('fulfill orders')) {
    $req = db_query("SELECT date, sid FROM {uc_deliverytimeslot_order} WHERE order_id = %d", $order->order_id);
    if ($res = db_fetch_array($req)) {
      $date = uc_date_format(date('m', $res['date']), date('d', $res['date']), date('Y', $res['date']));
      $title = t('Delivery: !date - !time.', array('!date' => $date, '!time' => $timeslot[$res['sid']]));
      $actions[] = array(
        'name' => t('Delivery'),
        'url' => 'admin/store/orders/deliverytimeslot',
        'icon' => '<img src="'. $module_path .'/images/calendar.png" alt="'. $title .'" />',
        'title' => $title,
      );
    }
  }
  return $actions;
}
/**
 * Implementation of hook_token_values(). (token.module)
 */
function uc_deliverytimeslot_token_values($type, $object = NULL) {
  $values = array();
  switch ($type) {
    case 'order':
      $order = $object;
      $result = db_fetch_array(db_query("SELECT doid, date, sid FROM {uc_deliverytimeslot_order} WHERE order_id = %d", $order->order_id));
      if (isset($result['doid'])) {
        $date = uc_date_format(date('m', $result['date']), date('d', $result['date']), date('Y', $result['date']));
        $timeslot = _uc_deliverytimeslot_timeslot();
        $timeslot = $timeslot[$result['sid']];

        $values['order-delivery-date'] = empty($result['date']) ? t('No date of delivery found.') : $date;
        $values['order-delivery-timeslot'] = !isset($result['sid']) ? t('No time slot of delivery found.') : check_plain($timeslot);
      }
      break;
  }

  return $values;
}

/**
 * Implementation of hook_token_list(). (token.module)
 */
function uc_deliverytimeslot_token_list($type = 'all') {
  $tokens = array();
  if ($type == 'order' || $type == 'ubercart' || $type == 'all') {
    $tokens['order']['order-delivery-date'] = t('The desired date of delivery.');
    $tokens['order']['order-delivery-timeslot'] = t('The desired timeslot of delivery.');
  }
  return $tokens;
}

/*******************************************************************************
 * Callback Functions, Forms, and Tables                                       *
 *******************************************************************************/

/**
 * Configuration and construction of delivery timeslot table on checkout pane
 */
function uc_checkout_pane_deliverytimeslot($op, &$arg1, $arg2) {
  $shipping_quote = variable_get('uc_deliverytimeslot_quote', array_values(array_flip(uc_quote_shipping_method_options())));
  $timeslot = _uc_deliverytimeslot_timeslot();
  switch ($op) {
    case 'view':
      drupal_add_css(drupal_get_path('module', 'uc_deliverytimeslot') .'/uc_deliverytimeslot.css');
      $description = variable_get('uc_deliverytimeslot_display_text', t('Please specify a date and time of delivery.'));
      $contents['delivery_timeslot'] = array('#type' => 'radios');
      if(variable_get('uc_deliverytimeslot_display_show', 0) == 1) {
        $no_hide = TRUE;
      }
      // back and error on checkout form
      if (is_numeric($arg1->deliverytimeslot['delivery_day']) && is_numeric($arg1->deliverytimeslot['delivery_sid'])) {
        $no_hide = TRUE;
        $_SESSION['deliverytimeslot'] = $arg1->deliverytimeslot['delivery_day'] .'|'. $arg1->deliverytimeslot['delivery_sid'];
      }
      elseif (isset($_SESSION['deliverytimeslot'])) {
        unset($_SESSION['deliverytimeslot']);
      }

      // if customer go away and back on the same session, quote is stored
      if (isset($_SESSION['quote']['method']) && in_array($_SESSION['quote']['method'], $shipping_quote)) {
        $no_hide = TRUE;
      }

      // ad js when select shipping quote
      $reg = '';
      foreach ($shipping_quote AS $quote) {
        $reg .= $quote .'|';
      }
      $reg = substr($reg, 0, -1);
      $js = 'Drupal.behaviors.deliverytimeslot = function() {';
      $no_hide ? $js .= '$("#deliverytimeslot-pane").show();' : $js .= '$("#deliverytimeslot-pane").hide();';
      // case : only one shipping quote, no input radios
      $js .= 'var onevalue = $("#quote").find("input:hidden[name=quote-option]").val();';
      $js .= 'if(window.set_line_item && onevalue){
                var reg = new RegExp("('. $reg .')", \'g\');
                if (reg.test(onevalue)){
                  $("#deliverytimeslot-pane").fadeIn("slow");
                } else {
                  $("#deliverytimeslot-pane").fadeOut("slow");
                }
              };';
      // case : multiple quote
      $js .= '$("#quote").find("input:radio").click(function(){
                  var checkedvalue=$(this).val();
                    var reg = new RegExp("('. $reg .')", \'g\');
                    if (checkedvalue && reg.test(checkedvalue)){
                      $("#deliverytimeslot-pane").fadeIn("slow");
                    } else {
                      $("#deliverytimeslot-pane").fadeOut("slow");
                    }
                });}';
      drupal_add_js($js, 'inline');
      return array('description' => check_plain($description), 'contents' => $contents, 'theme' => 'deliverytimeslot_pane');

    case 'process':
      if (in_array($arg1->quote['method'], $shipping_quote)) {
        if ($arg2['delivery_timeslot']) {
          $data = explode('|', $arg2['delivery_timeslot']);
          $arg1->deliverytimeslot['delivery_day'] = $data[0];
          $arg1->deliverytimeslot['delivery_sid'] = $data[1];
        }
        else {
          drupal_set_message(t('Please select a delivery timeslot.'), 'error');
          drupal_goto('cart/checkout');
        }
      }
      return TRUE;

    case 'review':
      if (is_numeric($arg1->deliverytimeslot['delivery_day']) && is_numeric($arg1->deliverytimeslot['delivery_sid']) && (in_array($arg1->quote['method'], $shipping_quote))) {
        $date = uc_date_format(date('m', $arg1->deliverytimeslot['delivery_day']), date('d', $arg1->deliverytimeslot['delivery_day']), date('Y', $arg1->deliverytimeslot['delivery_day']));
        $review[] = array('title' => t('Delivery date and time'), 'data' => $date .' - '. $timeslot[$arg1->deliverytimeslot['delivery_sid']]);
      }
      return $review;

    case 'settings':
      include_once(drupal_get_path('module', 'uc_deliverytimeslot') .'/uc_deliverytimeslot.admin.inc');
      return uc_deliverytimeslot_settings_pane();
  }
}

/**
 * Theme the deliverytimeslot form in table.
 *
 * @ingroup themeable
 * @see uc_checkout_pane_deliverytimeslot()
 *
 */
function theme_deliverytimeslot_pane($form) {

  $shipping_quote = variable_get('uc_deliverytimeslot_quote', array_values(array_flip(uc_quote_shipping_method_options())));
  $set_day = $set_sid = FALSE;
  $days_list = _uc_deliverytimeslot_week_days();
  $timeslot = _uc_deliverytimeslot_timeslot();
  $delta = variable_get('uc_deliverytimeslot_display_days_future', 0);
  $disp = variable_get('uc_deliverytimeslot_display_days', 5) + $delta;
  $disp_mode = variable_get('uc_deliverytimeslot_display_mode', 'day');
  $week_days = variable_get('uc_deliverytimeslot_week_days', _uc_deliverytimeslot_week_days());

  // back and error on checkout form
  if (isset($_SESSION['deliverytimeslot'])) {
    $tmp_value = explode('|', $_SESSION['deliverytimeslot']);
    $set_day = (int)$tmp_value[0];
    $set_sid = (int)$tmp_value[1];
  }

  // rows construction day on header
  $i = 0;
  if ($disp_mode == 'day') {
    foreach ($timeslot AS $sid => $slot) {
      $i < count($timeslot) ? $i++ : $i = 0;
      $row = $header = array();
      $row[] = array('data' => $slot, 'class' => 'deliverytimeslot');
      for ($delt = $delta; $delt < $disp; $delt++) {
        $timestamps = _uc_deliverytimeslot_date(FALSE, $delt);
        if (in_array(date('l', $timestamps), $week_days)) {
          // back button
          if (($set_day && $set_day == $timestamps) && ($set_sid == (int)$sid)) {
            $checked = ' checked="checked"';
          }
          else {
            $checked = '';
          }

          $header[] = array('data' => t("!day", array("!day" => date('l', $timestamps))) .'<div class="deliveryday">'. date('j', $timestamps) .'&nbsp;'. t('!month', array('!month' => date('F', $timestamps))) .'</div>', 'class' => 'deliverydate');

          $class = 'free';
          $max = $data = '';
          $value = $timestamps .'|'. $sid;
          $sp_query = db_query("SELECT * FROM {uc_deliverytimeslot_special} WHERE date = %d AND sid = %d", $timestamps, $sid);
          $sp_det = db_fetch_array($sp_query);
          $booked_num = db_result(db_query("SELECT Count(*) as num FROM {uc_deliverytimeslot_order} WHERE date = %d AND sid = %d AND confirmed = 1", $timestamps, $sid));

          if ($sp_det != 0) {
            $max = $sp_det['max_limit'];
          }
          else {
            $default_det = db_fetch_array(db_query("SELECT * FROM {uc_deliverytimeslot_default} WHERE day = '%s' AND sid = %d", date('l', $timestamps), $sid));
            $max = $default_det['max_limit'];
          }
          if (!$max || $max == 0) {
            $class = 'na';
          }
          elseif (($booked_num >= $max) && $checked == '') {
            $class = 'full';
          }
          else {
            $data = '<input type="radio" class="form-radio" value="'. $value .'" name="panes[deliverytimeslot][delivery_timeslot]" id="edit-panes-deliverytimeslot-delivery-timeslot-'. $value .'" '. $checked .'/>';
          }
          $row[] = array('data' => $data, 'class' => $class);
        }
        else {
          $i == 1 ? $disp++ : '' ;
        }
      }
    $rows[] = $row;
    $headers = array_merge(array('&nbsp;'), $header);
    }
  }
  // rows construction day on left column
  else {
    $headers = array_merge(array('&nbsp;', '&nbsp;'), _uc_deliverytimeslot_timeslot());
    for ($delt = $delta; $delt < $disp; $delt++) {
      $timestamps = _uc_deliverytimeslot_date(FALSE, $delt);
      $row = array();
      if (in_array(date('l', $timestamps), variable_get('uc_deliverytimeslot_week_days', _uc_deliverytimeslot_week_days()))) {

        $row[] = array('data' => t('!day', array('!day' => date('l', $timestamps))), 'class' => 'deliveryday');
        $row[] = array('data' => date('j', $timestamps) .' '. t('!month', array('!month' => date('F', $timestamps))), 'class' => 'deliverydate');

        foreach ($timeslot as $sid => $slot) {
          // back button
          if (($set_day && $set_day == $timestamps) && ($set_sid == $sid)) {
            $checked = ' checked="checked"';
          }
          else {
            $checked = '';
          }
          $class = 'free';
          $max = $data = '';
          $value = $timestamps .'|'. $sid;
          $sp_query = db_query("SELECT * FROM {uc_deliverytimeslot_special} WHERE date = %d AND sid = %d", $timestamps, $sid);
          $sp_det = db_fetch_array($sp_query);
          $booked_num = db_result(db_query("SELECT Count(*) as num FROM {uc_deliverytimeslot_order} WHERE date = %d AND sid = %d AND confirmed = 1", $timestamps, $sid));

          if ($sp_det != 0) {
            $max = $sp_det['max_limit'];
          }
          else {
            $default_det = db_fetch_array(db_query("SELECT * FROM {uc_deliverytimeslot_default} WHERE day = '%s' AND sid = %d", date('l', $timestamps), $sid));
            $max = $default_det['max_limit'];
          }
          if (!$max || $max == 0) {
            $class = 'na';
          }
          elseif (($booked_num >= $max) && $checked == '') {
            $class = 'full';
          }
          else {
            $data = '<input type="radio" class="form-radio" value="'. $value .'" name="panes[deliverytimeslot][delivery_timeslot]" id="edit-panes-deliverytimeslot-delivery-timeslot-'. $value .'" '. $checked .'/>';
          }
          $row[] = array('data' => $data, 'class' => $class);
        }
      }
      else {
        $disp++;
      }
    $rows[] = $row;
    }
  }
  // main delivery table
  $output = theme('table', $headers, $rows, array('class' => 'delivery', 'id' => 'deliverytimeslot'));
  // legend table
  $row_legend[] = array('data' => t("n/a"), 'class' => 'na');
  $row_legend[] = array('data' => t("full"), 'class' => 'full');
  $row_legend[] = array('data' => t("free"), 'class' => 'free');
  $rows_legend[] = $row_legend;
  $headers_legend[] = array('data' => t("legend"), 'colspan' => 3);
  $output .= theme('table', $headers_legend, $rows_legend, array('class' => 'delivery'));

  return $output;
}

/**
 * Handle delivery date and time on order pane
 */
function uc_order_pane_deliverytimeslot($op, $arg1) {

  switch ($op) {
    case 'view':
    case 'customer':
      if (!isset($arg1->deliverytimeslot['delivery_day']) || !isset($arg1->deliverytimeslot['delivery_sid'])) {
        $date = t('No delivery date specified');
      }
      else {
        $date = $arg1->deliverytimeslot['delivery_day'];
        $date = uc_date_format(date('m', $date), date('d', $date), date('Y', $date));
        $timeslot = _uc_deliverytimeslot_timeslot();
        $time = $timeslot[$arg1->deliverytimeslot['delivery_sid']];
      }
      return $date .'<br/>'. check_plain($time);

    case 'edit-form':
      $time_slot = _uc_deliverytimeslot_timeslot();

      $form['deliverytimeslot']['delivery_day'] = array(
        '#type' => 'date',
        '#title' => t('Delivery date'),
        '#default_value' => array(
          'month' => date("n", $arg1->deliverytimeslot['delivery_day']),
          'day' => date("j", $arg1->deliverytimeslot['delivery_day']),
          'year' => date("Y", $arg1->deliverytimeslot['delivery_day']),
          ),
        );
      $form['deliverytimeslot']['delivery_sid'] = array(
          '#type' => 'select',
          '#title' => t('Delivery timeslot'),
          '#options' => $time_slot,
          '#default_value' => $arg1->deliverytimeslot['delivery_sid'],
        );
      return $form;

    case 'edit-theme':
      return drupal_render($arg1['deliverytimeslot']);

    case 'edit-process':
      foreach ($arg1 as $key => $value) {
        if ($key == 'delivery_day') {
          $changes['deliverytimeslot'][$key] = _uc_deliverytimeslot_date($value);
        }
        if ($key == 'delivery_sid') {
          $changes['deliverytimeslot'][$key] = $value;
        }
      }
      return $changes;
  }
}

/**
 * return week days
 */
function _uc_deliverytimeslot_week_days() {
  $week_days = array(
    'Sunday' => t('Sunday'),
    'Monday' => t('Monday'),
    'Tuesday' => t('Tuesday'),
    'Wednesday' => t('Wednesday'),
    'Thursday' => t('Thursday'),
    'Friday' => t('Friday'),
    'Saturday' => t('Saturday'),
  );
  return $week_days;
}

/**
 * return time slot
 */
function _uc_deliverytimeslot_timeslot($array = TRUE) {
  $deliverytimeslot_timeslot = variable_get('uc_deliverytimeslot_timeslot', '');
  if ($deliverytimeslot_timeslot == '') {
    $deliverytimeslot_timeslot = array(
      '8:00-10:00',
      '10:00-12:00',
      '12:00-14:00',
      '14:00-16:00',
      '16:00-18:00',
      '18:00-20:00',
      '20:00-22:00',
    );
  }
  else {
    if (!is_array($deliverytimeslot_timeslot)) {
      $deliverytimeslot_timeslot = explode("\n", $deliverytimeslot_timeslot);
    }
  }
  // no empty line
  $deliverytimeslot_timeslot = array_filter($deliverytimeslot_timeslot);
  if ($array) {
    return $deliverytimeslot_timeslot;
  }
  else {
    return implode("\n", $deliverytimeslot_timeslot);
  }
}

/**
 * date helper
 */
function _uc_deliverytimeslot_date($date, $day = 0) {
  if (is_array($date) && isset($date['day'])) {
    $output = mktime(0, 0, 0, $date['month'], $date['day'] + $day, $date['year']);
  }
  elseif ($date) {
    $output = array('day' => date("d", $date), 'month' => date("m", $date), 'year' => date("Y", $date));
  }
  else {
    $output = mktime(0, 0, 0, date("m"), date("d") + $day, date("Y"));
  }
  return $output;
}
