<?php
// $Id: address.module,v 1.42.2.11.2.11 2007/03/01 13:24:10 gordon Exp $

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

/**
 * Implementation of hook_help()
 */
function address_help($section = 'admin/help#address') {
  switch ($section) {
    case 'admin/modules#description':
      return t('<b>EC:</b> Enable address books for users.');
  }
}

/**
 * Implementation of menu_hook()
 */
function address_menu($may_cache) {
  global $user;
  $uid = $user->uid;
  $items = array();

  if ($may_cache) {
  }
  else {
    if (arg(0) == 'user') {
      if (user_access('administer users')) {
        $uid = arg(1);
      }
      if ($uid) {
        $items[] = array(
          'path' => "user/$uid/address",
          'title' => t('address book'),
          'callback' => 'address_page',
          'access' => TRUE,
          'type' => MENU_LOCAL_TASK,
          'weight' => 1,
        );
      }
    }
  }

  return $items;
}

/**
 * Implementation of hook_user()
 */
function address_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'view':
      if (user_access('create invoice') && module_exist('invoice')) {
        if ($invoice = invoice_get($account->uid)) {
          $output.= l(t('edit pending invoice'), "admin/store/invoice/{$account->uid}/edit");
        }
        else {
          $output.= l(t('create invoice'), "admin/store/invoice/add/{$account->uid}");
        }
        $items[] = array(
          'value' => $output,
        );
        return array(t('Invoice') => $items);
      }
      break;
  }
}

/**
 * Implementation of hook_checkoutapi().
 */
function address_checkoutapi(&$txn, $op, $post_op = NULL, $arg4 = NULL) {
  global $user;
  if ($txn == 'address') return TRUE;
  $output = '';

  switch ($op) {
    case 'form':
      if ($txn->shippable) {
        drupal_set_title(t('Choose a shipping and billing address'));
      }
      else {
        drupal_set_title(t('Choose a billing address'));
      }
      $form = address_checkout_form($txn);
      $form[] = array('#type' => 'submit', '#default_value' => t('Continue')); 
      return $form;
      
    case 'validate' :
      if ($txn->uid > 0) {
        if ($txn->shippable && !$txn->shipping_address) {
          form_set_error('shipping_address', t('You need to select a shipping address.'));        
        }
        if (!$txn->billing_address) {
          form_set_error('billing_address', t('You need to select a billing address.'));
        }
      }
      break;

    case 'save':
      if ($txn->uid > 0) {
        $txn->address['shipping'] = address_get_address($txn->shipping_address ? $txn->shipping_address : $txn->billing_address);

        $txn->address['billing'] = address_get_address($txn->billing_address);
      }
      else {
        $txn->address['billing'] = (object)$txn->address['billing'];
        if ($txn->address['shipping']) {
          $txn->address['shipping'] = (object)$txn->address['shipping'];
        }
      }
      $txn->screen++;
      break;

    case 'review':
      if ($txn->shippable) {
        $form['title'] = array( '#value' => t('Shipping and billing address') );
        $form['shipping_address'] = array( '#value' => store_format_address($txn,'shipping','html') );
      }
      else {
        $form['title'] = array( '#value' => t('Billing address') );
      }
      $form['billing_address'] = array( '#value' =>  store_format_address($txn,'billing','html') );
      return $form;
  }
}

/**
 * Themes the address form elements on the checkout review page 
 */
function theme_address_review_form($form) {
  $output = '';
  $screens = checkout_get_screens();
  $screen = array_search('address', $screens);
  if (isset($form['shipping_address'])) {
    $output .= '<div class="address-shipping"><strong>' . t('Ship to:') . '</strong> ' 
      . l(t('(change)'), 'cart/checkout', array(), "op={$screen}&". drupal_get_destination()) . '<br />' . form_render($form['shipping_address']) . '</div>';
  }
  $output .= '<div class="address-billing"><strong>' . t('Billing to:') . '</strong> ' 
    . l(t('(change)'), 'cart/checkout', array(), "op={$screen}&". drupal_get_destination()) . '<br />' . form_render($form['billing_address']) . '</div>';

  return theme('box', form_render($form['title']), $output);
}

/**
 * Implementation of hook_invoiceapi()
 */
function address_invoiceapi(&$invoice, $op) {
  if (is_string($invoice) && $op == 'form') { 
    return t('address');
  }

  switch ($op) {
    case 'create':
      $invoice->uid = $invoice->invoice_id;
      $account = user_load(array('uid' => $invoice->uid));
      $invoice->address['billing']->firstname = $account->name;
      break;

    case 'form':
      return address_checkoutapi($invoice, 'form');
      break;

    case 'validate':
      return address_checkoutapi($invoice, 'validate');
      break;

    case 'submit':
      return address_checkoutapi($invoice, 'save');
      break;

    case 'post_update':
      break;

    case 'review':
      if (!$invoice->address['billing'] || ($invoice->shippable && !$invoice->address['shipping'])) {
        drupal_goto('admin/store/invoice/'. arg(3) .'/edit/address');
      }

      $form = address_checkoutapi($invoice, 'review');
      $form['#theme'] = 'address_review_form';
      return $form;
      break;
  }
}

/**
 * The form to set the shipping and billing address in the checkout procedure.
 */
function address_checkout_form($txn) {
  global $user;

  /* Configure the how to render addresss info */
  if ($txn->uid > 0) {

    /* Grab the user's addressbook */
    $address = address_get_addresses($txn->uid);

    if (empty($address)) {
      drupal_set_message(t('There are no addresses in your addressbook.  Please add a shipping/delivery address now.'));
      drupal_goto('user/'. $txn->uid. '/address/add', drupal_get_destination());
    }

    // Build address options
    $options = array();
    foreach ($address as $value) {
      $options[$value->aid] = t('%firstname %lastname, %street in %city',
        array(
          '%firstname' => $value->firstname,
          '%lastname' => $value->lastname,
          '%street' => $value->street1,
          '%city' => $value->city,
        ));
    }
    if ($txn->shippable) {
      $form['shipping_address'] = array(
        '#type' => 'select',
        '#title' => t('Shipping to'),
        '#default_value' => $txn->shipping_address,
        '#options' => $options,
        '#description' => t('Please choose where you would like the items to be delivered. You can also <a href="%add_address">add a new address</a>.', array('%add_address' => url("user/$txn->uid/address/add", drupal_get_destination()))),
      );
    }
    $form['billing_address'] = array(
      '#type' => 'select',
      '#title' => t('Billing to'),
      '#default_value' => $txn->billing_address,
      '#options' => $options,
      '#description' => t('Please choose where you would like the invoice to be sent. You can also <a href="%add_address">add a new address</a>.', array('%add_address' => url("user/$txn->uid/address/add", drupal_get_destination()))),
    );
  }
  else {

    /* Don't use the addressbook if the user can buy anonymously */
    $form['address']['billing'] = store_address_form($txn->address['billing']);
    $form['address']['billing']['firstname']['#required'] = TRUE;
    $form['address']['billing']['lastname']['#required'] = TRUE;
    if ($txn->shippable) {
      $form['address']['billing']['#type'] = 'fieldset';
      $form['address']['billing']['#title'] = t('Billing address');
      $form['address']['shipping'] = store_address_form($txn->address['shipping']);
      $form['address']['shipping']['#type'] = 'fieldset';
      $form['address']['shipping']['#title'] = t('Shipping address');
    }
  }

  $form['address']['#tree'] = TRUE;
  return $form;
}

/**
 * The controller for managing addresses.  Callback happens via menu().
 */
function address_page($action = null, $aid = null) {
  global $user;
  $uid = $user->uid;
  $access = user_access('administer users');
  if ($access) {
    $uid = arg(1);
  }
  $name = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid));
  drupal_set_title(t('%username\'s - address book', array('%username' => check_plain($name))));

  $output = t('<p>Your address book is used to save addresses for billing and shipping of items from our store.</p>');

  switch ($action) {
    case 'add':
    case 'edit':
      $edit = $aid && !$edit ? address_load($aid) : array();
      if (!$edit) {
        $edit['uid'] = $uid;
      }
      elseif (!$access && $edit['uid'] != $uid) {
        return drupal_access_denied();
      } 
      $output .= address_form($edit);
      break;

    case 'delete':
      address_delete($aid);
      drupal_goto("user/$uid/address");
      break;

    default:
      $output .= theme('address_overview');
  }

  return $output;
}

function address_load($aid) {
  return db_fetch_array(db_query('SELECT * FROM {ec_address} WHERE aid = %d', $aid));
}

function address_fields() {
  static $fields;

  if (!$fields) {
    $result = db_query('SELECT * FROM {ec_address} WHERE aid = 1');
    if (db_num_rows($result)) {
      $fields = array_keys(db_fetch_array($result));
    }
    if (!$fields) {
      // Make sure we return the default fields at least
      $fields = array('aid', 'uid', 'firstname', 'lastname', 'street1', 'street2', 'zip', 'city', 'state', 'country', 'phone');
    }
  }

  return $fields;
}

function address_form($edit = array()) {
  $form = address_form_fields($edit);
  if ($edit['aid']) {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Update address')
      );
  }
  else {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Create new address')
    );
  }

  drupal_add_js(drupal_get_path('module', 'address') .'/address.js');
  return drupal_get_form('address', $form);
}

function address_form_fields($edit = array()) {
  if (is_numeric($edit['country'])) {
    // alert users with old-style addresses
    drupal_set_message(t('<strong>Please update your <em>country</em> and <em>state/province</em></strong>.<br />We apologize for the inconvenience.'));
  }
  else if (!$edit['province']) {
    $edit['province'] = $edit['state'];
  }
  $countries = store_build_countries();
  array_unshift($countries, t('Please choose...'));
  $country = ($edit['country'] ? $edit['country'] : variable_get('ec_country', 0));
  $form['country'] = array(
    '#type' => 'select',
    '#title' => t('Country'),
    '#default_value' => $country,
    '#options' => $countries,
    '#description' => null,
    '#multiple' => false,
    '#required' => true,
    '#attributes' => array('onChange' => 'provORstate(this.options[this.selectedIndex].value)')
  );
  $form['firstname'] = array(
    '#type' => 'textfield',
    '#title' => t('First Name'),
    '#default_value' => $edit['firstname'],
    '#size' => 50,
    '#maxlength' => 75,
    '#description' => null,
    '#attributes' => null,
    '#required' => true,
  );
  $form['lastname'] = array(
    '#type' => 'textfield',
    '#title' => t('Last Name'),
    '#default_value' => $edit['lastname'],
    '#size' => 50,
    '#maxlength' => 75,
    '#description' => null,
    '#attributes' => null,
    '#required' => true,
  );
  $form['street1'] = array(
    '#type' => 'textfield',
    '#title' => t('Address Line 1'),
    '#default_value' => $edit['street1'],
    '#size' => 50,
    '#maxlength' => 75,
    '#description' => null,
    '#attributes' => null,
    '#required' => true,
  );
  $form['street2'] = array(
    '#type' => 'textfield',
    '#title' => t('Address Line 2'),
    '#default_value' => $edit['street2'],
    '#size' => 50,
    '#maxlength' => 75,
    '#description' => null,
    '#attributes' => null,
    '#required' => false,
  );
  $form['city'] = array(
    '#type' => 'textfield',
    '#title' => t('City'),
    '#default_value' => $edit['city'],
    '#size' => 30,
    '#maxlength' => 64,
    '#description' => null,
    '#attributes' => null,
    '#required' => true,
  );
  $states = store_build_states($country);
  array_unshift($states, t('Please choose...'));
  $form['state'] = array(
    '#type' => 'select',
    '#title' => t('State'),
    '#default_value' => $edit['state'],
    '#options' => $states,
    '#description' => null,
    '#extra' => null,
    '#multiple' => false,
    //'#required' => isset($_POST['province']),
  );
  $form['province'] = array(
    '#type' => 'textfield',
    '#title' => t('Province / Region'),
    '#default_value' => $edit['province'],
    '#size' => 30,
    '#maxlength' => 64,
    '#description' => null,
    '#attributes' => null,
    //'#required' => isset($_POST['state']),
  );
  $form['zip'] = array(
    '#type' => 'textfield',
    '#title' => t('Zip / Postal Code'),
    '#default_value' => $edit['zip'],
    '#size' => 20,
    '#maxlength' => 20,
    '#description' => null,
    '#attributes' => null,
    '#required' => true,
  );
  $form['phone'] = array(
    '#type' => 'textfield',
    '#title' => t('Phone Number'),
    '#default_value' => $edit['phone'],
    '#size' => 50,
    '#maxlength' => 100,
    '#description' => null,
    '#attributes' => null,
    '#required' => false,
  );

  if ($edit['aid']) {
    $form['aid'] = array('#type' => 'value', '#value' => $edit['aid']);
  }
  if ($edit['uid']) {
    $form['uid'] = array('#type' => 'value', '#value' => $edit['uid']);
  }

  return $form;
}

function theme_address_overview() {
  global $user;
  $uid = $user->uid;

  if (user_access('administer users')) {
    $uid = arg(1);
  }

  $output = "<p>". l(t('Click here to add a new address'), "user/$uid/address/add") .'.</p>';

  $header = array(t('address'), t('options'));
  $address = address_get_addresses($uid);
  foreach($address as $data) {
    $addr = array();
    $addr[] = check_plain($data->firstname). ' '. check_plain($data->lastname);
    $addr[] = check_plain($data->street1);
    $addr[] = ($data->street2) ? check_plain($data->street2) : "";
    $addr[] = check_plain($data->city). ', '. check_plain($data->state). ' '. check_plain($data->zip);
    $addr[] = store_get_country(check_plain($data->country));
    $addr[] = ($data->phone) ? t('tel: %phone', array('%phone' => check_plain($data->phone))) : '';
    foreach ($addr as $k => $v) {
      if (!$v) unset($addr[$k]);
    }
    $row[] = array(implode('<br />', $addr), l(t('edit'), "user/$uid/address/edit/$data->aid"). " / ". l(t("delete"), "user/$uid/address/delete/$data->aid"));
  }

  return $output . theme('table', $header, $row);
}

function address_get_addresses($uid = null) {
  global $user;
  $address = array();

  $result = db_query('SELECT * FROM {ec_address} WHERE uid = %d', ($uid) ? $uid : $user->uid);
  while($data = db_fetch_object($result)) {
    $address[] = $data;
  }

  return $address;
}

function address_get_address($aid) {
  return db_fetch_object(db_query('SELECT * FROM {ec_address} WHERE aid = %d', $aid));
}

/**
 * Validate an address being saved
 */
function address_validate($form_id, $form_values) {
  if ( variable_get('store_ignore_state', FALSE)) {
    return;
  }
  if (!$form_values['province'] && !$form_values['state']) {
    form_set_error('state', t('Please enter a state/province/region.'));
    form_set_error('province', '');
  }
}

function address_submit($form_id, $form_values) {
  address_save($form_values);
  return "user/{$form_values['uid']}/address";
}

/**
 * Format an address into html
 *
 * @param $data
 *   Object containing users address information
 *   typically obtained with address_get_address()
 * TODO remove and use store_format_address
 */
function address_format_address($data) {
    
  $break = '<br />';
  
  $address .= ucfirst($data->firstname) . ' ' . ucfirst($data->lastname). $break;
  $address .= ($data->street2) ? $data->street1 . $break . $data->street2. $break : $data->street1. $break;
  $address .= ($data->city) ? ucfirst($data->city) . ', ' : '';
  $address .= strtoupper($data->state). " ". $data->zip. $break;
  $address .= store_get_country($data->country). $break;
  $address .= $data->phone. $break . $break;
  
  return $address;
}

function address_save($edit) {
  if (!$edit['state']) {
    $edit['state'] = $edit['province'];
  }
  $aid = $edit['aid'];

  if (!$edit['uid']) {
    global $user;
    $edit['uid'] = $user->uid;
  }
  $fields = address_fields();

  if ($aid) {
    foreach ($edit as $key => $value) {
      if (in_array($key, $fields)) {
        $q[] = db_escape_string($key) ." = '%s'";
        $v[] = $value;
      }
    }
    db_query('UPDATE {ec_address} SET '. implode(', ', $q) ." WHERE aid = $aid", $v);
  }
  else {
    foreach ($edit as $key => $value) {
      if (in_array($key, $fields)) {
        $k[] = db_escape_string($key);
        $v[] = $value;
        $s[] = "'%s'";
      }
    }
    db_query('INSERT INTO {ec_address} ('. implode(', ', $k) .') VALUES('. implode(', ', $s) .')', $v);
  }

  drupal_set_message(t('The address has been saved.'));
}

function address_delete($aid) {
  db_query('DELETE FROM {ec_address} WHERE aid = %d', $aid);
  drupal_set_message(t('The address has been deleted.'));
}
