var TcmsForm = Class.create();
var tcms_Items = new Array();
var formAjaxResult;

//Get any forms with appropriate classes and turn them into tcms forms
Event.observe(window, 'load', function() {
  var wizardForms = document.getElementsByClassName("tcms_wizardForm");
  for (var i=0;i<wizardForms.length;i++) {
    tcms_Items.push(new TcmsForm($(wizardForms[i]).id));
  }
  var tabbedForms = document.getElementsByClassName("tcms_tabbedForm");
  for (var i=0;i<tabbedForms.length;i++) {
    tcms_Items.push(new TcmsForm($(tabbedForms[i]).id));
  }
});

//include validation.js by default
document.write("<script type='text/javascript' src='/js/validation.js'></script>");

TcmsForm.prototype = {
  initialize: function(form_id)
  {
    this.form = $(form_id);
    this.displayPanes = new Array();      
    this.nextButtons = [];
    this.backButtons = [];
    this.submitButtons = [];
    //default immediateValidation to false, set it to true if set to "true" in form tag
    var immediateValidation = false;
    if (this.form.getAttribute("immediateValidation") == "true") {
      immediateValidation = true;
    }
    //defaulting onSubmit to false since wizardDone handles calling the validation during submit
    this.valid = new Validation(this.form.id, {onSubmit:false, useTitles:true, immediate:immediateValidation});
    this.currentPaneId = 0;         
    if (this.form.hasClassName("tcms_wizardForm")) {
      this.paneToHideId = 0;
      this.nextButtons = $A(this.form.getElementsByClassName("tcms_wizardNextBtn"));
      this.backButtons = $A(this.form.getElementsByClassName("tcms_wizardBackBtn"));
      this.submitButtons = $A(this.form.getElementsByClassName("tcms_wizardSubmitBtn"));
      //if the onClick attribute exists for submit buttons, clear it out, so this doesnt break old forms
/*
      this.submitButtons.each( function(button) {
        if (button.getAttribute("onclick")) {button.setAttribute("onclick", "");}
      });
      */
      //register events on wizard buttons
      this.nextButtons.each(this.setupNavButton.bind(this));         
      this.backButtons.each(this.setupNavButton.bind(this));         
      this.submitButtons.each(this.setupNavButton.bind(this));         
      this.panes = this.form.getElementsByClassName("tcms_wizardPane");
      //show the appropriate buttons
      if (this.panes.length > 1) {
  $(this.nextButtons[0]).show();
      }
      if ((this.panes.length==1) && (this.submitButtons.length>0)) {
  $(this.submitButtons[0]).show();
      }
    }
    //create this.panes prior to creating this.displayPanes
    if (this.form.hasClassName("tcms_tabbedForm")) { 
      this.panes = this.form.getElementsByClassName("tcms_tabPane");
    } 
    //look up aliases, store in displayPanes array. 
    //The array index indicates the "current pane," the value represents the pane to display
    for(var i=0;i<this.panes.length;i++) {
      aliasElements = this.panes[i].getElementsByClassName("tcms_alias");
      if (aliasElements.length > 0) {
  this.displayPanes[i]=aliasElements.first().getAttribute("targetPaneId");
      }
      else if (aliasElements.length==0) {
        this.displayPanes[i]=i;
      }
    }
    if (this.form.hasClassName("tcms_tabbedForm")) { 
      this.tabs = this.form.getElementsByClassName("tcms_tab");
      //register submit event on tcms_tabbedFormSubmitBtn elements
      this.submitButtons = this.form.getElementsByClassName("tcms_tabbedFormSubmitBtn")
      this.submitButtons.each(this.setupNavButton.bind(this));         
      //Set up initial tab, leftmost tab selected by default, run onEnter
      this.tabs.first().addClassName("tcms_activeTab");
      //check if first pane has an alias and display the correct pane, run onEnter
      paneToDisplayId = this.displayPanes[this.currentPaneId];
      $(this.panes[paneToDisplayId]).addClassName('tcms_activeTabBody');
      eval($(this.panes[this.currentPaneId]).getAttribute("onEnter"));
      this.tabs.each(this.setupNavButton.bind(this));      
    }
    //display the first wizard pane
    if (this.form.hasClassName("tcms_wizardForm")) {
      this.displayWizardPane();
    }
    //add date selector calendar control to appropriate elements
    /*
    datePickers = this.form.getElementsByClassName("tcms_datePicker")
    datePickers.each(function(datePicker) {
      tcms_Items.push(new DatePicker(datePicker, tcms_Items.length));
    });

    // add color picker control to appropriate elements
    colorPickers = this.form.getElementsByClassName("tcms_colorpicker")
    colorPickers.each(function(Picker){
      trigger = Picker.id + "_trigger"
      Picker.setAttribute("OnChange", "$(\"" + trigger + "\").setStyle({'background-color':$('"+Picker.id+"').value})");
      Element.insert(Picker, {After: "<br/><input title='Click here to pick a color' style=\"cursor:pointer;border:1px solid #ccc;background-color:"+Picker.value+";\" id=\"" + trigger + "\" size="+Picker.size+"/>"});
      tcms_Items.push(new ColorPicker(Picker.id, trigger));
    });

    // add time picker control to appropriate elements
    timePickers = this.form.getElementsByClassName("tcms_timePicker");
    timePickers.each(function(TP){
      tcms_Items.push(new TimePicker(TP));
    });
    */
 },
    
  setupNavButton : function(element) {
    Event.observe(element,'click',this.activateNavButton.bindAsEventListener(this));
  },

  activateNavButton :  function(event) {
    //find the closest element to the element that fired the event. Done this way to handle a link with an interior element, such as <a><span/></a>
    var element = Event.findElement(event, "input");
    if (!element){element = Event.findElement(event, "a");}
    Event.stop(event);
    this.switchToPane(element);
  },

  switchToPane: function(element) 
  {
    //tabbed section
    if (this.form.hasClassName("tcms_tabbedForm")) {      
      if (element.hasClassName("tcms_tabbedFormSubmitBtn")) {        
  this.wizardDone(this.currentPaneId);
      }
      else {
  //add or remove tcms_invalidTab class as needed on current tab
  if (!this.validatePane(this.currentPaneId)) {
    $(this.tabs[this.currentPaneId]).addClassName('tcms_invalidTab');    
  }
  else {
    $(this.tabs[this.currentPaneId]).removeClassName('tcms_invalidTab');
  }
  //switch the pane
  $(this.tabs[this.currentPaneId]).removeClassName('tcms_activeTab');
  //check if the current pane has an alias and hide the correct pane
  paneToHideId = this.displayPanes[this.currentPaneId];
  $(this.panes[paneToHideId]).removeClassName('tcms_activeTabBody');
  $(this.panes[paneToHideId]).hide();
  //update currentTab
  eval($(this.panes[this.currentPaneId]).getAttribute("onExit"));          
  this.currentPaneId = this.tabs.indexOf(element);
  $(this.tabs[this.currentPaneId]).addClassName('tcms_activeTab');    
  //check if the current pane has an alias and display the correct pane, run onEnter
  paneToDisplayId = this.displayPanes[this.currentPaneId];
  $(this.panes[paneToDisplayId]).addClassName('tcms_activeTabBody');
  $(this.panes[paneToDisplayId]).show();
  eval($(this.panes[this.currentPaneId]).getAttribute("onEnter"));
      }
    }
    //wizard section
    if (this.form.hasClassName("tcms_wizardForm")) {
      if (element.hasClassName("tcms_wizardSubmitBtn")) {        
  this.wizardDone(this.currentPaneId);
      }
      if (element.hasClassName("tcms_wizardNextBtn")) {
  //if pane is valid, display new pane          
  if (this.validatePane(this.currentPaneId)) {          
    //check if current pane has an alias and hide the correct pane            
    paneToHideId = this.displayPanes[this.currentPaneId];            
    //progress to next pane if onExit returns true or is not present, otherwise eval onExit
    onExit = eval(this.panes[this.currentPaneId].getAttribute("onExit"));
    if (onExit == true || onExit == null) {
      this.panes[paneToHideId].hide();
      //increment currentPaneId            
      this.currentPaneId++;        
      this.displayWizardPane();
    }
  }
      }
      if (element.hasClassName("tcms_wizardBackBtn")) {
  //check if current pane has an alias and hide the correct pane            
  paneToHideId = this.displayPanes[this.currentPaneId];            
  this.panes[paneToHideId].hide();
  //decrement currentPaneId            
  this.currentPaneId--;        
  this.displayWizardPane();
      }
    }
  },   
  
  displayWizardPane: function()
  {
    eval(this.panes[this.currentPaneId].getAttribute("onEnter"));                          
    //check if current pane has an alias and hide the correct pane            
    paneToDisplayId = this.displayPanes[this.currentPaneId];            
    this.panes[paneToDisplayId].show();      
    //display appropriate buttons  
    //first pane in a 1 pane form, only show submit
    if (this.currentPaneId == 0 && this.panes.length==1) {
      this.nextButtons.each(function(button) {button.hide()});
      this.backButtons.each(function(button) {button.hide()});
      this.submitButtons.each(function(button) {button.show()});
    }
    //first pane in a mutli pane form, only show next
    else if (this.currentPaneId == 0 && this.panes.length > 1) {
      this.nextButtons.each(function(button) {button.show()});
      this.backButtons.each(function(button) {button.hide()});
      this.submitButtons.each(function(button) {button.hide()});
    }
    //last pane in a form, show back and submit
    else if (this.currentPaneId == this.panes.length-1) {
      this.nextButtons.each(function(button) {button.hide()});
      this.backButtons.each(function(button) {button.show()});
      this.submitButtons.each(function(button) {button.show()});
    }
    //middle panes, not first or last. show back and next
    else {  
      this.nextButtons.each(function(button) {button.show()});
      this.backButtons.each(function(button) {button.show()});
      this.submitButtons.each(function(button) {button.hide()});
    }
  },
  
  nextPane: function()
  {
    this.panes[paneToHideId].hide();
    this.currentPaneId ++;
    this.displayWizardPane();
  },
  
  confirmExit: function()
  {
      window.onbeforeunload = null;
      return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
  },
  
  validatePane: function(paneId)
  {
    return this.valid.validateSection($(this.panes[paneId]));
  },

  //returns true or false indicating whether all fields are valid or not
  //for tabbed forms, if true removes invalidTab class from invalid tabs
  validateForm: function()
  {
    isValid = true;
    isValid = this.valid.validate();
    //remove tcms_invalidTab class on tabs for invalid forms
    if (isValid == true && this.form.hasClassName("tcms_tabbedForm")) {      
      invalidTabs = this.form.getElementsByClassName("tcms_invalidTab");
      invalidTabs.each (function(invalidTab) {invalidTab.removeClassName("tcms_invalidTab");});
    }
    return isValid;
  },
  
  //returns true if all panes are valid, false otherwise
  //if an invalid pane is found that is not the current pane, run the passed in error Code or run an alert with default text
  //if all panes are valid on a tabbed form, remove invalidTab class from invalid tabs
  validateAllPanes: function(notifyCode)
  {
    isValid = false;
    invalidPaneIds = new Array();
    for (var i=0; i < this.panes.length; i++) {
      if (!this.validatePane(i)) {invalidPaneIds.push(i);}
    }
    if (invalidPaneIds.length == 0) {isValid = true;}
    else {
      //theres an invalid pane, display message if the invalid pane is not the current pane
      displayMessage = true;
      for (var i=0; i < invalidPaneIds.length; i++) {
  if (invalidPaneIds[i] == this.currentPaneId) {displayMessage = false;}
      }
      if (displayMessage == true) {
  //if nofityCode was passed in run it, otherwise run default alert
  if (notifyCode) {eval(notifyCode);} 
  else {alert("Please check all tabs for any invalid fields");}
      }
    }
    //remove tcms_invalidTab class on tabs for invalid forms
    if (isValid == true && this.form.hasClassName("tcms_tabbedForm")) {      
      invalidTabs = this.form.getElementsByClassName("tcms_invalidTab");
      invalidTabs.each (function(invalidTab) {invalidTab.removeClassName("tcms_invalidTab");});
    }
    return isValid;
  },
  
  wizardDone: function()
  {
    //validate the current tab
    var isTabValid = this.validatePane(this.currentPaneId);
    if (isTabValid) {
      $(this.panes[this.currentPaneId]).hide();
      this.submitButtons.each(function(button) {
        if (button.visible()) {button.hide();}
       });
       this.backButtons.each(function(button) {
        if (button.visible()) {button.hide();}
      });
      this.PostingMessageDiv = this.form.getElementsByClassName("tcms_wizardPostingMessage")[0];
      this.SuccessMessageDiv = this.form.getElementsByClassName("tcms_wizardSuccessMessage")[0];
      this.FailureMessageDiv = this.form.getElementsByClassName("tcms_wizardFailureMessage")[0];
      if (this.PostingMessageDiv) {this.PostingMessageDiv.show();}
      if (this.form.getAttribute("method") == "AJAX") {
        var Success = this.form.getAttribute("onSuccess");
        var Failed = this.form.getAttribute("onFailure");
        new Ajax.Request(this.form.getAttribute("action"), {
          method:'post',
          onSuccess: function(transport) {
            tcms_Items[0].form.getElementsByClassName("tcms_wizardPostingMessage")[0].hide();
            tcms_Items[0].form.getElementsByClassName("tcms_wizardSuccessMessage")[0].show();
            //if onsuccess was specified, run it, otherwise default handler is run
          },
          onFailure: function(transport) {
            this.PostingMessageDiv.hide();

            //if onfailure was specified, run it, otherwise default handler is run
            if (Failed != null) {
              var fn = eval(Failed);
              fn(this, transport);
            }
            else {this.FailureMessageDiv.show();}
  	     $$('.tcms_wizardFailureMessage')[0].innerHTML += ("<br>" + transport.status);
            $$('.tcms_wizardFailureMessage')[0].innerHTML += ("<br>" + transport.responseText);
          }.bind(this),
          on404: function(transport) {
            this.PostingMessageDiv.hide();
            this.FailureMessageDiv.show();
          }.bind(this),
          postBody: this.form.serialize()
        });
      }
      //if the form is not Ajax, it has passed validation so submit
      else {this.form.submit();}
    }
  }
}
