// Returns a list of INPUT elements from FORM 'f'
function findInputs(f) {
  var results = [];
  var q = [];
  q.push(f);
  while (q.length > 0) {
    var el = q.shift();
    var ns = el.childNodes;
    for (var i=0; i<ns.length; i++) {
      var n = ns[i];
      if (n.nodeName == 'INPUT' || n.nodeName == 'SELECT') {
        results.push(n);
      } else {
        q.push(n);
      }
    }
  }
  return results;
}

// Creates the code for one form
function createCode(f) {
  var inputs = findInputs(f);
  var s = '';
  var action = f.action;
  var method = f.method;
  if (!method) method = 'get';
  method = method.toLowerCase();
  s += createInitializeCode(inputs);
  s += createProcessCode(inputs,method,action);
  for (var i=0; i<inputs.length; i++) {
    if (i>0) s += "\n";
    s += createCodeForInput(inputs[i]);
  }
  s += "\n";
  return s;
}

function createInitializeCode(inputs) {
  var res = '';
  res += "\n";
  res += "  def initialize\n";
  for (var i=0; i<inputs.length; i++) {
    var input = inputs[i];
    if (input.nodeName != 'SELECT') continue;
    var name = input.name;
    res += "    @" + name + " = " + suggestClassName(name) + "::DEFAULT\n";
  }
  res += "  end   \n";
  return res;
}

function createProcessCode(inputs,method,action) {
  var res = '';
  res += "\n";

  // Output the params
  res += "  def process(";
  var printComma = false;
  for (var i=0; i<inputs.length; i++) {
    var input = inputs[i];
    if (input.type && input.type.match(/text/i)) {
      if (printComma) res += ",";
      printComma = true;
      res += input.name;
    }
  }

  res += ")\n";

  // Set up the url
  res += "    url = '" + action /* TODO: resolve it */ + "'\n";
  res += "    params = {\n";
  // Output the inits
  for (var i=0; i<inputs.length; i++) {
    var input = inputs[i];

    // Skip empty hidden inputs
    if (input.type == 'HIDDEN' && (!input.value || input.value == '')) {
      continue;
    }
    var name = input.name;
    res += "    :" + name + " => ";
    if (input.nodeName != 'TEXT') {
      res += '@';
    }
    res += name;
    res += ",";
    res += "\n";
  }
  res += "    }\n";
  res += "    Net::HTTP." + method + "_form(URI.parse(url),params).body\n";
  res += "  end   \n";
  return res;
}

// Creates a type safe enum from the <select> input
function createTypeSafeEnum(input) {
  var res = '';
  res += '  class ' + camelize(input.name) + "\n";
  var kids = input.childNodes;
  var outputDefault = false;
  for (var i=0; i<kids.length; i++) {
    var k = kids[i];
    if (k.nodeName != 'OPTION') continue;
    var value = k.value;
    var ihtml = k.innerHTML.replace(/^\s+/,'').replace(/\s+$/,'');
    if (!value) value = ihtml;
    res += '    ';
    var name = camelize(ihtml);
    //
    // Make sure the name start with a digit, if not add something to the front
    //
    if (!name.match(/^[a-zA-Z]/)) {
      name = 'T_' + name;
    }
    res += name + ' = "' + value + '"';
    res += "\n";
    if (!outputDefault) {
      res += '    DEFAULT = ' + name + "\n";
      outputDefault = true;
    }
  }
  res += '  end';
  res += "\n";
  return res;
}

// Creates attributes and possiblly a tpye-safe enum classes for this input
// if this is a select input
function createCodeForInput(input) {
  var name  = input.name;
  var value = input.value;
  var type  = input.type;

  // The final result
  var varName = name;
  var isEnum = input.nodeName == 'SELECT';
  var res = '';
  if (isEnum) {
    res += "\n";
  }
  res += '  attr_writer :' + varName;
  if (isEnum) {
    res += "\n" + createTypeSafeEnum(input);
  }
  return res;
}

// Creates the top of the ruby script
function createHeader(cls) {
  var s = '';
  s += "#!/usr/bin/env ruby\n";
  s += "\n";
  s += "require 'net/http'\n";
  s += "require 'uri'\n";
  s += "require 'cgi'\n";
  s += "\n";
  s += "class " + cls + "\n";
  return s;
}

// Creates the bottom of the ruby script
function createFooter() {
  var s = '';
  s += "end\n";
  return s;
}

// Displays the string 's'
function display(s) {

  var backgroundDiv = document.createElement("div");
  document.body.appendChild(backgroundDiv);
  backgroundDiv.style.position         = "absolute";
  backgroundDiv.style.top              = "0px";
  backgroundDiv.style.left             = "0px";
  backgroundDiv.style.height           = "100%";
  backgroundDiv.style.width            = "100%";
  backgroundDiv.style.backgroundColor  = "gray";
  backgroundDiv.style.opacity          = ".7";
  backgroundDiv.style.filter           = "alpha(opacity=70)";
  backgroundDiv.style.zIndexw          = "5";

  var el = document.createElement("div");

  var WIDTH = 70;
  var MARGIN = (100 - WIDTH) / 2;
  var HEIGHT = 700;

  el.style.position          = "absolute";
  el.style.backgroundColor   = "white";
  el.style.border            = "1px solid black";
  el.style.top               = "50px";
  el.style.width             = WIDTH + "%";
  el.style.height            = HEIGHT + "px";
  el.style.marginLeft        = MARGIN + "%";
  el.style.marginRight       = MARGIN + "%";
  el.style.zIndex            = "10";
  el.style.padding           = "20px";
  el.style.maxHeight         = "80%";
  el.style.minHeight         = "30%";

  document.body.appendChild(el);
  var text = document.createElement("textarea");
  el.appendChild(text);
  text.style.width = "100%";
  text.style.height = "100%";
  text.innerHTML = s;


}

// Returns a capital version of this thing
function capitilize(s) {
  if (!s) return s;
  return s.replace(/\w+/g, function(a){
      return a.charAt(0).toUpperCase() + a.substr(1).toLowerCase();
    });
}

// Turns the different parts to caps:
// e.g.
//   - null   ->  null
//   - a      ->  A
//   - ab     ->  Ab
//   - ab.cd  ->  AbDc
function camelize(host) {
  if (!host) return host;
  var parts = host.split(/[^a-zA-Z0-9_]/);
  var res = '';
  for (var i=0, N=parts.length; i<N; i++) {
    res += capitilize(parts[i]);
  }
  return res;
}

// Creates a name from the document location
function suggestClassName(name) {
  if (!name) {
    name = document.location.hostname + ""; // e.g. www.foo.bar.com
  }  
  name = name.replace(/^www\./,'');           // remove leading www -> foo.bar.com
  name = name.replace(/\.[^\.]+$/,'');        // remove extension   -> foo.bar
  name = camelize(name);                      // camlize            -> FooBar
  return capitilize(name);                    // return it, yuh
}

// Main entry point
function main() {
  var s = '';
  s += createHeader(suggestClassName());
  var fs = document.getElementsByTagName('form');
  for (var i=0; i<fs.length; i++) {
    s += createCode(fs[i]);
  }
  s += createFooter();
  display(s);
}

// --------------------------------------------------
// Main
// --------------------------------------------------
main();

