<?php
/**
 * Implements hook_form_FORM_ID_alter().
 *
 * call rules event
 */
function commerce_paypal_ipn_rules_integration_form_commerce_paypal_wps_redirect_form_alter(&$form, &$form_state) {
  // Prepare form data to be passed by reference as ArrayObjects.
  $form_data = new ArrayObject((array)$form);

  $order = $form_state['build_info']['args'][0];

  if ($order) {
    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
    // Forms are passed by reference via the ArrayObject class.
    // Element IDs for the form are appended and passed as arguments. This allows us to
    // use a select list in rules for selecting form elements rather than entering an element ID.
    $args = array(
      "commerce_paypal_ipn_rules_integration_paypal_wps_redirect",
      $order_wrapper,
      $form_data,
    );
    call_user_func_array('rules_invoke_event', $args);
  }

  // Repopulate form arrays to update the form.
  $form = (array) $form_data;
}

function commerce_paypal_ipn_rules_integration_add_subscription_info($form, $item_name, $a3, $p3, $t3) {
  $unit = _translate_period($t3);

  $paypal_fields = array(
    'cmd' =>'_xclick-subscriptions',
    'item_name' => check_plain($item_name),
    'a3' => $a3, //commerce_currency_amount_to_decimal($order_wrapper->commerce_order_total->amount->value(), $order_wrapper->commerce_order_total->currency_code->value()),
    'p3' => $p3, //commerce_sp_paypal_product_get_interval_amount_for_paypal($product_wrapper), // interval
    't3' => $unit, //commerce_sp_paypal_product_get_interval_period_for_paypal($product_wrapper), // unit
    'src' => 1, // Set recurring payments until canceled.
    'sra' => TRUE,
    'no_note' => TRUE,
    'modify' => FALSE,
  );
  foreach ($paypal_fields as $name => $value) {
    if (!empty($value)) {
      $form[$name] = array('#type' => 'hidden', '#value' => $value);
    }
  }
}

function _translate_period($t3) {
  // default is D - day
  $unit = 'D';

  switch ($t3) {
    case 'day':
      $unit = 'D';
      break;
    case 'week':
      $unit = 'W';
      break;
    case 'month':
      $unit = 'M';
      break;
    case 'year':
      $unit = 'Y';
      break;
  }
  return $unit;
}

/**
 * Implements hook_commerce_paypal_ipn_process().
 */
function commerce_paypal_ipn_rules_integration_commerce_paypal_ipn_process($order, $payment_method, $ipn) {
watchdog("DEBUG commerce_paypal_ipn_rules_integration_commerce_paypal_ipn_process", "order=".var_export($order, true));
watchdog("DEBUG commerce_paypal_ipn_rules_integration_commerce_paypal_ipn_process", "payment_method=".var_export($payment_method, true));
watchdog("DEBUG commerce_paypal_ipn_rules_integration_commerce_paypal_ipn_process", "ipn=".var_export($ipn, true));
  $account = user_load($order->uid);

  $payment_status = "";
  if (isset($ipn['payment_status'])) {
    $payment_status = $ipn['payment_status'];
  }
  $txn_type = "";
  if (isset($ipn['txn_type'])) {
    $txn_type = $ipn['txn_type'];
  }
  $ipn_id = "";
  if (isset($ipn['ipn_id'])) {
    $ipn_id = $ipn['ipn_id'];
  }
  $txn_id = "";
  if (isset($ipn['txn_id'])) {
    $txn_id = $ipn['txn_id'];
  }
  $receiver_email = "";
  if (isset($ipn['receiver_email'])) {
    $receiver_email = $ipn['receiver_email'];
  }
  $payer_email = "";
  if (isset($ipn['payer_email'])) {
    $payer_email = $ipn['payer_email'];
  }
  $test_ipn = false;
  if (isset($ipn['test_ipn'])) {
    $test_ipn = $ipn['test_ipn'];
  }

  rules_invoke_event('commerce_paypal_ipn_rules_integration_ipn_process', $order, $payment_method, $txn_type, $account, $ipn_id, $txn_id, $receiver_email, $payer_email, $payment_status, $test_ipn);
}

/**
 * Creates a new order based on the information given in $master_order.
 *
 * Billing address and line items get cloned. 
 *
 * @param $order
 *   The commerce order to clone.
 *
 * @return
 *   The cloned commerce order.
 */
function commerce_paypal_ipn_rules_integration_clone_order($master_order) {
  // Create a new order
  $new_order = commerce_order_new($master_order->uid, 'pending');

  // Clone the billing address.
  $new_order->commerce_customer_billing = $master_order->commerce_customer_billing;

  // Save it so it gets an order ID and return the full object.
  commerce_order_save($new_order);

  // Wrap the order for easy access to field data.
  $new_order_wrapper = entity_metadata_wrapper('commerce_order', $new_order);

  // Wrap the master order for easy access to field data.
  $master_order_wrapper = entity_metadata_wrapper('commerce_order', $master_order);
  foreach ($master_order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
    if ($line_item_wrapper->type->value() == 'product') {
      $new_line_item = commerce_product_line_item_new($line_item_wrapper->commerce_product->value(), $line_item_wrapper->quantity->value(), $new_order->order_id);
    }
    elseif ($line_item_wrapper->type->value() == 'coupon' && function_exists("commerce_coupon_line_item_new")) {
      // We can programatically reuse the coupon and thus ensure the same price.
      $coupon = entity_load_single('commerce_coupon', $line_item_wrapper->commerce_coupon_reference->value());
      if ($coupon) {
        $new_line_item = commerce_coupon_line_item_new($coupon, $new_order->order_id);
      }
    }
    if (isset($new_line_item)) {
      // Ensure the same price on the line items. The order total will always
      // be calculated base on this information.
      $new_line_item->commerce_unit_price = $line_item_wrapper->value()->commerce_unit_price;
      commerce_line_item_save($new_line_item);
      $new_order_wrapper->commerce_line_items[] = $new_line_item;
      unset($new_line_item);
    }
  }
  // Save the updated order.
  commerce_order_save($new_order);

  return $new_order;
}
