
var nodes = [];
var selected_node = null;

var formatAmount = 0;
var formatFunction = null;

function formatFixed(x) { return x.toFixed(formatAmount); }
function formatPrecision(x) { return formatAmount > 0 ? x.toPrecision(formatAmount) : x.toPrecision(); }
function formatExponential(x) { return x.toExponential(formatAmount); }
function formatLocale(x) { return x.toLocaleString(); }

function createTableCell(class_name, text) {
  var td = document.createElement('td');
  td.className = class_name;
  td.appendChild(document.createTextNode(text));
  return td;
}

function Node(name, multiplier, addend, original_class_name, parent) {
  this.name = name;
  this.multiplier = multiplier;
  this.addend = addend;
  this.original_class_name = original_class_name;
  this.value = 0;

  this.tr = document.createElement('tr');
  this.tr.className = original_class_name;

  this.tr.appendChild(createTableCell('name', name));

  this.tdResult = createTableCell('result', '-');
  this.tr.appendChild(this.tdResult);

  var node = this;
  (function() {
    node.tr.onmouseover = function() { node.onMouseOver(); }
    node.tr.onmouseout = function() { node.onMouseOut(); }
    node.tr.onclick = function() { node.onClick(); }
  })();

  parent.appendChild(this.tr);
}

Node.prototype.onMouseOver = function() {
  if(this != selected_node) {
    this.tr.className = 'mouseover';
  }
}

Node.prototype.onMouseOut = function() {
  if(this != selected_node) {
    this.tr.className = this.original_class_name;
  }
}

Node.prototype.onClick = function() {
  if(this != selected_node) {
    if(selected_node) {
      selected_node.tr.className = selected_node.original_class_name;
    }
    this.tr.className = 'selected';
    selected_node = this;
    setInstruction(this.name);
    convert();
  }
}

Node.prototype.toKey = function(x) { return (x - this.addend)/this.multiplier; }
Node.prototype.fromKey = function(x) { return this.multiplier * x + this.addend; }

Node.prototype.setOutput = function(x) { this.value = x; }
Node.prototype.updateOutput = function() { this.tdResult.innerHTML = formatFunction(this.value); }

window.onload = function() {

  clearInstruction();

  updateFormatAmount(3);
  document.getElementById('radioFixed').click();

  var table = document.getElementById('outputbody');
  for(var i = 0, item; item = data[i]; ++i) {
    nodes.push(new Node(item.name, item.multiplier, item.addend, i % 2 ? 'rowb' : 'rowa', table));
  }

  var keyNode = null;
  for(var j = 0, node; node = nodes[j]; ++j) {
    if((node.addend == 0) && (node.multiplier == 1)) {
      keyNode = node;
      break;
    }
  }

  if(!keyNode) {
    keyNode = nodes[0];
  }

  keyNode.onClick();
}

function onKeyPress(event) { return event.keyCode == 13 ? convert() : true; }

function convert() {
  if(selected_node) {
    var s = document.getElementById('input').value;
    var input = s.length > 0 ? parseFloat(s) : 0;
    var keyValue = selected_node.toKey(input);
    for(var i = 0, node; node = nodes[i]; ++i) {
      node.setOutput(node == selected_node ? input : node.fromKey(keyValue));
      node.updateOutput();
    }
  }
  return false;
}

function clearInstruction() { document.getElementById('instruction').innerHTML = ""; }
function setInstruction(s) { document.getElementById('instruction').innerHTML = "in " + s + " is equal to:"; }

function updateNodeOutputs() {
  for(var i = 0, node; node = nodes[i]; ++i) {
    node.updateOutput();
  }
}

function clickFormatFixed() {
  formatFunction = formatFixed;
  updateNodeOutputs();
}

function clickFormatPrecision() {
  formatFunction = formatPrecision;
  updateNodeOutputs();
}

function clickFormatExponential() {
  formatFunction = formatExponential;
  updateNodeOutputs();
}

function clickFormatLocale() {
  formatFunction = formatLocale;
  updateNodeOutputs();
}

function updateFormatAmount(x) {
  formatAmount = x;
  document.getElementById('amount').innerHTML = "Amount: " + formatAmount;
}

function incAmount() {
  if(formatAmount < 20) {
    updateFormatAmount(formatAmount + 1);
  }
  updateNodeOutputs();
}

function decAmount() {
  if(formatAmount > 0) {
    updateFormatAmount(formatAmount - 1);
  }
  updateNodeOutputs();
}
