window.addEvent('domready', function() {
  var ConfigurationPanel = new Class({
    Implements: [Events, Options],
    options: {
      container: 'userConfig', collapsiblePane: '.collapsiblePane',
      configButtonContainer: '.configButtons', configButtons: { open: '.openConfigLink, .closeConfigLink', reset: '.resetConfigLink' },
      onOpen: function () { this.togglePane(); }, onReset: $empty, onAfterInit: $empty, onTogglePane: function (button) { button.swapClasses('openConfigLink', 'closeConfigLink'); }
    },
    initialize: function (options) {
      this.setOptions(options);
      this.initializeButtons();
      this.collapsiblePane = $(this.options.container).removeClass('notDisplayed').show().getElement(this.options.collapsiblePane).removeClass('notDisplayed').setStyle('display', 'inline').hide();
      this.fireEvent('afterInit');
    },
    initializeButtons: function () {
      this.configButtonContainer = $(this.options.container).getElement(this.options.configButtonContainer);
      $each(this.options.configButtons, function (value, key) {
        var button = this.configButtonContainer.getElement(value);
        if ($defined(button)) button.addEvent('click', function (e) { this.fireEvent(key, [button]); e.stop(); button.blur(); }.bind(this));
      }, this);
      return this;
    },
    togglePane: function () {
      if (trident() === 4) {
        this.collapsiblePane.isDisplayed() ? this.collapsiblePane.hide() : this.collapsiblePane.show();
      } else { this.collapsiblePane.get('reveal').toggle(); }
      this.fireEvent('togglePane', this.configButtonContainer.getElement(this.options.configButtons.open));
      return this;
    }
  });
  
  var ListItemNumberManager = new Class({
    Implements: Options,
    options: {
      itemSelector: '.content ul li', displayedElements: { min:1, max:6, std:3 }, cookie: $empty, cookieKey: $empty, 
      hiddenListItemClass: 'temporarilyHidden', buttonSelectors: { plus: 'span.plusBtn', minus: 'span.minusBtn' },
      disabledButtonClasses: { plus: 'disabledPlusBtn', minus: 'disabledMinusBtn' }, buttonContainer: $empty
    },
    initialize: function(widgets, options) {
      this.setOptions(options);
      this.initializeWidgets(widgets);
    },
    initializeButtons: function(widget) {
      var plusBtn = new Element('span', { 'class': 'plusBtn' }).addEvent('click', function(e) { this.increaseListItemNumber(widget, e); }.bind(this));
      var minusBtn = new Element('span', { 'class': 'minusBtn' }).addEvent('click', function(e) { this.decreaseListItemNumber(widget, e); }.bind(this));
      this.options.buttonContainer.adopt(minusBtn, plusBtn);
    },
    initializeWidgets: function() {
      Array.flatten(arguments).each(function(widget) {
        this.initializeWidget(widget);
      }, this);
    },
    initializeWidget: function(widget) {
      this.initializeButtons(widget);
      var listItems = widget.getElements(this.options.itemSelector);
      if (!this.options.cookie.has(this.options.cookieKey) || 
        (this.options.cookie.has(this.options.cookieKey) && !$H(this.options.cookie.get(this.options.cookieKey)).has(widget.get('id')))
      ) {
        // the homepage is either not personalized OR the widget's list item number has not been saved yet
        // so we first only show the standard list item number by hiding the ones after that
        if (listItems.length > this.options.displayedElements.std) {
          $each(listItems.slice(this.options.displayedElements.std), function(el) { el.addClass(this.options.hiddenListItemClass).hide(); }.bind(this));
        }
        // and we disable the plus button in case there are not more than these to display
        if (listItems.length <= this.options.displayedElements.std) {
          widget.getElement(this.options.buttonSelectors.plus).addClass(this.options.disabledButtonClasses.plus);
        }
      } else {
        // the widget has a defined list item number
        // so get the saved number
        var cookieNbDisplayedElements = $H(this.options.cookie.get(this.options.cookieKey)).get(widget.get('id'));
        // but look out in case there aren't enough list items to display
        if (listItems.length > cookieNbDisplayedElements) {
          $each(listItems.slice(cookieNbDisplayedElements), function(el) { el.addClass(this.options.hiddenListItemClass).hide(); }.bind(this));
        } else {
          widget.getElement(this.options.buttonSelectors.plus).addClass(this.options.disabledButtonClasses.plus);
        }
        if (cookieNbDisplayedElements == this.options.displayedElements.min) { widget.getElement(this.options.buttonSelectors.minus).addClass(this.options.disabledButtonClasses.minus); }
        if (cookieNbDisplayedElements == this.options.displayedElements.max) { widget.getElement(this.options.buttonSelectors.plus).addClass(this.options.disabledButtonClasses.plus); }
      }
    },
    increaseListItemNumber: function(widget, e) {
      var hiddenListItems = widget.getElements(this.options.itemSelector + '.' + this.options.hiddenListItemClass);
      var shownListItems = widget.getElements(this.options.itemSelector).filter(function(li) { return !li.hasClass(this.options.hiddenListItemClass); }.bind(this));
      if (shownListItems.length < this.options.displayedElements.max && hiddenListItems.length > 0) {
        hiddenListItems[0].removeClass(this.options.hiddenListItemClass).reveal();
        e.target.getParent().getElement(this.options.buttonSelectors.minus).removeClass(this.options.disabledButtonClasses.minus);
        var currentNbDisplayedElements = shownListItems.length + 1;
        if ((currentNbDisplayedElements == this.options.displayedElements.max) || (hiddenListItems.length == 1)) {
          e.target.addClass('disabledPlusBtn');
        }
        this.saveCurrentListItemNumber(widget, currentNbDisplayedElements);
      }
    },
    decreaseListItemNumber: function(widget, e) {
      var shownListItems = widget.getElements(this.options.itemSelector).filter(function(li) { return !li.hasClass(this.options.hiddenListItemClass); }.bind(this));
      if (shownListItems.length > this.options.displayedElements.min) {
        shownListItems[shownListItems.length - 1].addClass(this.options.hiddenListItemClass).dissolve();
        e.target.getParent().getElement(this.options.buttonSelectors.plus).removeClass(this.options.disabledButtonClasses.plus);
        var currentNbDisplayedElements = shownListItems.length - 1;
        if (currentNbDisplayedElements == this.options.displayedElements.min) { e.target.addClass(this.options.disabledButtonClasses.minus); }
        this.saveCurrentListItemNumber(widget, currentNbDisplayedElements);
      }
    },
    saveCurrentListItemNumber: function(widget, nb) {
      mySortables.saveNbDisplayElementsOption(widget.get('id'), nb);
    }
  });

  Sortables.Cookie = new Class({
    Extends: Sortables,
    Implements: [Chain],
    Binds: ['saveWidgetOrder', 'isWidgetClosable'],
    options: { onToggleWidget: $empty },
    effects: {},
    initialize: function(options) {
      this.cookie = new Hash.Cookie(options.cookie.name, options.cookie.options);
      this.setHTMLWidgetOrder(options);
      this.loadWidgetOrder(options);
      this.parent(options.lists, options);
      this.updateColumnHeight();
      window.addEvent('load', this.updateColumnHeight.bind(this));
    },
    addLists: function() {
      Array.flatten(arguments).each(function(list) {
        this.lists.push(list);
        var allWidgets = this.getAllWidgetsInList(list);
        this.addItems(this.getMovableWidgetsInList(allWidgets));
        this.configureWidgetOptionsBar(allWidgets);
      }, this);
      return this;
    },
    getAllWidgetsInList: function(list) {
      return list.getElements('div.home-widget');
    },
    getMovableWidgetsInList: function(widgets) {
      return widgets.filter(function(el) { return this.isWidgetMovable(el); }, this);
    },
    getClosableWidgetsInList: function(list) {
      return this.getAllWidgetsInList(list).filter(function(el) { return this.isWidgetClosable(el); }, this);
    },
    getVisibleWidgetsInList: function(list) {
      return this.getAllWidgetsInList(list).filter(function(widget) { return widget.isDisplayed(); });
    },
    isWidgetClosable: function(widget) {
      return widget.hasClass(this.options.optionsBarClasses.closable);
    },
    isWidgetMovable: function(widget) {
      return !widget.hasClass(this.options.optionsBarClasses.fixed);
    },
    getDroppables: function() {
      var droppables = this.getMovableWidgetsInList(this.getAllWidgetsInList(this.list));
      if (!this.options.constrain) { droppables = this.lists.concat(droppables).erase(this.list); }
      return droppables.erase(this.clone).erase(this.element);
    },
    configureWidgetOptionsBar: function(widgets) {
      var blanket = new Element('div', { 'class': 'blanket_for_javascript', 'styles': {
        'position': 'absolute', 'left': 0, 'top': 0, 'z-index': 1000, 'height': '100%', 
        'width': '100%', 'background-color': '#022145'
      }}).hide();
      widgets.each(function(widget) {
        if (this.isWidgetMovable(widget)) {
          (widget.getElement(this.options.handle) || widget).setStyle('cursor', 'move');
          if (!widget.hasClass(this.options.closedWidgetClass)) widget.setStyle('position', 'relative');
          var newBlanket = blanket.clone();
          if (trident() === 4) newBlanket.setStyle('height', widget.getDimensions().height);
          newBlanket.inject(widget, 'top');
        }
        var optionsBar = widget.getElement('.' + this.options.optionsBarClasses.container);
        if ($defined(optionsBar)) {
          optionsBar.removeClass('notDisplayed');
          if (this.isWidgetClosable(widget)) {
            optionsBar.grab(
              new Element('a', { 'class': 'closeBtn' })
              .addEvents({
                'click': function() { this.closeWidget(widget); }.bind(this),
                'mouseenter': function(e) { e.target.addClass('closeBtnHover'); },
                'mouseleave': function(e) { e.target.removeClass('closeBtnHover'); }
              })
            , 'top');
          }
          if (widget.hasClass(this.options.optionsBarClasses.changeNbOfDisplayedElements)) {
            new ListItemNumberManager(widget, { cookie: this.cookie, cookieKey: this.options.cookie.nbDisplayedElementsKey, buttonContainer: optionsBar });
          }
        }
      }, this);
      blanket = null;
      return this;
    },
    loadWidgetOrder: function(options) {
      if (!this.cookie.has(options.cookie.sortOrderKey)) { return; }
      this.cookie.get(options.cookie.sortOrderKey).each(function(widgetColumn, columnIndex) {
        widgetColumn.reverse().each(function(widgetId) {
          if (!$(widgetId)) { return; }
          var widget = $(widgetId);
          var widgetColumnElement = $$(options.lists[columnIndex])[0];
          widget.inject(widgetColumnElement, 'top');
          if (this.cookie.has(options.cookie.closedWidgetsKey) && this.cookie.get(options.cookie.closedWidgetsKey).contains(widgetId)) {
            widget.addClass(options.closedWidgetClass);
          }
        }, this);
      }, this);
    },
    setHTMLWidgetOrder: function(options) {
      var names = ['.configColInformation', '.configColMultimedia', '.configColOther'].map(function(configColumn) {
        return $$('.home-widget' + configColumn).map(function(widget) { return widget.hasClass(options.optionsBarClasses.closable) ? widget.get('id') : null; });
      });
      this.HTMLWidgetOrder = names;
    },
    saveWidgetOrder: function() {
      this.cookie.set(this.options.cookie.sortOrderKey, this.serialize());
      this.cookie.save();
    },
    saveNbDisplayElementsOption: function(widgetId, value) {
      this.cookie.set(this.options.cookie.nbDisplayedElementsKey, $H(this.cookie.get(this.options.cookie.nbDisplayedElementsKey)).set(widgetId, value));
      this.saveWidgetOrder();
    },
    resetWidgetOrder: function() { this.cookie.dispose(this.options.cookie.name); },
    saveWidgetCloseOption: function(widget, close) {
      var currentlyClosedWidgets = this.cookie.get(this.options.cookie.closedWidgetsKey) || new Array();
      if (close) { currentlyClosedWidgets.include(widget.get('id')); } else { currentlyClosedWidgets.erase(widget.get('id')); }
      this.cookie.set(this.options.cookie.closedWidgetsKey, currentlyClosedWidgets);
      this.saveWidgetOrder();
    },
    closeWidget: function(widget) {
      if (trident() === 4) { widget.hide(); } else {
        if (this.currentId == widget.get('id')) return false;
        this.currentId = widget.get('id');
        widget.get('reveal', { onComplete: function() {
          this.currentId = null;
          this.updateColumnHeight();
        }.bind(this) }).dissolve();
      }
      this.saveWidgetCloseOption(widget, true);
      this.fireEvent('toggleWidget', [widget, false]);
      return true;
    },
    openWidget: function(widget) {
      if (this.currentId == widget.get('id') && trident() !== 4) return false;
      var visibleWidgets = this.getVisibleWidgetsInList($$(this.options.lists[1])[0]);
      // 1. no widgets in center column => inject at the top of the center column
      if (visibleWidgets.length == 0) { widget.inject($$(this.options.lists[1])[0], 'top'); }
      else {
        var movableWidgets = this.getMovableWidgetsInList(visibleWidgets);
        // 2. only fixed widgets in center column => inject after all the fixed widgets, in other words: inject at the bottom of the center column
        if (movableWidgets.length == 0) {
          widget.inject($$(this.options.lists[1])[0], 'bottom');
        } else {
          // 3. at least one movable widget in center column => inject before the first movable widget
          widget.inject(movableWidgets[0], 'before');
        }
      }
      widget.removeClass(this.options.closedWidgetClass);
      if (trident() === 4) { widget.show(); } else {
        this.currentId = widget.get('id');
        widget.get('reveal', { onComplete: function() {
          this.currentId = null;
          widget.setStyles({ 'position': 'relative', 'margin-bottom': '0.6666em' });
          this.updateColumnHeight();
        }.bind(this) }).reveal();
      }
      this.saveWidgetCloseOption(widget, false);
      this.fireEvent('toggleWidget', [widget, true]);
      return true;
    },
    updateColumnHeight: function() {
      // dynamically set the height of all widget containers to the height of the tallest widget container
      var lists = $$(this.lists);
      var listHeights = lists.map(function (list) {
        list.setStyle('min-height', 0);
        if (trident() === 4) list.setStyle('height', 0);
        return list.getDimensions().height;
      });
      var maxHeight = listHeights.max();
      var compensation = 0, olympiaHighlightHeight = 0;
      /* don't use ID here, could be something else on the live system */
      var olympiaHighlightsWidget = $('olympia_highlights');
      if ($chk(olympiaHighlightsWidget)) { olympiaHighlightHeight = olympiaHighlightsWidget.getParent().getDimensions().height; }
      if (listHeights[0] == maxHeight) { /* left column is tallest, subtract Olympia highlight widget height from center and right column height */
        listHeights[1] = maxHeight - olympiaHighlightHeight;
        listHeights[2] = maxHeight - olympiaHighlightHeight;
      } else { /* center or right column is tallest, add Olympia highlight widget height to left column height */
        listHeights[0] = maxHeight + olympiaHighlightHeight;
        listHeights[1] = maxHeight;
        listHeights[2] = maxHeight;
      }
      $each(lists, function (list, index) {
        list.setStyle('min-height', this[index]);
        if (trident() === 4) list.setStyle('height', this[index]);
      }, listHeights);
    }
  });
  
  var PictureChanger = new Class({
    Implements: [Events, Options],
    Binds: ['advance', 'timedAdvance'],
    options: {
      widget: $('olympia_highlights'), highlightedListItemClass: 'highlightListItem', 
      listItemContainer: '.content', listItemSelector: 'ul li', bigPictureSelector: 'img[id$=_bild]'
    },
    initialize: function(options) {
      this.setOptions(options);
      if (!$chk(this.options.widget)) { return; }
      this.initializeListItems();
      this.currentListItem = 0;
      $$(this.listItems[this.currentListItem].addClass(this.options.highlightedListItemClass).getParent(this.options.listItemContainer).getElements(this.options.bigPictureSelector).slice(1)).addClass('notDisplayed');
      this.advanceTimerStarted = false;
      this.startAutomaticAdvance();
    },
    initializeListItems: function() {
      this.listItems = this.options.widget.getElement(this.options.listItemContainer).getElements(this.options.listItemSelector);
      this.listItems.each(function(listItem, i) {
        listItem.addEvents({
          'mouseenter': function() { this.stopAutomaticAdvance().advance(listItem); }.bind(this),
          'mouseleave': function() { this.startAutomaticAdvance(i); }.bind(this)
        });
      }.bind(this));
      return this;
    },
    startAutomaticAdvance: function(index) {
      if (this.advanceTimerStarted) return;
      if ($defined(index)) {
        this.listItems[index].addClass(this.options.highlightedListItemClass);
        this.currentListItem = index;
      }
      this.advanceTimerStarted = true;
      this.advanceTimer = this.timedAdvance.periodical(5000);
    },
    stopAutomaticAdvance: function() {
      $clear(this.advanceTimer);
      this.listItems[this.currentListItem].removeClass(this.options.highlightedListItemClass);
      this.advanceTimerStarted = false;
      return this;
    },
    advance: function(listItem) {
      if ($defined(corresponding_picture = listItem.getParent(this.options.listItemContainer).getElement('#' + listItem.get('id') + '_bild'))) {
        corresponding_picture.removeClass('notDisplayed');
        listItem.getParent(this.options.listItemContainer).getElements(this.options.bigPictureSelector).erase(corresponding_picture).addClass('notDisplayed');
      }
    },
    timedAdvance: function() {
      var lastHighlightedItem = this.currentListItem;
      this.currentListItem = (this.currentListItem === this.listItems.length - 1) ? 0 : this.currentListItem + 1;
      this.listItems[lastHighlightedItem].removeClass(this.options.highlightedListItemClass);
      this.listItems[this.currentListItem].addClass(this.options.highlightedListItemClass);
      this.advance(this.listItems[this.currentListItem]);
    }
  });

  var mySortables = new Sortables.Cookie({
    lists: ['.home-colLeft', '.home-colCenter', '.home-colRight'],
    cookie: { name: 'vancouver_homepage', sortOrderKey: 'sort_order', closedWidgetsKey: 'closed_widgets', 
    nbDisplayedElementsKey: 'nb_displayed_elements', options: { duration: 3600, autoSave: false } },
    closedWidgetClass: 'closed_widget', clone: true, revert: true, opacity: 1, handle: '.header, .header .banner_widget_handle', snap: 1,
    optionsBarClasses: { container: 'optionsBar', fixed: 'fixed', closable: 'closable', changeNbOfDisplayedElements: 'plusminusBtns' },
    onStart: function (widget, clone) {
      widget.getElement('.blanket_for_javascript').show();
      if (trident() === 4) widget.setStyle('visibility', 'hidden');
      clone.set('id', widget.get('id')).setStyle('z-index', 2000);
    },
    onComplete: function (widget) {
      this.saveWidgetOrder();
      widget.getElement('.blanket_for_javascript').hide();
      if (trident() === 4) widget.setStyle('visibility', 'visible');
      this.updateColumnHeight();
    }
  });
  
  var ConfigurationPanelHomepage = new Class({
    Extends: ConfigurationPanel,
    options: { onConfigSwitchedOn: $empty, onConfigSwitchedOff: $empty },
    initialize: function (options) {
      this.initializeConfigColumns(options).parent(options);
      mySortables.addEvent('toggleWidget', function (widget, open) { this.toggleSwitch(widget.get('id'), (open) ? true : false); }.bind(this));
    },
    initializeConfigColumns: function (options) {
      mySortables.HTMLWidgetOrder.each(function (columnContainer, i) {
        var configColumnSwitchContainer = $(options.container).getElement(options.configColumns[i]).getElement(options.configColumnSwitchContainer).empty();
        columnContainer.each(function (widgetId) {
          if ($defined(widgetId)) {
            configColumnSwitchContainer.adopt(options.buildConfigColumnSwitch($(widgetId), this, options));
          }
        }, this);
      }, this);
      return this;
    },
    toggleSwitch: function(stateSwitch, enable) {
      if ($type(stateSwitch) == 'string') stateSwitch = this.collapsiblePane.getElement('#check_' + stateSwitch).getParent();
      if (enable) stateSwitch.swapClass(this.options.configColumnStateClasses.disabled, this.options.configColumnStateClasses.enabled);
      else stateSwitch.swapClass(this.options.configColumnStateClasses.enabled, this.options.configColumnStateClasses.disabled);
    }
  });
  
  var collapsiblePane = new ConfigurationPanelHomepage({
    container: 'userConfig',
    configColumns: ['.configColInformation', '.configColMultimedia', '.configColOther'], configColumnSwitchContainer: 'ul',
    configColumnStateClasses: { enabled: 'enabled', disabled: 'disabled' },
    onReset: function () {
      mySortables.resetWidgetOrder();
      window.location.reload();
    },
    onConfigSwitchedOn: function (stateSwitch, button) { mySortables.openWidget($(button.get('for').replace('check_', ''))); },
    onConfigSwitchedOff: function (stateSwitch, button) { mySortables.closeWidget($(button.get('for').replace('check_', ''))); },
    buildConfigColumnSwitch: function (forWidget, object, options) {
      var widget = $(forWidget);
      var cornerLeft = new Element('span', { 'class': 'cornerLeft' });
      var cornerRight = new Element('span', { 'class': 'cornerRight' });
      return (new Element('li', { 'class': (widget.hasClass(mySortables.options.closedWidgetClass) ? options.configColumnStateClasses.disabled : options.configColumnStateClasses.enabled) })
        .adopt(
          cornerLeft.clone(), cornerRight.clone(),
          new Element('input', { 'type': 'checkbox', 'value': 'e', 'id': 'check_' + widget.get('id'), 'name': 'check_' + widget.get('id') }), 
          new Element('label', { 'for': 'check_' + widget.get('id'), 'text': widget.getElement('h2 span').get('text').replace('Widget-Vorlage :: ', '') }),
          new Element('span', { 'class': 'footer' }).adopt(cornerLeft.clone(), cornerRight.clone())
        )
        .addEvent('click', function (e) {
          this.fireEvent('configSwitched' + (e.target.getParent().hasClass(options.configColumnStateClasses.enabled) ? 'Off' : 'On'), [e.target.getParent(), e.target]);
          e.stop(); e.target.blur();
        }.bind(object))
      );
    }
  });
  
  var topnachrichtenPictureChanger = new PictureChanger();
});