/**
 * Route info calculator scripts.
 *
 * @requires add.js|view.js
 */
// TODO: Refactor this into a separate class/object?
// Any need to standardize the rounding precision? (2-digits?)

/**
 * Distance units in use.
 */
var distanceUnits = runtrackr.DISTANCE_UNITS.km;

/**
 * Weight units in use.
 */
var weightUnits = runtrackr.WEIGHT_UNITS.lbs;

// Run when the DOM is ready.
jQuery(document).ready(function()
{
  // Event handlers for taking other route data, such as user weight, etc.
  jQuery('.weight .value').click(showWeightInput);
  jQuery('.weight .submit').click(setWeight);

  // TODO: Okay for a closure here?
  jQuery('.weight .input').keydown(function(e)
  {
    // TODO: Change this to a 'checkEnterKeyPress' method that accepts a
    // function signature and then executes it if keyCode == 13.
    // TODO: Allow ESC to Cancel.

    // Using keydown event because keypress event seems to pass in
    // unpredictable keyCode values.
    if (13 == e.keyCode)
    {
      setWeight(e);
    }
  });
});

/**
 * Holds all the functions used to update route info on screen.
 */
var updateInfo = {};

/**
 * Updates the distance on screen.
 */
updateInfo.distance = function()
{
  // Output distance in the correct units.
  var distanceKms = routeMap.getRouteDistance();
  var distance;
  if (distanceUnits == runtrackr.DISTANCE_UNITS.miles)
  {
    distance = distanceKms / runtrackr.DISTANCE_UNITS.CONVERSIONS.MILES_TO_KMS;
  }
  else
  {
    distance = distanceKms;
  }
  jQuery('.distance .value').text(distance.toFixed(2));

  // TODO: This is a quick fix to get miles to display as well... remove once
  // have user-specific setting. (Make miles default)
  jQuery('.distance .miles.value').text((distanceKms/runtrackr.DISTANCE_UNITS.CONVERSIONS.MILES_TO_KMS).toFixed(2));
}

/**
 * Updates the calories on screen.
 */
updateInfo.calories = function()
{
  // Calculate calories based on user weight and distance ran.
  var distanceKms = routeMap.getRouteDistance();
  var weight = parseFloat(jQuery('.weight .value').html())
  var calories;
  if (!isNaN(weight))
  {
    // Make sure weight is in kgs.
    if (weightUnits == runtrackr.WEIGHT_UNITS.lbs)
    {
      weight = weight * runtrackr.WEIGHT_UNITS.CONVERSIONS.LBS_TO_KGS;
    }
    calories = runtrackr.Utility.calcCalories(weight, distanceKms);
  }
  else
  {
    calories = 0;
  }
  jQuery('.calories .value').html(calories.toFixed(2));
}

/**
 * Event handler to show input field for a user's weight.
 */
function showWeightInput(e)
{
  // Prevent default action if triggered by event.
  if (e && e.preventDefault)
    e.preventDefault();

  // Show the input field, focus it and hide the display/value.
  jQuery('.weight .input-fields').show();
  jQuery('.weight .input').focus().val(jQuery('.weight .value').html());
  jQuery('.weight .value').hide();
}

// TODO: Should changing the weight in the JS form here update the weight in
// the user's profile? (If user logged in)
/**
 * Event handler to set the weight used in calculations by retrieving the input
 * value from the DOM.
 */
function setWeight(e)
{
  // Prevent default action if triggered by event.
  if (e && e.preventDefault)
    e.preventDefault();

  try
  {
    var weight = getNumericValueFromDomInput('.weight .input');

    // TODO: Messy! Should be part of another function...
    if (weight <= 0)
    {
      throw new RangeError('Weight must be a positive value.');
    }

    // Set the weight, show it, hide the input and update on-screen data.  Note
    // that the displayed value of the weight *is* the value used in
    // calculations. (Value is obtained from the DOM)
    jQuery('.weight .value').html(weight.toFixed(0)).show();
    jQuery('.weight .input-fields').hide();

    updateInfo.calories();
  }
  catch (ex)
  {
    // Notify of the problem and re-focus the input field.
    window.alert(ex.message);
    jQuery('.weight .input').focus();
  }
}

/**
 * Attempts to retrieve a numeric value from a DOM element that is an input.
 *
 * If the value entered cannot be parsed or is invalid an exception is thrown.
 *
 * @param String path the jQuery selector of the DOM element that is the input.
 * @return Number the value from the DOM element input.
 * @throws TypeError if the input value is not a valid number.
 * @throws RangeError if the input value is not a positive number.
 */
function getNumericValueFromDomInput(path)
{
  // TODO: What happens when field is blank?
  var value = parseFloat(jQuery(path).val());
  if (isNaN(value))
  {
    throw new TypeError('Must be a numeric value.');
  }
  return value;
}
