// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Some general utility functions
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Written by Matthew Strawbridge
// matthew [@] philoxenic.com
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Copyright 2004
// UltraThin Military Ribbons

// ======================= START OF THIRD-PARTY CODE =======================
// Taken from http://www.faqts.com/knowledge_base/view.phtml/aid/6231
//
// --------------------------------------------------------------------------
// Clones an object
//
// @param deep  true if a deep copy is required (i.e. if all of the
//              subcomponents are also to be cloned),
//              false if a shallow copy is required (i.e. all of the
//              subcomponents of the clone point at the subcomponents of
//              the original object).
// --------------------------------------------------------------------------
function clone(deep) {
   var objectClone = new this.constructor();
   for (var property in this)
      if (!deep)
         objectClone[property] = this[property];
      else if (typeof this[property] == 'object')
         objectClone[property] = this[property].clone(deep);
      else
         objectClone[property] = this[property];
   return objectClone;
}

// Allow you to call myObject.clone()
Object.prototype.clone = clone;
// ======================== END OF THIRD-PARTY CODE ========================


// --------------------------------------------------------------------------
// Helper function for debugging - show all of the attributes of an object
// --------------------------------------------------------------------------
function inspect(obj) {
   var str = '';
   for (var property in obj)
      str = str + property + ':' + obj[property] + '\n';
   alert(str);
}


// --------------------------------------------------------------------------
// Return a copy of all or part of an existing array
//
// @param array  source array to copy from
// @param start_index  index of the first element to copy
// @param length       length of portion to copy
// @param deep         is this a deep copy? TRUE by default
//
// Note that both start_index and length are optional
// --------------------------------------------------------------------------
function copy_of_array(array, start_index, length, deep) {
   if (start_index == undefined) start_index = 0;
   if (length == undefined) length = array.length - start_index;
   if (deep == undefined) deep = true;
   var newArray = new Array(length);
   for (sourcei = start_index, targeti = 0; sourcei < start_index + length; sourcei++, targeti++) {
      if (typeof array[sourcei] == 'object') {
         newArray[targeti] = array[sourcei].clone(deep); // note deep copy  - see clone()
      }
      else {
         // Some simple type
         newArray[targeti] = array[sourcei];
      }
   }
   return newArray;
}


// --------------------------------------------------------------------------
// Return a new array consisting of the original array with
// the extra element added to the end
// Note that this function should only be used if a copy
// of the array is really needed, since array[array.length] = element
// can be used to dynamically add to an existing array.
//
// @param array
// @param element
// @param position  optional index at which to add the element (defaults to
//                  adding it to the end of the array)
// --------------------------------------------------------------------------
function add_to_array(array, element, position) {
   var newArray = null;
   if (array == null) {
      newArray = new Array(1);
      newArray[0] = element;
   }
   else {
      if (position == undefined) position = array.length;
      newArray = new Array(array.length + 1);
      var i = 0;
      for (; i < position; i++) {
         newArray[i] = array[i];
      }
      newArray[i] = element;
      for (j = i; j < array.length; j++) {
         newArray[j + 1] = array[j];
      }
   }
   return newArray;
}


// --------------------------------------------------------------------------
// Insert an element into the middle of an existing array, at the specified
// 0-based index, without specifically creating a new array.
// --------------------------------------------------------------------------
function insert_element_into_array(array, element, index) {
   // shuffle everything after the index to the right
   for (r = array.length; r > index; r--) {
      array[r] = array[r - 1];
   }
   array[index] = element;
}


// --------------------------------------------------------------------------
// Takes a float or integer parameter, and returns a string representing
// that number to 2 decimal places. Typically for formatting currencies.
//
// @param num  number to convert to 2 decimal places
// --------------------------------------------------------------------------
function two_dp(num) {
   // Use Math.round to fix any rounding problems
   var cents = Math.round(num * 100);
   if (cents % 100 == 0) return ('' + (cents / 100) + '.00');
   if (cents % 10 == 0) return ('' + (cents / 100) + '0');
   return '' + cents / 100;
}


// --------------------------------------------------------------------------
// Set the value of a drop-down
//
// @param selection  name of the element to reset
// @param value      value to select
// --------------------------------------------------------------------------
function set_selection_value(selection, value) {
   var ob = document.getElementById(selection);
   ob.value = value;
}


// --------------------------------------------------------------------------
// Finds the HTML form element from its id, and returns its numerical
// value. Returns 0 if the control is not an integer.
//
// @param control_id  id of the control to return a value for
// --------------------------------------------------------------------------
function get_integer_value_of(control_id) {
   var theelement = document.getElementById(control_id);
   if (theelement == undefined) alert("theelement is undefined for " + control_id);
   if (theelement == null) alert("theelement is null for " + control_id);
   var value = parseInt(theelement.value);
   if (isNaN(value)) value = 0;
   return value;
}
