function byId(id) {
  return document.getElementById(id);
}

function show(id) {
  byId(id).style.display = 'block';
}

function hide(id) {
  byId(id).style.display = 'none';
}

var MOUNT_TYPES = [
		   {label: "Ceiling", code: "ceiling", price: 0},
		   {label: "Wall Mount - 1 inch", code: "wall1", price: 0},
		   {label: "Wall Mount - 3 inch", code: "wall3", price: 0},
		   {label: "Wall Mount - 5.5 inch", code: "wall55", price: 0}
		   ];

//The following two variables are filled in by parseWorksheetData.

// Codes for the different track sizes/duties.
var codes = [];
// Table of objects indexed by duty code name. These provide convenient
// access to the values specified in the spreadsheet.
var parts = {};

var FLOAT_RE = /^[-+]?(0\.[0-9]*|[1-9][0-9]*\.?[0-9]*|\.[0-9]+)$/;
function isFloat(string) {
  return FLOAT_RE.test(string);
}

// Map from mount code name to wall mount description for display purposes.
var MOUNT_DESCRIPTIONS_BY_CODE = {'ceiling': '', 'wall1': '1 in.', 'wall3': '3 in.', 'wall55': '5.5 in.'};

// Keys into the parts objects. These should correspond to the
// row names given in the spreadsheet.
var NAME = 'Name';
var ROLL_LEN = 'Roll length';
var MIN_TRACK_LEN = 'Min track length';
var TRACK_COST = 'Track cost/ft';
var ROLLER_COST = 'Roller cost';
var END_CAP_COST = 'End cap cost';
var CEILING_MT_CARTRIDGE_COST = 'Ceiling mount cartridge cost';
var WALL_MT_BRACKET_COST = 'Wall mount bracket cost';
var DBL_TRACK_CARTRIDGE_COST = 'Double track cartridge cost';
var VALANCE_COST = 'Valance cost';

function parseWorksheetData(json) {
  var cells = json.feed.entry;
  var title = null;
  for (var i = 0, len = cells.length; i < len; i++) {
    var cell = cells[i].gs$cell;
    var content = cell.$t;
    var row = parseInt(cell.row);
    var col = parseInt(cell.col);
    if (row === 1) {
      if (col !== 1) {
        codes.push(content);
	parts[content] = {};
      }
      else {
        continue; // Skip "Code"
      }
    }
    else {
      if (col === 1) {
        title = content;
      }
      else {
        var part = parts[codes[col - 2]];
        if (isFloat(content)) {
	  part[title] = parseFloat(content);
        }
        else {
          part[title] = content;
        }
      }
    }
  }
  var dutyTypes = [];
  for (var i = 0; i < codes.length; i++) {
    var code = codes[i];
    var part = parts[code];
    dutyTypes.push({label: part[NAME], code: code});
  }
  insertRadios('dutyTypes', dutyTypes, 'dutytype');
}

// Replaces the DOM node with ID nodeID with HTML for the radio buttons
// corresponding to dataArray. Returns a table mapping from code / radio button
// name to dataArray row, allowing for fast look up of 
function insertRadios(nodeId, dataArray, name) {
  var rows = [];
  var lookupTable = {};
  for (var i = 0; dataArray[i]; ++i) {
    var data = dataArray[i];
    lookupTable[data.code] = data;
    var checked = (i === 0) ? ' checked ' : ' ';
    rows[i] = '<label><input type="radio" id="' + name + '_' + data.code + '" name="'
      + name + '" value="' + data.code + '" ' + checked + '> ' + data.label + '</label>';
  }
  byId(nodeId).innerHTML = rows.join('<br>');
  return lookupTable;
}
  
function valueOfChecked(checkboxName) {
  var checkboxes = document.getElementsByName(checkboxName);
  for (var i = 0, len = checkboxes.length; i < len; ++i) {
    var checkbox = checkboxes[i];
    if (checkbox.checked) {
      return checkbox.value;
    }
  }
  return null;
}

function valueOfSelect(id) {
  var select = byId(id);
  if (select) {
    return select.options[select.selectedIndex].value;
  }
  return null;
}

function formatDollars(dollars) {
  return '$' + dollars.toFixed(2);
}

function setDollars(id, dollars) {
  setValue(id, formatDollars(dollars), '');
}

function setValue(id, value, unit) {
  if (unit !== '') {
    unit = ' ' + (unit ? unit : ' units');
  }
  byId(id).value = value + unit;
}

function clearAll(ids) {
  for (var i = 0, len = ids.length; i < len; ++i) {
    var id = ids[i];
    var node = byId(id);
    if (node) {
      node.value = '';
    }
  }
}

function clearAllDerivedValues() {
  clearAll(['dutysize', 'wallmountsize', 'tracktotal', 'rollers', 'endcap', 'cmountvalue',
	    'wmountvalue', 'cost_tracktotal', 'cost_rollers', 'cost_endcap', 'cost_cmount',
	    'cost_wmount', 'cost_handling', 'cost_valence', 'cost_total']);
}

function clearCalculator() {
  clearAll(['track_length', 'segments']);
  clearAllDerivedValues();
}

function checkvalues()
{
  var dutyType = valueOfChecked('dutytype');
  if (!dutyType) {
    alert('Please select a track size');
    return false;
  }
  part = parts[dutyType];

  var track_length = byId('track_length');
  if (!(track_length.value > 0) || !isFloat(track_length.value)) {
    alert("Please enter in the length of TRACK needed");
    track_length.focus();
    return false;
  }
  var trackLength = Math.ceil(parseFloat(track_length.value));
  var orderLength = trackLength;  // The length which must actually be ordered.
  var straightTrackType = false;
  if (dutyType === 'TS2' || dutyType === 'AS2') {
    orderLength = 8 * Math.ceil(trackLength / 8);
    straightTrackType = true;
  }
  var minLength = part[MIN_TRACK_LEN];
  if ((minLength && trackLength < minLength) && ((part[NAME] == 'Medium Duty (T-2)') ||
  (part[NAME] == 'Standard Duty (T-3)'))) {
    alert(part[NAME] + " orders require a " + minLength.toFixed(1)
	  + " feet minimum track length.  \n \n For track lengths shorter than " + minLength.toFixed(1)
          + " feet, we offer our pre-packaged F-Track Packs; please scroll down to learn more.");
    track_length.focus();
    return false;
  }
  else if ((minLength && trackLength < minLength) && ((part[NAME] == 'Heavy Duty (T-1)') ||
  (part[NAME] == '8\' Straight Medium Duty Track (TS-2)') || (part[NAME] == '8\' Bendable Aluminum Straight Track (AS-2)'))) {
      alert(part[NAME] + " orders require a " + minLength.toFixed(1)
	  + " feet minimum track length.");
    track_length.focus();
    return false;
  }

  var segmentsInput = byId('segments');
  if (!(segmentsInput.value > 0) || !isFloat(segmentsInput.value)) {
    alert("Please enter in the number of TRACK SEGMENTS needed");
    segmentsInput.focus();
    return false;
  }

  var numSegments = Math.round(parseFloat(segmentsInput.value));

  var mountType = valueOfChecked('mounttype');

  var numMounts = trackLength;

  if ('T1' === dutyType || 'T2' === dutyType || 'T3' === dutyType) {
    if (valueOfChecked('trackApplication') !== 'curved') {
      numMounts = 4/3 * trackLength;
    }
  }
  else if ('AS2' === dutyType) {
    numMounts = trackLength / 2.5;
  }
  numMounts = Math.round(numMounts);  // XXX! Should we use Math.ceil here instead?

  var mountsCost = part[mountType] * (numMounts + 1);

  var wallMountsDesc = '';
  var numWallMounts = 0;
  var wallMountsCost = 0;
  var numCeilingMounts = 0;
  var ceilingMountsCost = 0;
  if (mountType === 'ceiling') {
    numCeilingMounts = numMounts + 1;
    ceilingMountsCost = mountsCost;
  }
  else {
    numWallMounts = numMounts + 1;
    wallMountsCost = mountsCost;
    if (mountType === 'wall3' || mountType === 'wall55') {
      numCeilingMounts = numMounts + 1;
      ceilingMountsCost = part['ceiling'] * (numMounts + 1);
    }
    wallMountsDesc = MOUNT_DESCRIPTIONS_BY_CODE[mountType];
  }

  var numRollers = 4 * trackLength;
  var numEnds = 2 * numSegments;

  var handling = 10;
  var leftOver = orderLength % part[ROLL_LEN];  // Whatever doesn't use a full roll costs 15% more.
  var trackCost = part[TRACK_COST] * (0.15 * leftOver + orderLength);
  var rollersCost = part[ROLLER_COST] * numRollers;
  var endsCost = part[END_CAP_COST] * numEnds;
  var valanceCost = part[VALANCE_COST] * trackLength;

  setValue('dutysize', part[NAME], '');
  setValue('wallmountsize', wallMountsDesc, '');
  setValue('tracktotal', orderLength, 'feet');
  setValue('rollers', numRollers);
  setValue('endcap', numEnds);
  setValue('cmountvalue', numCeilingMounts);
  setValue('wmountvalue', numWallMounts);
  setDollars('cost_tracktotal', trackCost);
  setDollars('cost_rollers', rollersCost);
  setDollars('cost_endcap', endsCost);
  setDollars('cost_cmount', ceilingMountsCost);
  setDollars('cost_wmount', wallMountsCost);
  setDollars('cost_handling', handling);
  if (valueOfSelect('valanceKit') === 'Yes') {
    setDollars('cost_valence', valanceCost);
    byId('valanceCostSpan').style.display = 'inline';
  }
  else {
    setValue('cost_valence', '', '');
    hide('valanceCostSpan');
  }
  setDollars('cost_total', trackCost + rollersCost + endsCost + ceilingMountsCost + wallMountsCost + handling);

  return true;
}

