/*
  QuinScape Xtreme Foundation Classes   (QXFC)
  JavaScript Framework
  
  Copyright (c) 2007 QuinScape GmbH
  All Rights Reserved.
 
  http://www.quinscape.de
 
  No part of this source code may be distributed in any form, be it altered
  or unaltered, without the explicit written permission of QuinScape.
 
  Author: Jörg Gottschling
*/ 

if(!qxfc)
{
  throw('Requires QXFC JavaScript Framework'); 
}
else if(!qxfc.ajax)
{
  /** @namespace */
  qxfc.ajax =
  {
    
    /**
     * Basis Pfad zu allen JSON-VM-Templates
     * @constant
     */
    baseJsonVmPath : 'internal/system/vm/json/quinscape/',

    /**
      Führt ein HTTP-Get via AJAX mit einer JSON-Antwort aus. Damit wird auf
      dem Server keine Controller-Aktion ausgeführt (dafür die Methode post
      benutzen), sondern nur ein Velocity-Script ausgeführt. Dieses muss eine
      Antwort im JSON-Format senden.
      
      @param {map} requestParameter
          Eine Map mit Request-Parametern als Name-Wert paare. Die Werte werden
          hexkodiert, müssen also noch im Klartext sein. Die Werte müssen keine
          String sein, es dürfen beispielsweise auch Zahlen benutzt werden.
          Es werden keine Parameter automatisch hinzugefügt. Der Request muss
          also komplett sein.

      @param {function} callback
          Eine callback-Funktion bzw. ein closure, welches aufgerufen wird,
          sobald die Server-Antwort angekommen ist. Die Antwort wird als JSON
          interpretiert, deserialisiert und dem callback als erster Parameter
          übergeben.
          
      @example
      // sehr einfacher Beispielaufruf
      qxfc.ajax.get(
          {
            // Template welches auf der Serverseite die Antwort erzeugt
            "rq_Template"  : "internal/system/vm/json/quinscape/getFooBar.vm",
            // Ein zusätzlicher Parameter
            "rq_qsMyParam" : 4711
          },
          function(foo)
          {
            alert("The foo bar is " + foo.bar + "!");
          });

      @author: Jörg Gottschling
    */
    get: function(requestParameter, callback)
    {
      if(!requestParameter) throw('No requestParameter (first parameter) defined!');
      if(!callback) throw('No callback method (second parameter) defined!');

      // logging via Firebug
      if(typeof console != 'undefined')
      {
        console.log('qxfc.ajax.get(requestParameter=',
                    qxfc.json.toString(requestParameter), 
                    ', callback=', callback);
      }
           
      // AJAX-Objekt erzeugen
      var oXmlHttp = new upXmlHttp();
      oXmlHttp.strMethod = "GET";
      oXmlHttp.bProcessResponse = true;
      
      // verarbeitet die Ajax-Antwort
      oXmlHttp.processResponse = function()
      {
        if (oRequest.readyState == 4)
        {
          if (oRequest.status == 200)
          {
            var result = qxfc.json.parseJSON(oRequest.responseText);
            try
            {
              callback(result);
            }
            catch(exc)
            {
              alert("error in callback: " + exc);
            }
          }
          else
          {
            alert("Http Error " + oRequest.status + "\n" + oRequest.statusText);
          } 
        }
      };
      
      // Request aufbauen
      oXmlHttp.strUrl = "?" + this._toQueryString(requestParameter);
      
      // Request absenden
      oXmlHttp.send();
      
      // true, fuer Aufrufe aus event handler (z.B. onchange)
      // die Verarbeitung ist hier natuerlich noch nicht erfolgt
      return true;
    },
    
    /**
      Führt ein HTTP-Post via AJAX mit einer JSON-Antwort aus. Damit werden auf
      dem Server auch Controller-Aktion wie insert, update, delete ausgeführt.
      Die Antwort muss im JSON-Format gesendet werden.
      
      Vor dem Abschicken sollte die ActionID gesetzt werden. Siehe dazu auch
      qxfc.setActionId(id).
      
      @param {map} requestParameter
          Eine Map mit Request-Parametern als Name-Wert paare. Die Werte werden
          hexkodiert, müssen also noch im klartext sein. Die Werte müssen keine
          String sein, es dürfen beispielsweise auch Zahlen benutz werden.
          Es werden keine Parameter automatisch hinzugefügt. Der Request muss
          also komplett sein.

      @param {function} callback
          Eine callback-Funktion bzw. ein closure, welches aufgerufen wird,
          sobald die Server-Antwort angekommen ist. Die Antwort wird als JSON
          interpretiert, deserialisiert und dem callback als erster Parameter
          übergeben.
          
      @param {object} [form]
          Die Form die verschickt werden soll. Im Normalfall ist bei
          Intrexx aber nur eine Form auf der Seite vorhanden. Deshalb wird 
          direkt die erste verschickt, falls der Parameter weggelassen wird!
          
      @example
      // sehr einfacher Beispielaufruf
      qxfc.ajax.post(
          {
            // Template welches auf der Serverseite die Antwort erzeugt
            "rq_Template"  : "internal/system/vm/json/quinscape/getFooBar.vm",
            // Ein zusätzlicher Parameter
            "rq_qsMyParam" : 4711
          },
          function(foo)
          {
            alert("The foo bar is " + foo.bar + "!");
          });

      @author: Jörg Gottschling
    */
    post: function(requestParameter, callback, form)
    {
      if(!requestParameter) throw('No requestParameter (first parameter) defined!');
      if(!callback) throw('No callback method (second parameter) defined!');
      
      // logging via Firebug
      if(typeof console != 'undefined')
      {
        console.log('qxfc.ajax.post(requestParameter=',
                    qxfc.json.toString(requestParameter),
                    ', callback=', callback, 'form=', form);
      }
           
      // AJAX-Objekt erzeugen
      var oXmlHttp = new upXmlHttp();
      oXmlHttp.strMethod = "POST";
      oXmlHttp.bProcessResponse = true;
      oXmlHttp.bAddFormData = true;
      
      // TODO auslagern in eigene Methode
      if(typeof form == 'undefined')
        oXmlHttp.addForm(document.forms[0]);
      else if(typeof form == 'object')
        oXmlHttp.addForm(form);
      else 
        throw('Illegal (third) Parameter form!');
      
      // verarbeitet die Ajax-Antwort
      oXmlHttp.processResponse = function()
      {
        if (oRequest.readyState == 4)
        {
          if (oRequest.status == 200)
          {
            var result = qxfc.json.parseJSON(oRequest.responseText);
            try
            {
              callback(result);
            }
            catch(exc)
            {
              alert("error in callback: " + exc);
            }
          }
          else
          {
            alert("Http Error " + oRequest.status + "\n" + oRequest.statusText);
          } 
        }
      };
      
      // Request aufbauen
      oXmlHttp.strUrl = "?" + this._toQueryString(requestParameter);
      
      // Request absenden
      oXmlHttp.send();
      
      // true, fuer Aufrufe aus event handler (z.B. onchange)
      // die Verarbeitung ist hier natuerlich noch nicht erfolgt
      return true;
    },
    
    /*
      Wandelt eine Map von Parametern in einen korrekten
      Query-String mit Hex-Kodierung, etc. um. Der String enthält
      kein & am Anfang oder Ende und auch kein ? am Anfang. Aber
      natürlich zwischen den Parametern. :-)
      Parameter die auf "Guid" enden werden NICHT hexkodiert!
    */
    _toQueryString : function(parameter)
    {
      var result = "";
      var first = true;
      for(var name in parameter)
      {
        if(first)
          first = false;
        else
          result += "&";
        result += name + "=";
        if(name.match(/Guid$/))
          result += parameter[name];
        else
          result += Helper.hexEncodeString(""+parameter[name]);
      }
      return result;
    },
    
    /*
      Soll einen korrekten Callback Rahmen und das eigentliche Callback
      erzeugen.
    */
    _createCallback : function(callback)
    {
      // TODO: Funktioniert das???
      return function(callback)
      {
        if (oRequest.readyState == 4)
        {
          if (oRequest.status == 200)
          {
            var result = qxfc.json.parseJSON(oRequest.responseText);
            try
            {
              callback(result);
            }
            catch(exc)
            {
              alert("error in callback: " + exc);
            }
          }
          else
          {
            alert("Http Error " + oRequest.status + "\n" + oRequest.statusText);
          } 
        }
      };
    }
    
  };
}

