q = {
  Tabs : function(id) {
    $(id).select('li').each(function(tab) {
      tab.observe('click', function() {
        $(id).select('li').each(function(otherTab) {
          otherTab.removeClassName('active-tab');
        });
        tab.addClassName('active-tab');
      });
    });
  },

  getBaseWindow : function() {
    parentWindow = window;
    while (parentWindow.parent && parentWindow.parent != parentWindow) parentWindow = parentWindow.parent;
    return parentWindow;
  },

  getEventTarget : function(e) {
	  e = e || window.event;
	  return e.target || e.srcElement;
	},

  Popup : function(id) {
    var _id = id;
    var _title = '';
    var _showCloseButton = true;
    var default_options = {autosize: true, topclose: true}
    
    return {
      setDimensions : function(width, height) {
        default_options.width = (width == null) ? window.innerWidth - 120 : width;
        default_options.height = (height == null) ? window.innerHeight - 120 : height;
        return this;
      },
      
      setTitle : function(title) {
        default_options.title = urldecode(title);
        return this;
      },
      
      showCloseButton : function(showCloseButton) {
        default_options.closeButton = (showCloseButton) ? 'small' : 'hide';
        return this;
      },
      
      displayUrl : function(url, options) {
        Lightview.show({
          href: url,
          rel: 'iframe',
          options: $H(default_options).merge(options).toObject()
        });
      },
      
      close : function() {
        Lightview.hide();
			},
			
			id : function() {
        return _id;
			}
    }
  },

  addMessage : function(message, type, defaultToAlert) {
    if ($('messages')) {
	    var messageRow = '<li id="newMessage" class="';
	    if (type == 'ERROR') messageRow += 'errorMessage';
	    else if (type == 'WARNING') messageRow += 'warningMessage';
	    else messageRow += 'successMessage';
	    messageRow += '" style="display: none"><div>' + message + '</div></li>';
	    $('messages').insert(messageRow);
	    messageRow = $('newMessage');
	    Effect.ScrollTo('top', {duration: 0.2});
	    Effect.SlideDown(messageRow, {duration: 0.3});
	    setTimeout(function() {new Effect.SlideUp(messageRow, {duration: 0.3})}, 3500);
	    setTimeout(function() {$('messages').removeChild(messageRow)}, 4800);
	  }
	  else if (defaultToAlert) alert(message);
  },
  
  login : function() {
    var showPasswordField = function(passwordField) {
      passwordField.type = 'password';
      passwordField.value = '';
    }
    
    var hidePasswordField = function(passwordField) {
      if (passwordField.value == '') {
        passwordField.type = 'text';
        passwordField.value = 'password';
      }
    }
    
    var doLogin = function() {
      var ajax = new q.AjaxRequest();
      var password = ($('password').type == 'text') ? '' : $F('password');
      ajax.setParameters({'signin[username]': $F('username'), 'signin[password]': password});
      ajax.onSuccess(function(response) {
        ajax.executeLoginInterruptedAjax();
        $('username').value = $('password').value = '';
        $('username').onblur();
        hidePasswordField($('password'));
      });
      ajax.onError(function(response) {
        Effect.SlideDown($('loginErrorBar'), {duration: 0.3});
        setTimeout(function() {new Effect.SlideUp($('loginErrorBar'), {duration: 0.3})}, 3500);
      });
      ajax.send(loginRoute);
    }
      
	  var createLoginPopup = function() {
	    $$('body')[0].insert('<div id="login">' +
	        '<div class="titleBar">You must be logged in to perform this task</div>' +
	        '<div id="loginErrorBar"><div>The username and/or password is invalid</div></div>' +
	        '<div class="loginFields">' +
	        '<input type="text" value="username" id="username" onfocus="if (this.value == \'username\') this.value = \'\'" onblur="if (this.value == \'\') this.value = \'username\'"/>' +
	        '<input type="text" id="password" value="password"/>' +
	        '<div><input class="loginButton" type="button" value="Log-in"/>' +
	        '<a class="nav_link" href="/" title="I forgot my password">I forgot my password</a></div></div></div>');
	    $('password').onfocus = function(){showPasswordField(this)};
	    $('password').onblur = function(){hidePasswordField(this)};
	    $$('#login div.loginFields input.loginButton').first().onclick= doLogin;
	  }
	  
	  return {
	    getPopup : function() {
	      if (!$('login')) createLoginPopup();
	      return $('login');
	    }
	  }
	}(),

  AjaxRequest : function() {
    var _asynchronous = false;
    var _method = 'post';
    var _onSuccess = null;
    var _successMessage = null;
    var _onError = null;
    var _errorMessage = null;
    var _warningMessage = null;
    var _onComplete = null;
    var _updateElement = null;
    var _evaluateScripts = true;
    var _onFailure = function(response) {
      q.addMessage('A critical error has occurred. Please contact support.', 'ERROR');
    };
    var _onException = function(request, exception) {
      q.addMessage(exception.message, 'ERROR');
    };
    var _parameters = {};
    
    return {
      onSuccess : function(onSuccess) {
        _onSuccess = onSuccess;
        return this;
      },
      
      onError : function(onError) {
        _onError = onError;
        return this;
      },
      
      onComplete : function(onComplete) {
        _onComplete = onComplete;
        return this;
      },
      
      onFailure : function(onFailure) {
        _onFailure = onFailure;
        return this;
      },
      
      onException : function(onException) {
        _onException = onException;
        return this;
      },
      
      setParameters : function(parameters) {
        _parameters = parameters;
        return this;
      },
      
      setSuccessMessage : function(successMessage) {
        _successMessage = successMessage;
        return this;      
      },
      
      setErrorMessage : function(errorMessage) {
        _errorMessage = errorMessage;
        return this;
      },
      
      setWarningMessage : function(warningMessage) {
        _warningMessage  = warningMessage;
        return this;
      },
      
      // NOTE: if updating an element eval scripts is set to true due to prototype's update() call
      updateElement : function(updateElement) {
        _updateElement = updateElement;
        return this;
      },
      
      evaluateScripts : function(evaluateScripts) {
        _evaluateScripts = evaluateScripts;
        return this;
      },
      
      setMethod : function(method) {
        _method = method;
        return this;
      },
      
      send : function(url) {
        options = {
          asynchronous : _asynchronous,
          method : _method,
          parameters : _parameters,
          evalJS : (_updateElement) ? false : _evaluateScripts, // if updating elements eval scripts after element is updated
          onSuccess : function(transport) {
            var success = function() {
	            if (transport.responseJSON) {
		            if (transport.responseJSON.result == 'SUCCESS' || transport.responseJSON.result == 'WARNING') {
		              if (_successMessage != null && transport.responseJSON.result == 'SUCCESS') q.addMessage(_successMessage);
		              else if (transport.responseJSON.result == 'WARNING' && _warningMessage === true) q.addMessage(transport.responseJSON.contents, 'WARNING');
		              if (_updateElement) _updateElement.update(transport.responseJSON.contents);
		              if (_onSuccess) _onSuccess(transport.responseJSON.contents);
		            }
		            else if (transport.responseJSON.result == 'ERROR') {
		              if (_errorMessage === true) q.addMessage(transport.responseJSON.contents, 'ERROR');
		              else if (_errorMessage != null) q.addMessage(_errorMessage, 'ERROR');
		              if (_onError) _onError(transport.responseJSON.contents);
		            }
		            if (_onComplete) _onComplete(transport.responseJSON.contents);
		          }
	            else {
	              if (_updateElement) _updateElement.update(transport.responseText);
	              if (_onComplete) _onComplete(transport);
	            }
	          }
	          // ensure success function gets run outside the context of the ajax request on the outermost parent
	          q.getBaseWindow().setTimeout(success, 0);
          }
        }
        options.on401 = function(transport) {
          var baseWindow = q.getBaseWindow();
          baseWindow.setTimeout(function() {
            baseWindow.loginInterruptedAjax = {url: url, options: options, loginPopup: q.Popup.create()};
	          baseWindow.loginInterruptedAjax.loginPopup.setDimensions(330, 160).displayElement(baseWindow.q.login.getPopup());
	          baseWindow.document.getElementById('loginErrorBar').style.display = 'none';
          }, 0);
        }
        options.on403 = function(transport) {
          q.addMessage("You don't have the required permission to access this page", 'ERROR');
        }
        return new Ajax.Request(url, options);
      },
      
      executeLoginInterruptedAjax : function() {
        var baseWindow = q.getBaseWindow();
        baseWindow.loginInterruptedAjax.loginPopup.close();
        return new Ajax.Request(baseWindow.loginInterruptedAjax.url, baseWindow.loginInterruptedAjax.options);
      }
    }
  }
}

q.AjaxRequest.create = function() {
  return new q.AjaxRequest();
}

q.Popup.popupsCreated = 0;
q.Popup.popups = [];

q.Popup.create = function() {
  return new q.getBaseWindow().q.Popup(q.getBaseWindow().q.Popup.popupsCreated++);
}

q.Popup.close = function(popup) {
  LightView.hide();
}

q.Popup.closeAll = function() {
  LightView.hide();
}

function urldecode(str) {
  return unescape(str.replace(/\+/g, ' '));
}
