// warb.js
//
// Webtemplate Asynchronous Request Broker - Javascript Library
// Copyright(C) 2007 Datafathom, LLC.  All rights reserved.
//
// Written by Craig P. McDaniel, Jr. <craig@datafathom.com>
// Contains small snippet of code by Dieter Raber <dieter@dieterraber.net>
//
//


// Some Utility methods.
//

var WarbUtil =
{

  /* Return true if a variable is numeric, false otherwise.
   */

   isNumeric: function(sText)
   {
      var ValidChars = "0123456789.";
      var IsNumber=true;
      var Char;

      for (i = 0; i < sText.length && IsNumber == true; i++)
      {
         Char = sText.charAt(i);
         if (ValidChars.indexOf(Char) == -1)
         {
            IsNumber = false;
         }
      }

      return IsNumber;
   },


  /* Return true if a variable is defined, false otherwise.
   */

   isDefined: function(variable)
   {
      return (typeof(variable) == "undefined") ? false: true;
   },


  /* Take the validationErrors object of key=value pairs returned from the broker and display
   * a neat little alert box telling the user to correct the following validation errors, displaying
   * each validation error on a line.
   */

   alertValidationErrors: function(validateErrors)
   {
      var text = "Please correct the following errors: \n\n";
      var key;

      for (key in validateErrors)
      {
         text += validateErrors[key] + "\n";
      }

      alert(text);
   }
}



// We create our custom WARB states so they can be used in Ajax.Request
//

Ajax.Responders.register(
{
   onComplete: function(request, transport, json)
   {
      if (transport.status == 200)
      {
         if (json == null)
         {
            var json = transport.responseText.evalJSON(true);
         }

         if (!json.result ||
             !WarbUtil.isDefined(json.numAuthErrors) ||
             !WarbUtil.isDefined(json.numValidateErrors) ||
             !WarbUtil.isDefined(json.numErrors) ||
             !WarbUtil.isNumeric(json.numAuthErrors) ||
             !WarbUtil.isNumeric(json.numValidateErrors) ||
             !WarbUtil.isNumeric(json.numErrors) ||
             json.result == null ||
             json.result == ""
            )
         {
             alert("The WARB broker did not return a valid response.");
             return;
         }

         /* Check WARB result variable and call appropriate method. */
         if (request.options.onWarbSuccess && json.result == "success")
         {
            request.options.onWarbSuccess(transport, json);
         }

         if (request.options.onWarbFailure && json.result == "fail")
         {
            request.options.onWarbFailure(transport, json);
         }

         if (request.options.onWarbAuthError && json.numAuthErrors > 0)
         {
            request.options.onWarbAuthError(transport, json);
         }

         if (request.options.onWarbValidateError && json.numValidateErrors > 0)
         {
            request.options.onWarbValidateError(transport, json);
         }
      }
   }

});



// WARB Debug Window
//

responseWindow = 0;
headerWindow = 0;
rawWindow = 0;
debugWindow = 0;
dataWindow = 0;
errorWindow = 0;
authWindow = 0;
validationWindow =0;
var warbDebugWindowRef;


var WarbDebug =
{
   json: "",


   /* Callback function to record a created request */
   onCreate: function(request, transport)
   {
       WarbDebug.request = request;
   },



   /* Callback function to record a completed request. */
   onComplete: function(request, transport)
   {
      try
      {
         WarbDebug.json = transport.responseText.evalJSON();
      }
      catch (exception)
      {
         WarbDebug.json.debugHTML = "Invalid JSON data received from broker;"
         WarbDebug.json.numErrors = 1;
      }

      WarbDebug.displayEntry(request, transport);
   },



   /* See that debug window is open. */
   openWindow: function()
   {
      //if (warbDebugWindowRef == null || warbDebugWindowRef.closed)
     // {
         warbDebugWindowRef = window.open("", "WarbDebugWindow", "location=0, status=1, scrollbars=1");
         warbDebugWindowRef.document.title = "WARB Debug Window"
         WarbDebug.displayHeader();
     // }
   },



   /* Not reliable. Close it yourself! ;) */
   closeWindow: function()
   {
      // nothing
   },



   /* Display header in debug window only if window is new or has been cleared */
   displayHeader: function()
   {
       if (!warbDebugWindowRef.warbDebugWindowHeader || warbDebugWindowRef.warbDebugWindowHeader == 0)
       {
          var header = "";

          header += '<script type="text/javascript">              ';
          header += 'new PeriodicalExecuter(function(pe)          ';
          header += '{                                            ';
          header += '   top.opener.warbDebugWindowRef = window;   ';
          header += '}, 1);                                       ';
          header += 'warbDebugWindowHeader=1;                     ';
          header += '</script>                                    ';
          header += '<div style="background-color:#4087c3; border: 3px solid #25333e; font-family:Verdana, Helvetica, sans-serif; font-size:18px; color:#FFFFFF; text-align:center; padding:15px; margin-bottom:20px;">WARB Debug Window&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="button" value="Clear" OnClick="document.body.innerHTML=\'\'; warbDebugWindowHeader=0; top.opener.warbDebugWindowRef=window; opener.WarbDebug.displayHeader();"></div>';
          warbDebugWindowRef.document.write(header);
       }
    },


   /* Display request entry in debug window. */
   displayEntry: function(request, transport)
   {
      var requestNum = Math.floor(Math.random() * 100000); /* random identifier for this entry */
      var debug = WarbDebug.json.debugHTML;
      var parameters = "";
      var response = "";
      var errors = "";
      var auth = "";
      var validation = "";

      /* Format parameters in readable form */
      parameters = "<pre>" + format_r(request.parameters) + "</pre>";
      if (parameters == "") parameters = "No parameters sent to request broker.";

      /* Format response data in readable form */
      if (!WarbDebug.json || WarbDebug.json == "")
      {
         response = "No response data received from broker.";
      }
      else
      {
         response = "<pre>" + format_r(WarbDebug.json) + "</pre>";
      }

      /* list any errors */
      if (WarbDebug.json.numErrors > 0)
      {
         WarbDebug.json.errors.each(function(item)
         {
            errors += '<div style="border:1px solid #325572; background-color:#d6e6f3; padding:3px; margin-bottom:9px;">' + item + '</div>';
         });
      }
      else
      {
         errors = "No errors.";
      }

      /* list any validation errors */
      if (WarbDebug.json.numValidateErrors > 0)
      {
         for (key in WarbDebug.json.validateErrors)
         {
            validation += '<div style="border:1px solid #325572; background-color:#d6e6f3; padding:3px; margin-bottom:9px;">Var: \'' + key + '\' &nbsp;&nbsp;&nbsp; Detail: ' + WarbDebug.json.validateErrors[key]  + '</div>';
         }
      }
      else
      {
         validation = "No validation errors.";
      }

      /* list any auth errors */
      if (WarbDebug.json.numAuthErrors > 0)
      {
         for (key in WarbDebug.json.authErrors)
         {
            auth += '<div style="border:1px solid #325572; background-color:#d6e6f3; padding:3px; margin-bottom:9px;">Var: \'' + key + '\' &nbsp;&nbsp;&nbsp; Detail: ' + WarbDebug.json.validateErrors[key]  + '</div>';
         }
      }
      else
      {
         auth = "No auth errors.";
      }


      if (request.method ="post" || request.method == "POST")
        var method = "POST";
      else if (request.method ="get" || request.method == "GET")
        var method = "GET";
      else
        var method = request.method;


      var html = "";

      html += '<div style="background-color:#e4e5e5; border: 3px solid #25333e; font-family:Verdana, Helvetica, sans-serif; font-size:12px; color:#000000;">';
      html += '<div style="padding: 5px;">Method: ' + method + '. &nbsp;&nbsp; WARB Broker: <b>' + request.url + '</b> &nbsp;&nbsp;&nbsp; HTTP Response: <b>' + transport.status + '</b> &nbsp;&nbsp;&nbsp; Execution time: <b>0.32ms</b></div>';
      html += '<br />';

      html += '<div style="width: 10px; float: left; padding: 4px;"></div>';
      html += '<a style="width: 100px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleRequest(' + requestNum + ')">Request Data</a>';

      html += '<div style="width: 20px; float: left; padding: 4px;"></div>';
      html += '<a style="width: 100px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleResponse(' + requestNum + ')">Response Data</a>';

      html += '<div style="width: 20px; float: left; padding: 4px;"></div>';
      html += '<a style="width: 150px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleDebug(' + requestNum + ')">Broker Debug Output</a>';

      // html += '<div style="width: 20px; float: left; padding: 4px;"></div>';
      // html += '<a style="width: 150px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleRaw(' + requestNum + ')">Broker Raw Output</a>';

      html += '<div style="width: 20px; float: left; padding: 4px;"></div>';
      html += '<a style="width: 100px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleError(' + requestNum + ')">Errors (' + WarbDebug.json.numErrors + ')</a>';

      html += '<div style="width: 20px; float: left; padding: 4px;"></div>';
      html += '<a style="width: 100px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleAuth(' + requestNum + ')">Auth Errors (' + WarbDebug.json.numAuthErrors + ')</a>';

      html += '<div style="width: 20px; float: left; padding: 4px;"></div>';
      html += '<a style="width: 150px; float: left; padding:4px; background-color: #60a9e8; text-align:center;" onClick="window.opener.WarbDebug.toggleValidation(' + requestNum + ')">Validation Errors (' + WarbDebug.json.numValidateErrors + ')</a>';

      html += '<div style="clear: both; border-bottom: 1px solid #000000;"></div>';

      html += '<br />';

      // this screws stuff up and I don't know why.
      // html += '<div id="rawLayer_' + requestNum + '"        style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + transport.responseText + '</div>';

      html += '<div id="requestLayer_' + requestNum + '"    style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + parameters + '</div>';
      html += '<div id="responseLayer_' + requestNum + '"   style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + response + '</div>';
      html += '<div id="debugLayer_' + requestNum + '"      style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + debug + '</div>';
      html += '<div id="errorLayer_' + requestNum + '"      style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + errors + '</div>';
      html += '<div id="authLayer_' + requestNum + '"       style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + auth + '</div>';
      html += '<div id="validationLayer_' + requestNum + '" style="display:none; margin: auto; width: 95%; border:1px solid #000000; background-color:#FFFFFF; padding:20px">' + validation + '</div>';
      html += '<br />';

      html += '</div>';
      html += '<br />';

      warbDebugWindowRef.document.write(html);
   },



   // Functions to toggle various layers of information on and off
   //


   toggleRequest: function(num)
   {
     var id = "requestLayer_" + num;

     if (dataWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  dataWindow = 1;
		  return;
     }

     if (dataWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  dataWindow = 0;
		  return;
     }
  },

  toggleResponse: function(num)
  {
     var id = "responseLayer_" + num;

     if (responseWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  responseWindow = 1;
		  return;
     }

     if (responseWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  responseWindow = 0;
		  return;
     }
  },

  toggleDebug: function(num)
  {
     var id = "debugLayer_" + num;

     if (rawWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  rawWindow = 1;
		  return;
     }

     if (rawWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  rawWindow = 0;
		  return;
     }
  },

  toggleRaw: function(num)
  {
     var id = "rawLayer_" + num;

     if (rawWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  rawWindow = 1;
		  return;
     }

     if (rawWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  rawWindow = 0;
		  return;
     }
  },

  toggleError: function(num)
  {
     var id = "errorLayer_" + num;

     if (errorWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  errorWindow = 1;
		  return;
     }

     if (errorWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  errorWindow = 0;
		  return;
     }
  },

  toggleAuth: function(num)
  {
     var id = "authLayer_" + num;

     if (authWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  authWindow = 1;
		  return;
     }

     if (authWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  authWindow = 0;
		  return;
     }
  },

  toggleValidation: function(num)
  {
     var id = "validationLayer_" + num;

     if (validationWindow == 0)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='block';
		  validationWindow = 1;
		  return;
     }

     if (validationWindow == 1)
	  {
        warbDebugWindowRef.document.getElementById(id).style.display='none';
		  validationWindow = 0;
		  return;
     }
  },



  /* Turn the WARB debug mode on.  Register our responder functions. */
  on: function()
  {
     Ajax.Responders.register(
     {
        onCreate: WarbDebug.onCreate,
        onComplete: WarbDebug.onComplete,
        onFailure: WarbDebug.onComplete
     });

     WarbDebug.openWindow();
  },


  /* Turn the WARB debug mode off. Unregister our responder functions. */
  off: function()
  {
     Ajax.Responders.unregister(
     {
        onCreate: WarbDebug.onCreate,
        onComplete: WarbDebug.onComplete,
        onFailure: WarbDebug.onComplete
     });
  }


/* end WarbDebug */
}



//
// @author      Dieter Raber <dieter@dieterraber.net>
// @copyright   2004-12-27
// @version     1.0
// @license     http://www.gnu.org/copyleft/lesser.html (LGPL)
//

function format_r(expr)
{
   var dim    = 0;
   var padVal = '\xA0\xA0\xA0\xA0\xA0';

   switch(typeof expr)
   {
      case 'string':
      case 'number':
        retVal = expr;
        break;
      case 'object':
        retVal = 'Array\n{\n' + outputFormat(expr, dim) + '\n}';
        break;
      default:
        retVal = typeof(expr);
   }

   function pad(dim)
   {
      padding = '';
      for (i = 0; i < dim; i++)
      {
         padding += padVal;
      }

   return padding;
   }

   function outputFormat(expr, dim)
   {
     var retVal = '';

     for (var key in expr)
     {
        if (key == "debugHTML")
        {
          retVal += padVal + pad(dim) + '[' + key + '] => *** value not displayed *** \n';
          continue;
        }

        if (typeof expr[key] == 'object' && expr[key].constructor == Array)
        {
          retVal += padVal + pad(dim) + '[' + key + '] => Array\n'
                 + padVal + pad(dim) + '{\n'
                 + outputFormat(expr[key], dim + 1) + padVal + pad(dim) + '}\n';
        }
        else if (expr[key].constructor == Function)
        {
          continue;
        }
        else
        {
          retVal = retVal + padVal + pad(dim) + '[' + key + '] => ' + expr[key] + '\n';
        }
     }

   return retVal;
   }

return retVal;
}

