var __DEBUG__;
__DEBUG__ = false;
//if (Browser.Engine.gecko)
  //__DEBUG__ = true;


/**
 *  Shows the message in the console
 *
 *  @param {Object} obj Object to show
 */
function debug(obj) {
  if (!__DEBUG__) return;

  try {
    console.log(obj);
  } catch(e) {
    alert(obj);
  }
}


/**
 *  Shows the message
 *
 *  @param {Object} sender Where the error occured
 *  @param {Object} exception Exception
 */
function jserror(sender, exception) {
  debug('EXCEPTION : origin='+ sender +', exception='+ exception.message);
  return '<div class="error">\n'
       + '  <h1>JS ERROR</h1>\n'
       + '  <b>'+ sender +'</b>\n'
       + '  <p>'+ exception.message +'</p>\n'
       +'</div>';
}


/**
 *  Some common stuff
 */
var Global = new function() {
  var self = this;  // reference to itself


  /**
   *  loadContent - Loads an AJAX response into div#content
   *
   *  @param {Object} response AJAX response object {html, scripts, elements, tree}
   *  @param {String} target Target element
   */
  this.loadContent = function() {
    debug('Global.loadContent()');
    var response  = arguments[0];
    var target    = (arguments[1]) ? arguments[1] : $('content');

    // get the content from the layout
    var html = '';
    try {
      var match = response.html.match(/<!--ajax-->([\s\S]*?)<!--\/ajax-->/i);
      html = (match) ? match[1] : html;
      //debug('Global.loadContent() : html='+ html);
    } catch (e) {
      //debug(e.message);
      html = jserror('Global.loadContent()', e);
    }

    // display the content
    target.innerHTML = html;

    // get the script from the content
    var scripts = response.scripts;
    //debug('Global.loadContent() : scripts='+ scripts);
    try {
      $exec(scripts);   // try to execute the script
    } catch(e) {
      jserror('Error trying to execute script.', e);
    }
  }


  /**
   *  getError() - Gets an error message from the AJAX response
   *
   *  @param {Object} transport AJAX response object
   *  @return {Object} {String code, String description, String header, String content} Error message with the details
   */
  this.getError = function(transport) {
    debug("Global.getError()");
    var status = transport.status;
    var text = transport.statusText;
    var html = transport.responseText;

    var title = '';
    try {
      var match = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
      title = (match) ? match[1] : title;
    } catch (e) {
      title = '';
    }

    var body = '';
    try {
      var match = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
      body = (match) ? match[1] : body;
    } catch (e) {
      body = jserror('Global.getError()', e);
    }

    // {code, description, header, content, toString}
    return {
      code: status,
      description: text,
      header: title,
      content: body,
      toString: function() {
        return  '<div class="error">\n'
              + '  <h1>'+ status +' - '+ text +'</h1>\n'
              + '  <h2>'+ title +'</h2>\n'
              +    body +'\n'
              + '</div>';
      }
    }
  }


  /**
   *  onFailure() - AJAX onFailure handler; common for all the requests - redirects to the Login Page in case of unauthorized access
   *
   *  @param {Object} sender Owner of the request
   *  @param {Object} transport AJAX response object
   */
  this.onFailure = function(sender, transport) {
    debug("Global.onFailure(); sender="+ sender);
    var error = this.getError(transport);

    // AJAX onFailure handler
    var __onFailure = function(transport) {
      debug("Global.onFailure().__onFailure()");
      error = this.getError(transport);
      $('content').innerHTML = error.toString();
    }

    // AJAX onSuccess handler
    var __onSuccess = function(response) {
      debug("Global.onFailure().__onSuccess()");
      self.loadContent({html: response});
    }

    debug("code="+ error.code);
    debug("description="+ error.description);
    debug("header="+ error.header);
    debug("content="+ error.content);
    switch (error.code) {
      // Unauthorized, Forbidden
      case 401:
      case 403:
        new Request({
          url: 'pages/error.html',
          method: 'get',
          async: false,
          onSuccess: __onSuccess,
          onFailure: __onFailure
        }).send();
        break;
      default:
        try { $('content').innerHTML = error.toString(); } catch(e) {}
    }
  }


  /**
   *  limitTextboxes() - Limits the size of textbox fields on the form
   *
   *  @param {Object} form Form element
   */
  this.limitTextboxes = function(form) {
    debug("Global.limitTextboxes()");
    // quit if this function has already been called (to speed up the code a little bit)
    //if (arguments.callee.form == form.id) return false;
    //arguments.callee.form = form.id;    // flag this function so we don't do the same thing twice

    var element = null;
    var tag     = '';
    var type    = '';
    for (var i=0; i<form.elements.length; i++) {
      element = form.elements[i];   // reference to the element
      tag     = element.tagName.toLowerCase();
      type    = element.type;

      // try to trim the values
      try { element.value = element.value.trim(); } catch(e) {}

      // check for single line textboxes (input type=text)
      if (tag == 'input' && type == 'text') {
        if (element.value.length > 250)   // 250 chacacters is fair enough
          element.value = element.value.substring(0, 250);
      }
      // hidden input fields can contain some important info, such as form state in JSON format, so they can be a bit longer
      else if (tag == 'input' && type == 'hidden') {
        if (element.value.length > 2040)    // 2k is more than enough (anyway, AtLeap will strip it to 252 in most of the cases)
          element.value = element.value.substring(0, 2040);
      }
      // check for multiline textboxes (textarea)
      else if (tag == 'textarea') {
        if (element.value.length > 2040)    // 2k is more than enough (anyway, AtLeap will strip it to 252 in most of the cases)
          element.value = element.value.substring(0, 2040);
      }
    }
  }


  /**
   *  toQueryString() - Creates an encoded list of field=value pairs
   *
   *  @param {Object} form Form Element
   *  @return data
   *  @type String
   */
  this.toQueryString = function(form) {
    debug("Global.toQueryString()");
    var data  = '';

    for (var i=0; i<form.elements.length; i++) {
      var element = form.elements[i];
      var tag     = element.tagName.toUpperCase();
      // input field types (text fields, password fields, hidden fields, checkboxes, radio buttons)
      if (tag == 'INPUT' && element.name != '') {
        switch (element.type) {
          case 'text':
          case 'password':
          case 'hidden':
            data += element.name + '=' + encodeURIComponent(element.value) + '&';
            break;
          case 'checkbox':
            if (element.checked)
              data += element.name + '=' + encodeURIComponent(element.value) + '&';
            else
              data += element.name + '=&';
            break;
          case 'radio':
            if (element.checked)
              data += element.name + '=' + encodeURIComponent(element.value) + '&';
            break;
        }
      }
      // textarea type (memo fields)
      else if (tag == 'TEXTAREA') {
        data += element.name + '=' + encodeURIComponent(element.value) + '&';
      }
      // select type (comboboxes)
      else if (tag == 'SELECT') {
        for (var j=0; j<element.options.length; j++) {
          var option = element.options[j];
          if (option.selected)
            data += element.name + '=' + encodeURIComponent(option.value ? option.value : option.text) + '&';
        }
      }
    }

    return data;
  }


  /**
   *  Opens a new window or a dialog
   *
   *  @param {String} url Specifies the URL of the document to display. If no URL is specified, a new window with about:blank is displayed.
   *  @param {String} name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element.
   *  @param {Object} options Object that contains params
   *  @return {Object} Reference to a window
   */
  this.popup = function(/*name, url, params*/) {
    debug("Global.popup()");
    var name = arguments[0];          // newly created window name
    if (!name)  return;               // no name - no game!

    var url					= arguments[1];   // url
    var options     = arguments[2];   // additional options

    var caller			= (options != null && options.caller)     ? options.caller		 : null;   // caller window
    var w						= (options != null && options.width)      ? options.width  		 : null;   // width
    var h						= (options != null && options.height)     ? options.height		 : null;   // height
    var resizable		= (options != null && options.resizable)  ? options.resizable	 : true;   // is resizable
    var scrollbars	= (options != null && options.scrollbars) ? options.scrollbars : null;   // has scrollbars
    var modal       = (options != null && options.modal)      ? options.modal      : null;   // is modal
    var result      = (options != null && options.result)     ? options.result     : null;   // return the result or not

    if (!url)  url = "about:blank";      // default url
    if (url.indexOf('http') != 0)  url = BASE_URL + url;   // add base url if not set
    if (!caller)  caller = window.parent;   // who has called the popup
    if (!w || !h) { w = 800;  h = 600; }    // default window size

    var size    = "width="+ w +","+ "height="+ h +",";                            // window size
    var resize  = (resizable)  ? "yes" : "no";                                    // resizable
    var scroll  = (scrollbars) ? "yes" : "no";                                    // scrollbars
    var status  = (__DEBUG__)  ? "yes" : "no";                                    // status bar
    var y       = (screen.height <= 600) ? 0 : parseInt((screen.height- h)/2);    // center the window
    var x       = (screen.width	 <= 800) ? 0 : parseInt((screen.width	- w)/2);    // center the window

    // window reference
    var hWnd = null;

    // open modal
    if (modal) {
      if (window.showModalDialog) {   // IE
        hWnd = window.showModalDialog(url,  {'name': name, 'caller': caller},
          'dialogWidth: '	+ w +'px;'+
          'dialogHeight: '+ h +'px;'+
          'dialogTop: '		+ y +'px;'+
          'dialogLeft: '	+ x +'px;'+
          'edge: raised;'	+
          'center: yes;'	+
          'help: no;'			+
          'resizable: '		+ resize +';'+
          'scroll: '			+ scroll +';'+
          'status: '			+ status +';'
        );
      } else {                        // FF
        hWnd = window.open(url, name,
          'modal=yes,'        +
          'width='            + w +','+
          'height='           + h +','+
          'top='              + y +','+
          'left='             + x +','+
          'resizable='        + resize +','+
          'scrollbars='       + scroll +','+
          'status='			      + status +','+
          'channelmode=no,'   +
          'directories=no,'   +
          'fullscreen=no,'    +
          'location=no,'      +
          'menubar=no,'       +
          'titlebar=no,'      +
          'toolbar=no,'       +
          // mozilla
          'chrome=yes,'       +
          'centerscreen=yes,' +
          'directories=no,'   +
          'personalbar=no,'   +
          'dependent=yes,'    +
          'dialog=yes,'       +
          'modal=yes'
        );
        hWnd.dialogArguments = {'name':name, 'caller':caller};
      }
    }
    // open non modal
    else {
      //alert(name);
      hWnd = window.open(url, name,
        'width='            + w +','+
        'height='           + h +','+
        'top='              + y +','+
        'left='             + x +','+
        'resizable='        + resize +','+
        'scrollbars='       + scroll +','+
        'status='			      + status +','+
        'channelmode=no,'   +
        'directories=no,'   +
        'fullscreen=no,'    +
        'location=no,'      +
        'menubar=no,'       +
        'titlebar=no,'      +
        'toolbar=no,'       +
        // mozilla
        'chrome=yes,'       +
        'centerscreen=yes,' +
        'directories=no,'   +
        'personalbar=no,'   +
        'dependent=yes,'    +
        'dialog=no'
      );
    }

    if (result) return hWnd;
  }


  /**
   *  setProgress() - Sets the progress bar
   *
   *  @param {boolean} show true/false
   */
  this.setProgress = function() {
    debug("Global.setProgress()");

    var fade = arguments[0];

    var target = $('content');
    if (fade)
      target.fade(0.0);
    else
      target.fade(1.0);

    //var shape = (arguments[0]) ? arguments[0] : 'default';
    //$(document.body).setStyle('cursor', shape);
  }
}


/**
 *  Message object - in charge of displaying messages in a div#message element
 */
var Message = new function() {
  var self    = this;   // reference to itself
  var message = null;   // message div element
  this.owner  = null;   // object which has set the message


  /**
   *  Shows the message
   *
   *  @param {Object} text String Text to display
   *  @param {Object} sender The owner of the message (which has set the message)
   */
  this.show = function(/*text, sender*/) {
    //debug("Message.show()");
    var text = arguments[0];
    if (arguments[1]) this.owner = arguments[1];

    try {
      if (!message) message = $('message');
      message.innerHTML = text.trim();
      message.style.display = 'block';
      window.scrollTo(0,0);
    } catch(e) {
      jserror('Message.show()', e);
      alert(text.trim());
    }
  }


  /**
   *  Hides the message
   *
   *  @param {Object} sender The object which is trying to hide the message
   */
  this.hide = function(/*sender*/) {
    //debug("Message.hide()");
    var sender = arguments[0];
    if (sender && this.owner != sender) return;

    try {
      if (!message) message = $('message');
      message.style.display = 'none';
      message.innerHTML = '';
    } catch(e) {
      jserror('Message.hide()', e);
    }
  }
}
