var SubFormController = new Class({
  
  // webservice client
  webService: null,
  
  // the button that was used to request the new row 
  lastSender: null,
  
  // timer for setting the timeout if a ajax timeout occurs
  timer: null,
  
  // some default options
  options: {
    ajaxTimeout: 5000
  },
  
  /**
   * Constructor, setup the webservice client
   */
  initialize: function(uri, options)
  {
    // apply options
    this.applyOptions(options);
    
    // create new webservice client
    this.webService = new WebServiceClient(uri, options);
    
    // setup the webservice client
    // allow the insert row button to show when an ajax call fails
    this.webService.onFailure = function(callParams, error){
      alert(error.message);
      this.showInsertButton();
    };
    
    // hide the insert button on each ajax call and set a timeout to show it again
    // if we dont get a response from something to tell it otherwise
    this.webService.beforeRequest = function(requestID){
      this.timer = setTimeout("subFormController.resetButton()",this.options.ajaxTimeout);
      this.lastSender.hide();
    }.pbind(this);
    
    // clear the timeout after a successful ajax request
    this.webService.afterRequest = function(requestID){
      clearTimeout(this.timer);
    }.pbind(this);
  },
  
  /**
   * Generate a new subform row, will append the row to the current subform with an incremented row count
   * 
   * @param sender The button used to add the new row
   * @param module The module that the subform is part of, used for loading the module in the ajax call
   */
  newSubFormRow: function(sender, module)
  {
    // retrieve fieldname of the subform and the current row number
    if(sender === undefined)
      return false;
    
    var fieldname = sender.name.match(/(.*)\[[0-9]+\].*/)[1];
    var rowid = sender.name.match(/.*\[([0-9]+)\].*/)[1];
    
    // build ajax data and send to webservice to generate new row
    var data = {
      action: 'newrow',
      data: {'rowid':rowid,'fieldname':fieldname,'module':module}
    };
    
    // define the last sender object that if anything goes wrong with the ajax call
    // it can show/hide the sending button as necessary
    this.lastSender = sender;
    
    // ajax call.
    this.webService.call(this.callback, data);
  },
  
  /**
   * Delete a subFormRow from the page
   * 
   * @param sender The button used to remove the row
   */
  deleteSubFormRow: function(sender)
  {
    // retrieve fieldname of the subform and the current row number
    if(sender === undefined)
      return false;
    
    var fieldname = sender.name.match(/(.*)\[[0-9]+\].*/)[1];
    var elementname = sender.name.match(/.*\[[0-9]+\]\[(.*)\]/)[1].replace("del_","");
    var rowid = sender.name.match(/.*\[([0-9]+)\].*/)[1];
    
    // first find out if the current subform being removed is the most 'recent' subform
    // by finding all insert buttons 
    var indicies = [];
    $(fieldname + '_ajax_subform').getElements('[name*="'+elementname+'"]').each(function(el){
      var row = el.name.match(/.*\[([0-9]+)\].*/)[1];
      indicies.push(parseInt(row));
    });
    
    // if we only have 1 row, return because we dont want to delete the last row
    var numRows = 0;
    if(indicies.length != 0)
      numRows = indicies.length / 2;
    
    if(numRows <= 1)
      return false;
    
    // get the highest index and second highest index
    // if we are deleting the 'last' row we need the second highest index
    // to show that button (as deleting the last row will remove its insert button)
    var highestRow = Math.max.apply(Math, indicies);
    indicies = indicies.erase(highestRow);
    var secondHighestRow = Math.max.apply(Math, indicies);
    
    // if the current deleted row is the highest (most recent) subform row, show the previous insert button
    if(rowid == highestRow)
      $(fieldname + '[' + secondHighestRow + '][' + elementname + ']').show('inline');
    
    // now delete this row, we incrememnt rowid by 1 because when the row ids are created the subform iterator has incremented
    $(fieldname + '_subform_row_' + (String)(++rowid)).dispose(); 
    
  },
  
  /**
   * Callback that appends the subform row data to the subform element on the page
   * 
   * @param data The ajax response as a JSON string
   */
  callback: function(data)
  {
    // attempt to convert the result to JSON
    try {
      data = JSON.decode(data);
    }
    catch (e) {
      alert('Failed decoding JSON data');
      this.showInsertButton();
      return false;
    }
    
    // if an error occured, alert it and return false
    if(data.error !== undefined)
    {
      alert(data.error);
      this.showInsertButton();
      return false;
    }
    
    // if no html is returned we have a problem..
    if(data.html === undefined)
    {
      alert('here');
      this.showInsertButton();
      return false;
    }
 
    // append the elements to the subform, we get the children as the form will be returned in its ajax wrapper
    $(data.fieldname + '_ajax_subform').adopt(Elements.from(data.html));
  },
  
  /**
   * Show the last insert button that was pressed
   */
  showInsertButton: function()
  {
    this.lastSender.show('inline');
  },
  
  /**
   * Apply any options that are supplied to this instance
   * 
   * @param options
   */
  applyOptions: function(options)
  {
    if(options === undefined)
      return false;
    for(option in options)
      this.options[option] = options[option];
    return true;
  }
  
});


// create controller
var subFormController = false;
window.addEvent('domready', function(){
  subFormController = new SubFormController('formgeneration/subform');
})
