<?php

/**
 * @file
 * Coupon with fixed amount.
 */

/**
 * Implements hook_commerce_coupon_type_configure().
 */
function commerce_coupon_fixed_amount_commerce_coupon_type_configure($bundle, $reset = FALSE) {
  // Skip all $bundles except the fixed coupon type
  if ($bundle != 'commerce_coupon_fixed') {
    return;
  }

  $entity_type = 'commerce_coupon';

  // If a field type we know should exist isn't found, clear the Field cache.
  if (!field_info_field_types('commerce_price')) {
    field_cache_clear();
  }
  // Look for or add the specified fixed amount
  $field_name = 'commerce_coupon_fixed_amount';
  $field = field_info_field($field_name);
  $instance = field_info_instance($entity_type, $field_name, $bundle);
  $weight = 0;

  if (empty($field) || $reset) {
    $field_data = array(
      'field_name' => $field_name,
      'type' => 'commerce_price',
      'label' => t('Fixed Amount'),
      'cardinality' => 1,
      'entity_types' => array($entity_type),
      'translatable' => FALSE,
      'locked' => FALSE,
    );

    if (empty($field)) {
      $field = field_create_field($field_data);
    }
    else {
      $field = field_update_field($field_data);
    }
  }
  if (empty($instance) || $reset) {
    $instance_data = array(
      'field_name' => $field_name,
      'entity_type' => $entity_type,
      'bundle' => $bundle,
      'label' => t('Fixed Amount'),
      'required' => TRUE,
      'settings' => array(),
      // Because this widget is locked, we need it to use the full price widget
      // since the currency option can't be adjusted at the moment.
      'widget' => array(
        'type' => 'commerce_price_full',
        'weight' => $weight,
        'settings' => array(
          'currency_code' => 'default',
        ),
      ),
      'default_value' => array(
        array(
          'amount' => 0,
          'currency_code' => commerce_default_currency(),
          'data' => array(
            'components' => array(),
          ),
        ),
      ),
      'display' => array(),
    );

    if (empty($instance)) {
      field_create_instance($instance_data);
    }
    else {
      field_update_instance($instance_data);
    }
  }
}

/**
 * Implements hook_commerce_cart_line_item_refresh().
 *
 * Refresh the line item pricing for fixed coupons.
 */
function commerce_coupon_fixed_amount_commerce_cart_line_item_refresh($line_item, $order_wrapper) {
  if ($line_item->type == 'commerce_coupon') {
    $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    $coupon_wrapper = $line_item_wrapper->commerce_coupon_reference;
    $coupon = $coupon_wrapper->value();
    if (!empty($coupon)) {
      if ($coupon->type == 'commerce_coupon_fixed') {

        $amount = commerce_price_wrapper_value($coupon_wrapper, 'commerce_coupon_fixed_amount', TRUE);
        // Get the price component to use in this price.
        $price_component_name = $coupon_wrapper->price_component_name->value();

        // Remove the component type and add it again for this coupon code.
        $line_item_wrapper->commerce_unit_price->data = commerce_price_component_delete($line_item_wrapper->commerce_unit_price->value(), $price_component_name);
        if ($coupon->is_active && !commerce_price_component_load($line_item_wrapper->commerce_unit_price->value(), $price_component_name)) {
          $line_item_wrapper->commerce_unit_price->amount = $amount['amount'] * -1;
          $line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
              $line_item_wrapper->commerce_unit_price->value(), $price_component_name, $line_item_wrapper->commerce_unit_price->value(), TRUE, FALSE
          );
        }
      }
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function commerce_coupon_fixed_amount_form_commerce_order_ui_order_form_alter(&$form, &$form_state, $form_id) {
  $form['#validate'][] = 'commerce_coupon_fixed_amount_form_commerce_order_ui_order_form_validate';
}

/**
 * Validation of coupon codes.
 */
function commerce_coupon_fixed_amount_form_commerce_order_ui_order_form_validate($form, &$form_state) {
  $field = $form_state['field']['commerce_coupon_order_reference'][LANGUAGE_NONE]['field'];
  $items = field_get_items('commerce_order', $form_state['commerce_order'], $field['field_name']);
  $items = _field_filter_items($field, $items);
  $original_order = $form['#entity'];
  $coupon_validation = array();
  foreach ($items as $item) {
    $commerce_coupon = commerce_coupon_load($item['target_id']);
    $commerce_coupon_wrapper = entity_metadata_wrapper('commerce_coupon', $commerce_coupon);
    // Don't allow to apply the same code twice, don't apply any other
    // validation to admins.
    if (commerce_coupon_code_is_in_order($commerce_coupon_wrapper->commerce_coupon_code->raw(), $original_order) && in_array($item['target_id'], $coupon_validation)) {
      form_set_error('commerce_coupon_order_reference', t('Sorry, you can only apply a coupon once per order.'));
    }
    else {
      $coupon_validation[] = $item['target_id'];
    }
  }
}

/**
 * Implements hook_field_attach_submit().
 */
function commerce_coupon_fixed_amount_field_attach_submit($entity_type, $entity, $form, &$form_state) {
  if ($entity_type == 'commerce_order' && isset($form_state['field']['commerce_coupon_order_reference'])) {
    $items = array();
    $instance = $form_state['field']['commerce_coupon_order_reference'][LANGUAGE_NONE]['instance'];
    $field = $form_state['field']['commerce_coupon_order_reference'][LANGUAGE_NONE]['field'];
    field_default_extract_form_values($entity_type, $entity, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state);
    field_default_submit(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state);
    $original_order = $form['#entity'];
    foreach ($items as $item) {
      $commerce_coupon = commerce_coupon_load($item['target_id']);
      $commerce_coupon_wrapper = entity_metadata_wrapper('commerce_coupon', $commerce_coupon);
      // When editing an order, do not try to apply coupons that were already
      // there twice.
      if (!commerce_coupon_code_is_in_order($commerce_coupon_wrapper->commerce_coupon_code->raw(), $original_order)) {
        rules_invoke_event('commerce_coupon_redeem', $commerce_coupon, $form_state['commerce_order']);
      }
    }
  }
}

/**
 * Implements hook_commerce_coupon_granted_amount_alter().
 */
function commerce_coupon_fixed_amount_commerce_coupon_granted_amount_alter(&$amount, $coupon, $order) {
  // Load the fixed amount from the coupon.
  if ($coupon->type == 'commerce_coupon_fixed') {
    $commerce_coupon_wrapper = entity_metadata_wrapper('commerce_coupon', $coupon);
    $price = $commerce_coupon_wrapper->commerce_coupon_fixed_amount->raw();
    $amount = commerce_currency_format($price['amount'], $price['currency_code'], $coupon);
  }
}
