//this file is dependent on ajax_clientfuncs.js

AJAXPHPInvoker.prototype.constructor    = AJAXPHPInvoker;
AJAXPHPInvoker.prototype.CallFunction   = AJAXPHPInvoker_CallFunction;

AJAXPHPInvoker.prototype.OnCall         = AJAXPHPInvoker_DefaultEvent_OnCall;
AJAXPHPInvoker.prototype.OnReturn       = AJAXPHPInvoker_DefaultEvent_OnReturn;
AJAXPHPInvoker.prototype.OnError        = AJAXPHPInvoker_DefaultEvent_OnError;
AJAXPHPInvoker.prototype.OnCompleted    = AJAXPHPInvoker_DefaultEvent_OnCompleted;


AJAXPHPInvoker.prototype.ajaxclient   = null;
AJAXPHPInvoker.prototype.url          = null;
AJAXPHPInvoker.prototype.callcounter  = 0;

//Flags
AJAXPHPInvoker.prototype.xmloff       = false;
AJAXPHPInvoker.prototype.output       = false;
AJAXPHPInvoker.prototype.parser       = "xmldoc";
AJAXPHPInvoker.prototype.debug        = false;


function AJAXPHPInvoker(url)
{
   this.ajaxclient = new AJAXClient(url);
   this.ajaxclient.attachEventOnStateChange(this.ajaxclient.READYSTATE_LOADED, 
                                             AJAXPHPInvoker_OnAJAXResponseComplete );  
  
   //allow for extra parameters as flags to this object
   for(var i = 1; i < arguments.length; ++i)
   {
      if ( arguments[i] == "-debug on")
      {
         this.debug = true;
      }
      else if (arguments[i] == "-output on")
      {
         this.output = true;
      }
      else if (arguments[i] == "-xml off")
      {
         this.xmloff = true;
      }
      else if (arguments[i] == "-parser substring")
      {
         this.parser = "substring";
      }
   }                                      
}

//override this method 
function AJAXPHPInvoker_DefaultEvent_OnCall(sender)
{
   //do nothing, this is just here to show you that an override is possible
}

//override this method 
function AJAXPHPInvoker_DefaultEvent_OnReturn(sender, returnValue, outputText)
{
   //do nothing, this is just here to show you that an override is possible
}

//override this method 
function AJAXPHPInvoker_DefaultEvent_OnError(sender, returnValue, outputText)
{
   //do nothing, this is just here to show you that an override is possible
}

//override this method 
function AJAXPHPInvoker_DefaultEvent_OnCompleted(sender, returnValue, errorText, outputText)
{
   //do nothing, this is just here to show you that an override is possible
   alert("Webmaster Warning: In AJAXPHPInvoker, you need to define the object's OnCompleted method()");
}

function AJAXPHPInvoker_private_expandArray(array, startindex)
{
   var resultstr = "";
   for(var i = startindex; i < array.length; ++i)
   {
      if ( array[i] !== "" )
      {
         if ( typeof (array[i]) == "object")
            resultstr += AJAXPHPInvoker_private_expandArray(array[i], 0);
         else
            resultstr += "&f_prm[]=" + array[i];
      }
   }
   return resultstr;
}

function AJAXPHPInvoker_CallFunction(identifier, phpfunction)
{
   if (this.OnCall){ this.OnCall(identifier); }
     
   callid = new Array(this, identifier);
      
   //set the parameters and execute the ajax
   var postData = "function=" + phpfunction +
                   AJAXPHPInvoker_private_expandArray(arguments, 2);
  

   this.ajaxclient.sendPost(callid, postData);
}

//Get the substring between the two strings
//returns {true, resultstr} if start string and end string was found
//returns {-1, resultstr}   if end string not found, (but resultstr is filled)
//returns {false, null}       if start string was not found
function AJAXPHPInvoker_substring(haystack, startstr, endstr)
{
      var pos1 = haystack.indexOf(startstr);
      var pos2;
      var resultstr;
      
      if (pos1 >= 0)
      {
         pos1 += startstr.length;
         
         pos2 = haystack.lastIndexOf(endstr);
         if (pos2 == -1)
         {
            resultstr = haystack.substring(pos1, haystack.length);
            return new Array(-1, resultstr); //end not found, but we grabbed up until the end anyway
         }
         else
         {
            resultstr = haystack.substring(pos1, pos2);
            return new Array(true, resultstr);
         } 
      }
      else //start string not found
      {
         return new Array(false, null);
      } 
}

var oncompletecounter = 0;

function AJAXPHPInvoker_OnAJAXResponseComplete(callid, xmlHttpReq)
{   
   //the callid is an array we set up with the send function above
   var self = callid[0];
   var identifier = callid[1];
    
   oncompletecounter++;
          
   //if you wish to see the resulting XML file, uncomment the line below
   if (self.debug == true)
   {
     alert('Called ' + oncompletecounter + ' times');
    var errorelem = document.getElementById("jserror");
    if (errorelem) errorelem.textContent  = xmlHttpReq.responseText;
    else alert('Response: ' + xmlHttpReq.responseText);
   }  
   
   var resultValue;
   var errorMessage;
   var hasError = false;
   var outputText;
   var errorInXML = false;
   var parseSUBSTRINGS = false;

  //if xml is turned off, just return the whole shabang
   if (self.xmloff == true)
   {
      outputText = xmlHttpReq.responseText;
      if ( typeof(self.OnCompleted) == 'function' )
      {  
         self.OnCompleted (identifier, resultValue, errorMessage, outputText);
      }  
      return;
   }
   
//------------------------------------------------------------------------
//----- D E T E R M I N E    P A R S I N G    M E T H O D    -------------
//------------------------------------------------------------------------
  var result_xml_doc;
  var resultNode;
  
  //if the xml document has trouble parsing, just use our own regular expression parsing
  if (self.parser == "xmldoc")
  {
      result_xml_doc = xmlHttpReq.responseXML;  
     if (result_xml_doc.parseError && result_xml_doc.parseError.errorCode != 0) errorInXML = true;
  }
  if (errorInXML)
  { 
     self.parser = "substring";
  }
  
  if (self.parser == "substring")
  {
     parseSUBSTRINGS = true;
     result_xml_doc = xmlHttpReq.responseText;
  }
  
   if (self.debug == true)
   {
     alert('Parsing Method: ' + self.parser);
   }  
  
//------------------------------------------------------------------
  if (parseSUBSTRINGS === false)
  {
      resultNode = result_xml_doc.getElementsByTagName("AJAXFunctionError");
   
      //did the function call get an error or the result have an error node?
      if (resultNode.length > 0) 
       {
          if (resultNode[0].firstChild)
          {
             errorMessage = resultNode[0].firstChild.nodeValue; 
          }
          else
          {
             errorMessage = "Undefined error.";
          }
          hasError = true;
       }
  }
  else //parsing with substrings instead of the built in xml parsers
  {
      var gotsubstr = AJAXPHPInvoker_substring(result_xml_doc, "<AJAXFunctionError>", "</AJAXFunctionError>");
      if (gotsubstr[0] === -1 || gotsubstr[0] === true)
      {
         hasError = true;
         if (gotsubstr === -1) errorMessage = "An unknown error has occurred.";
         else errorMessage = gotsubstr[1];
      }
  }
  
   

  //also get page output if true 
   if (self.output === true)
   {
    if (parseSUBSTRINGS === false)
    {
         resultNode = result_xml_doc.getElementsByTagName("AJAXFunctionOutput");
         if (resultNode.length > 0)
         {
            if (resultNode[0].firstChild)
            {
               outputText = resultNode[0].firstChild.nodeValue;
            }
            else
            {
               outputText = "";
            } 
       }
    }
    else //parsing with substrings instead of the built in xml parsers
    {
       var sub = AJAXPHPInvoker_substring(result_xml_doc, "<AJAXFunctionOutput>", "</AJAXFunctionOutput>");
       //outputText will either be undefined, the text between the output xml, or the text after the first output
       if (sub[0] !== false)
       {
          outputText = sub[1];
       }
    }
   }   
  
  if (parseSUBSTRINGS === false)
  {
      resultNode = result_xml_doc.getElementsByTagName("AJAXFunctionResult");
      //did the function get a result?
      if (resultNode.length > 0)
      { 
      
         if (resultNode[0].firstChild)
         {
           //method was invoked successfully
           resultValue = resultNode[0].firstChild.nodeValue;
         }
         else
         {
           resultValue = "";
         }
      } 
      //possibly throw a NO_RESULT ERROR if no result
      //else 
  }
  else //parsing with substrings instead of the built in xml parsers
  {
     var sub = AJAXPHPInvoker_substring(result_xml_doc, "<AJAXFunctionResult>", "</AJAXFunctionResult>");
     //resultValue will either be undefined, the text between the output xml, or the text after the first output 
     if (sub[0] !== false)
     {
        resultValue = sub[1];
     }
  }
   
   //********* MAKE EVENT CALLS *************
   
   var fonerr = typeof(self.OnError) == 'function';
   var fonret = typeof(self.OnReturn) == 'function';
   var foncomplete = typeof(self.OnCompleted) == 'function';
   
   
  // call events based on three possible outcomes: result, error, result + error
   if (hasError === true && fonerr)
   {
      self.OnError(identifier, errorMessage, outputText);
   }
   
   if (resultValue !== undefined && fonret)
   {
       self.OnReturn(identifier, resultValue, outputText);
   }

   if (foncomplete)
   {
      self.OnCompleted (identifier, resultValue, errorMessage, outputText);
   }  

}
