var dialog = {
// -----------------------------------------------------------------------------
// Settings
// -----------------------------------------------------------------------------
  
  backgroundOpacity: .6,
  messageDialogOpacity: 1,
  formDialogOpacity: 1,
  collapseFieldsets: false,

// -----------------------------------------------------------------------------
// Internal variables
// -----------------------------------------------------------------------------
  
  backgroundElements: [],
  dialogElements: [],
  dialogElement: null,
  darkboxes: {},
  darkboxMargins: {},
  zIndex: 10,
  cancelled: false,
  
// -----------------------------------------------------------------------------
// Internal methods
// -----------------------------------------------------------------------------

  isIE6: function()
  {
    return $.browser.msie && $.browser.version < 7;
  },
  
  getFloatingPosition: function()
  {
    if (this.isIE6()) return 'absolute';
    else return 'fixed';
  },

// -----------------------------------------------------------------------------
// Compatibility methods
// -----------------------------------------------------------------------------
  
  prepareOverlay: function()
  {
    if (this.isIE6())
      for (var i in this.dialogElements)
        this.dialogElements[i].find('select').css('visibility', 'hidden');
  },
  
  restoreOverlay: function()
  {
    if (this.isIE6())
      for (var i in this.dialogElements)
        this.dialogElements[i].find('select').css('visibility', 'visible');
  },
  
// -----------------------------------------------------------------------------
// Background elements
// -----------------------------------------------------------------------------

  hideBackgroundElement: function()
  {
    for (var i = this.backgroundElements.length - 1; i >= 0; i--)
    {
      if (this.backgroundElements[i] != this.loadingDialogBackground &&
          this.backgroundElements[i] != undefined)
      {
        this.backgroundElements[i].fadeOut('fast', function()
        {
          $(this).remove();
        });
        this.zIndex--;
        this.backgroundElements.splice(i, 1);
        return;
      }
    }
  },
  
  showBackgroundElement: function()
  {
    var backgroundElement;
    
    if (this.isIE6())
    {
      backgroundElement = $('<img class="dialogBackground"/>').
        attr('src', base_url + '/images/spacer.gif');
    }
    else
    {
      backgroundElement = $('<div class="dialogBackground"/>');
    }
    
    backgroundElement.css({
      top: 0, left: 0, width: '100%', height: '100%', 'z-index': this.zIndex++,
      opacity: this.backgroundOpacity,
      position: this.getFloatingPosition()
    }).hide();
    
    $('body').prepend(backgroundElement.fadeIn('fast'));
    this.backgroundElements.push(backgroundElement);
    
    return backgroundElement;
  },
  
// -----------------------------------------------------------------------------
// Dialog elements
// -----------------------------------------------------------------------------
  
  newDialogElement: function(domElement)
  {
    if (domElement == undefined) domElement = '<div/>';
    
    this.prepareOverlay();
    
    this.dialogElements.push(this.dialogElement =
      $(domElement).addClass('dialogElement').css('z-index', this.zIndex++).
      hide());
    
    return this.dialogElement;
  },
  
  showDialogElement: function(dialogElement)
  {
    $('body').prepend(dialogElement.fadeIn('fast'));
    return dialogElement;
  },
  
  hideDialogElement: function(callback)
  {
    for (var i = this.dialogElements.length - 1; i >= 0; i--)
    {
      if (this.dialogElements[i] != this.loadingDialog &&
          this.dialogElements[i] != undefined)
      {
        this.dialogElements[i].fadeOut('fast', function()
        {
          $(this).remove();
          if (callback != undefined)
          {
            callback();
          }
        });
        this.dialogElements.splice(i, 1);
        this.zIndex--;
        break;
      }
    }
        
    if (this.dialogElement.length == 0) 
    {
      this.dialogElement = null;
    }
    else 
    {
      this.dialogElement = this.dialogElements[this.dialogElement.length - 1];
    }
    
    this.restoreOverlay();
  },

// -----------------------------------------------------------------------------
// Dialogs
// -----------------------------------------------------------------------------

  newDialog: function(element)
  {
    if (this.backgroundElements.length == 0)
    {
      $('html').css('overflow', 'hidden');
    }
    
    this.showBackgroundElement();
    return this.showDialogElement(this.newDialogElement(element));
  },

  hideDialog: function(callback)
  {
    this.hideDialogElement(callback);
    this.hideBackgroundElement();
    
    if (this.backgroundElements.length == 0)
    {
      $('html').css('overflow', 'visible');
    }
  },


// -----------------------------------------------------------------------------
// Forms
// -----------------------------------------------------------------------------
  
  toggleFieldsets: function(element)
  {
    var fieldsets = $(element).find('fieldset');
    
    fieldsets.each(function()
    {
      $(this).addClass('collapsed').children().hide();
      $(this).find('legend').css('cursor', 'pointer').show();
    });
    
    fieldsets.find('legend').click(function()
    {
      var parent = $(this).parent();
      
      if (parent.hasClass('collapsed'))
      {
        parent.removeClass('collapsed');
        parent.children().show();
      }
      else
      {
        parent.addClass('collapsed');
        parent.children().hide();
        $(this).show();
      }
    });
  },
  
  showForm: function(url, data, callback)
  {
    return this.newDialog(
      $('<form action="' + url + '" method="post" class="formDialog"/>').css({
        opacity: this.formDialogOpacity
      }).css(this.isIE6()
        ? { position: 'absolute', width: '60em', height: '30em',
            top: '2em', left: '50%', 'margin-left': '-31em' }
        : { top: '2em', bottom: '2em', left: '2em', right: '2em',
            position: 'fixed' }
      ).load(url, data, function()
      {
        if (dialog.collapseFieldsets) dialog.toggleFieldsets(this);
        if (callback != undefined) callback(this);
      }));
  },
  
  clearErrors: function()
  {
    this.dialogElement.find('div.field').each(function()
    {
      $(this).removeClass('error').find('.errorText').remove();
    });
  },
  
  processErrors: function(errors)
  {
    var firstError = null;
    
    this.clearErrors();
    for (var field in errors)
    {
      
      (function(error) {
        var errorElement = $('<div class="errorText"/>').html(error);
        
        dialog.dialogElement.find(':input[name=' + field + ']').each(function()
        {
          var parent = $(this).parent();
          parent.addClass('error').append(errorElement);
          
          if (firstError == null)
          {
            firstError = parent;
          }
        });
        
        var boxElements =
          dialog.dialogElement.find(':input[name="' + field + '[]"]');
        
        if (boxElements.length > 0)
        {
          var parent = $(boxElements[0]).parent().parent();
          parent.addClass('error').append(errorElement);
          
          var topParent = parent.parent().parent();
          if (topParent[0].nodeName == 'FIELDSET')
          {
            topParent.addClass('error');
          }
          
          if (firstError == null)
          {
            firstError = parent;
          }
        }
      })(errors[field]);
    }
    
    if (firstError != null) 
    {
      this.dialogElement.find('div.fields').scrollTo(firstError, 500);
    }
  },
  
  button: function(caption, classNames, callback)
  {
    return $('<a class="button" href="javascript:void(0)"/>').
      addClass(classNames).
      append($('<span/>').append(caption)).
      append($('<b/>')).
      click(callback);
  },
  
  buttons: function(buttonList, classNames)
  {
    var buttonsContainer = $('<div class="buttons"/>');
    
    if (classNames != undefined) buttonsContainer.addClass(classNames);
    
    for (var i in buttonList)
    {
      var button = buttonList[i];
      
      if (button['classNames'] == undefined) classNames = undefined;
      else classNames = button['classNames'];
      
      var buttonElement = this.button(
        button['caption'], classNames, button['callback'])
      
      if (button['style'] != undefined)
        buttonElement.attr('style', button['style']);
      
      buttonsContainer.append(buttonElement);
    }
    
    return buttonsContainer;
  },

// -----------------------------------------------------------------------------
// Messages
// -----------------------------------------------------------------------------
  
  messageDialog: function(message, classNames, buttons)
  {
    if (classNames == undefined) classNames = 'message';
    else classNames += ' message';
    
    if (buttons == undefined)
    {
      buttons = [{
        caption: text['generic']['close'],
        classNames: 'primary',
        callback: function() { dialog.hideDialog() }
      }];
    }
    
    return this.newDialog(
      $('<div/>').
        addClass(classNames).
        css({
          position: 'absolute',
          opacity: this.messageDialogOpacity
        }).
        append($('<p/>').html(message)).
        append(this.buttons(buttons, 'lowProfile')));
  },
  
  messageDialogAjax: function(url, data, classNames, buttons)
  {
    $.post(url, data, function(data)
    {
      dialog.messageDialog(data, classNames, buttons);
    });
  },
  
  confirm: function(message, callbackYes, callbackNo)
  {
    this.messageDialog(message, 'confirm', [{
      caption: text['generic']['yes'],
      classNames: 'primary first',
      callback: function() { dialog.hideDialog(callbackYes) }
    }, {
      caption: text['generic']['no'],
      classNames: 'last',
      callback: function() { dialog.hideDialog(callbackNo) }
    }]);
  },

// -----------------------------------------------------------------------------
// Progress
// -----------------------------------------------------------------------------

  loadingDialog: null,
  loadingDialogBackground: null,

  showLoadingDialog: function()
  {
    if (this.loadingDialog == null)
    {
      this.loadingDialog = this.messageDialog(
        text['generic']['loading'] + '...', 'progress', [{
          caption: text['buttons']['cancel'],
          callback: function()
          {
            dialog.cancelled = true;
            dialog.hideLoadingDialog();
            dialog.hideDialog();
          }
        }]);
      
      this.loadingDialogBackground =
        this.backgroundElements[this.backgroundElements.length-1];
      
      this.loadingDialogBackground.css('z-index', 200);
      this.loadingDialog.css('z-index', 201);
    }
  },
  
  hideLoadingDialog: function()
  {
    if (this.loadingDialog != null)
    {
      this.loadingDialogBackground.hide();
      this.loadingDialog.hide();
      
      for (var i in this.backgroundElements)
        if (this.backgroundElements[i] == this.loadingDialogBackground)
          this.backgroundElements.splice(i, 1);
      
      if (this.backgroundElements.length == 0)
        $('html').css('overflow', 'visible');
      
      for (var i in this.dialogElements)
        if (this.dialogElements[i] == this.loadingDialog)
          this.dialogElements.splice(i, 1);
      
      this.loadingDialogBackground = null;
      this.loadingDialog = null;
    }
  },

// -----------------------------------------------------------------------------
// Darkbox
// -----------------------------------------------------------------------------

  hideDarkbox: function(callback)
  {
    this.hideDialog(callback);
  },

  showDarkbox: function(name, index)
  {
    this.showLoadingDialog();
    
    var
      anchors = this.darkboxes[name],
      buttons = [{
        caption: text['generic']['close'],
        callback: function() { dialog.hideDarkbox() }
      }];
    
    if (anchors.length > 1)
    {
      var
        buttonPrevious = {
          caption: text['generic']['previous'],
          callback: function()
          {
            dialog.hideDarkbox(function()
            {
              dialog.showDarkbox(name, index - 1);
            });
          }
        },
        buttonNext = {
          caption: text['generic']['next'],
          callback: function()
          {
            dialog.hideDarkbox(function()
            {
              dialog.showDarkbox(name, index + 1);
            });
          }
        };
      
      if (index == 0)
      {
        buttons.push(buttonNext);
      }
      else if (index == anchors.length - 1)
      {
        buttons.push(buttonPrevious);
      }
      else
      {
        buttonPrevious.classNames = 'first';
        buttons.push(buttonPrevious);
        
        buttonNext.classNames = 'last';
        buttons.push(buttonNext);
      }
    }
    
    var image = $('<img/>').attr('src', anchors[index].href);
    
    if (!this.cancelled) 
    {
      this.hideLoadingDialog();
      
      var darkbox = this.newDialog($('<div class="darkbox"/>').css({
        top: '50%',
        left: '50%',
        position: this.getFloatingPosition(),
        visibility: 'hidden'
      }).append(image).append(this.buttons(buttons, 'lowProfile')));
      
      if (dialog.darkboxMargins[name] != undefined && dialog.darkboxMargins[name][index] != undefined) 
      {
        darkbox.css({
          margin: dialog.darkboxMargins[name][index],
          visibility: 'visible'
        });
      }
      else 
      {
        image.load(function()
        {
          if (dialog.darkboxMargins[name] == undefined) 
            dialog.darkboxMargins[name] = [];
          
          dialog.darkboxMargins[name][index] =
            '-' + parseInt((image.height() / 2) + 20, 10) + 'px 0 0 ' +
            '-' + parseInt(image.width() / 2, 10) + 'px';
          
          darkbox.css({
            margin: dialog.darkboxMargins[name][index],
            visibility: 'visible'
          });
        });
      }
      
      this.backgroundElements[this.backgroundElements.length - 1].click(function()
      {
        dialog.hideDarkbox();
      });
    }
    else
    {
      this.cancelled = false;
    }
  },
  
  darkboxAppend: function(name, anchor)
  {
    this.darkboxes[name].push(anchor);
    
    (function(index)
    {
      $(anchor).click(function()
      {
        if (!$(this).hasClass('disabled')) 
        {
          dialog.showDarkbox(name, index);
        }
        return false;
      });
    })(dialog.darkboxes[name].length - 1);
  },

  darkbox: function(name, anchors)
  {
    this.darkboxes[name] = anchors;
    
    $(anchors).each(function(i)
    {
      $(this).click(function(event)
      {
        if (!$(this).hasClass('disabled')) 
        {
          dialog.showDarkbox(name, i);
        }
        event.preventDefault();
      });
    });
  }
}
