<?php

/**
 * @file
 * Shipping quote module that defines a flat shipping rate for each product.
 */


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

  $items['admin/store/settings/quotes/methods/flatrate/add'] = array(
    'title' => 'Add flat rate quote',
    'description' => 'Create a new flat rate shipping quote.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_flatrate_admin_method_edit_form'),
    'access arguments' => array('configure quotes'),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'uc_flatrate.admin.inc',
  );
  $items['admin/store/settings/quotes/methods/flatrate/%'] = array(
    'title' => 'Edit flat rate method',
    'description' => 'Edit an existing flat rate shipping quote.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_flatrate_admin_method_edit_form', 6),
    'access arguments' => array('configure quotes'),
    'file' => 'uc_flatrate.admin.inc',
  );
  $items['admin/store/settings/quotes/flatrate/%/delete'] = array(
    'title' => 'Delete flat rate method',
    'description' => 'Delete a flat rate shipping quote.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('uc_flatrate_admin_method_confirm_delete', 5),
    'access arguments' => array('configure quotes'),
    'file' => 'uc_flatrate.admin.inc',
  );

  return $items;
}

/**
 * Implements hook_form_alter().
 *
 * Adds a form element for the shipping rate of a product.
 */
function uc_flatrate_form_alter(&$form, &$form_state, $form_id) {
  if (uc_product_is_product_form($form)) {
    $weight = variable_get('uc_quote_method_weight', array());
    $result = db_query("SELECT mid, title, product_rate FROM {uc_flatrate_methods}");
    foreach ($result as $method) {
      // Ensure default weight is set.
      $weight += array('flatrate_' . $method->mid => 0);

      if (!isset($form['shipping']['flatrate'])) {
        $form['shipping']['flatrate'] = array(
          '#type' => 'fieldset',
          '#title' => t('Flat shipping rates'),
          '#description' => t("Overrides the default shipping rate per product for each flat rate shipping method. Leave field empty to use the method's default value."),
          '#tree' => TRUE,
          '#collapsible' => TRUE,
          '#collapsed' => FALSE,
          '#weight' => 0,
        );
      }
      $form['shipping']['flatrate'][$method->mid] = array(
        '#type' => 'uc_price',
        '#title' => check_plain($method->title),
        '#default_value' => isset($form['#node']->flatrate[$method->mid]) ? $form['#node']->flatrate[$method->mid] : '',
        '#description' => t('Default rate: %price', array('%price' => uc_currency_format($method->product_rate))),
        '#weight' => $weight['flatrate_' . $method->mid],
        '#empty_zero' => FALSE,
      );
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function uc_flatrate_node_insert($node) {
  uc_flatrate_node_update($node);
}

/**
 * Implements hook_node_update().
 */
function uc_flatrate_node_update($node) {
  if (uc_product_is_product($node->type)) {
    if (isset($node->flatrate) && is_array($node->flatrate)) {
      if (empty($node->revision)) {
        db_delete('uc_flatrate_products')
          ->condition('vid', $node->vid)
          ->execute();
      }

      $query = db_insert('uc_flatrate_products')
        ->fields(array('vid', 'nid', 'mid', 'rate'));

      foreach ($node->flatrate as $mid => $rate) {
        if (is_numeric($rate) && $rate >= 0) {
          $query->values(array(
              'vid' => $node->vid,
              'nid' => $node->nid,
              'mid' => $mid,
              'rate' => $rate,
            ));
        }
      }

      $query->execute();
    }
  }
}

/**
 * Implements hook_node_load().
 */
function uc_flatrate_node_load($nodes, $types) {
  $vids = array();
  $product_types = uc_product_types();

  foreach ($nodes as &$node) {
    if (in_array($node->type, $product_types)) {
      $vids[$node->nid] = $node->vid;
    }
  }

  if ($vids) {
    $result = db_query("SELECT nid, mid, rate FROM {uc_flatrate_products} WHERE vid IN (:vids)", array(':vids' => $vids));
    foreach ($result as $method) {
      $nodes[$method->nid]->flatrate[$method->mid] = $method->rate;
    }
  }
}

/**
 * Implements hook_node_delete().
 */
function uc_flatrate_node_delete($node) {
  db_delete('uc_flatrate_products')
    ->condition('nid', $node->nid)
    ->execute();
}

/**
 * Implements hook_node_revision_delete().
 */
function uc_flatrate_node_revision_delete($node) {
  db_delete('uc_flatrate_products')
    ->condition('vid', $node->vid)
    ->execute();
}

/**
 * Implements hook_uc_shipping_method().
 */
function uc_flatrate_uc_shipping_method() {
  $methods = array();

  $result = db_query("SELECT mid, title, label, base_rate, product_rate FROM {uc_flatrate_methods}");
  foreach ($result as $method) {
    $methods['flatrate_' . $method->mid] = array(
      'id' => 'flatrate_' . $method->mid,
      'module' => 'uc_flatrate',
      'title' => $method->title,
      'description' => t('!base_rate + !product_rate per item', array('!base_rate' => uc_currency_format($method->base_rate), '!product_rate' => uc_currency_format($method->product_rate))),
      'operations' => array(
        'edit' => array(
          'title' => t('edit'),
          'href' => 'admin/store/settings/quotes/methods/flatrate/' . $method->mid,
        ),
        'delete' => array(
          'title' => t('delete'),
          'href' => 'admin/store/settings/quotes/flatrate/' . $method->mid . '/delete',
        ),
      ),
      'quote' => array(
        'type' => 'order',
        'callback' => 'uc_flatrate_quote',
        'accessorials' => array(
          $method->label,
        ),
      ),
      'enabled' => TRUE,
    );
  }

  return $methods;
}

/**
 * Standard callback to return a shipping rate via the flat rate method.
 *
 * @param $products
 *   The order's products.
 * @param $details
 *   Other order details including a shipping address.
 * @param $method
 *   The shipping method to use to create the quote.
 *
 * @return
 *   An array containing the shipping quote for the order.
 */
function uc_flatrate_quote($products, $details, $method) {
  $method = explode('_', $method['id']);
  $mid = $method[1];

  if ($method = db_query("SELECT * FROM {uc_flatrate_methods} WHERE mid = :mid", array(':mid' => $mid))->fetchObject()) {
    // Start at the base rate.
    $rate = $method->base_rate;

    foreach ($products as $product) {
      if (!isset($product->flatrate[$mid])) {
        // Add the method's default product rate.
        $rate += $method->product_rate * $product->qty;
      }
      else {
        // Add the product-specific rate.
        $rate += $product->flatrate[$mid] * $product->qty;
      }
    }

    $quotes[] = array(
      'rate' => $rate,
      'label' => check_plain($method->label),
      'option_label' => check_plain($method->label),
    );
  }

  return $quotes;
}
