var SL = SL || {};


SL.easySlide = function (evt, sliderKey, direction) {
	evt = new Event(evt).stop();
	var slider = SL.Registry.get('sl.easysliders.'+sliderKey)[0];

	if (slider){
		slider.slide(direction);
	}
};




/** section: Impl
 * SL.Overlay(event, options)
 *     - evt (Event): A link's click event
 *     - options (Object): _(Optional)_ set of options, to pass to the underlying [SL.ModalDialog.Ajax])
 *
 * Creates a new overlay, centeres it and stores the instance in the registry.
**/ 
SL.Overlay = function(evt, options)
{
	evt = new Event(evt).stop();
	options = $merge({
		'target': document.body,
		'message': 'Einen Moment, die Daten werden geladen',
		'fxOptions': {
			'duration': '300'
		},
		'url': SL._fetchEventUrl(evt)
	}, options || {});

	var overlay = new SL.ModalDialog.Ajax(options.url, options.target, options).show();
	SL.Registry.add('activeDialog', overlay);

	overlay.addEvent('hide', function(){
		SL.Registry.remove('activeDialog')[0];
	});

	return overlay;
}


/** section: Impl
 * SL.Overlay.staticContent(event, html, options)
 *     - event (Event): A link's click event
 *     - html (String): html content
 *     - options (Object): _(Optional)_ set of options, to pass to the underlying [SL.ModalDialog])
 *
 * Creates a new overlay with the given static html content, centeres it and stores the instance in the registry.
**/ 
SL.Overlay.staticContent = function(event, html, options) {
	event = new Event(event).stop();
	var overlay = new SL.ModalDialog(null, $merge({
		'messageContainer': {
			'html': html
		}
	}, options)).show();
	SL.Registry.add('activeDialog', overlay);
	
	overlay.addEvent('hide', function(){
		SL.Registry.remove('activeDialog')[0];
	});
}


/** section: Impl
 * SL.Overlay.hide(evt, options)
 *     - evt (Event): A link's click event
 *
 * Hides and destroys the active overlay.
**/
SL.Overlay.hide = function(evt)
{
	evt = new Event(evt).stop();
	SL.Registry.remove('activeDialog')[0].hide();
}



/** section: Impl
 * SL.Overlay.update(evt, options)
 *     - evt (Event): A link's click event
 *     - options (Object): _(Optional)_ set of options, to pass to the underlying [SL.ModalDialog.Ajax])
 *
 * Updates the content of the active overlay with content read from a given url,
**/
SL.Overlay.update = function(evt, options)
{
	evt = new Event(evt).stop();
	var dialog = SL.Registry.get('activeDialog')[0];
	if (!dialog) return;
	options = $merge({
		'fxOptions': {
			'duration': '1000'
		}
	}, options || {});

	var url = SL._fetchEventUrl(evt);
	dialog.updateContent(url, options);
}



/** section: Impl
 * SL.Overlay.post(evt, options)
 *     - evt (Event): A forms onsubmit event
 *     - options (Object): _(Optional)_ set of options, to pass to the underlying [SL.ModalDialog.Ajax] )
 *
 * Updates the content of the active overlay with content read from a given url using a post request.
**/
SL.Overlay.post = function(evt, options)
{
	evt = new Event(evt).stop();
	var dialog = SL.Registry.get('activeDialog')[0];
	if (!dialog) return;

	options = $merge({
		'fxOptions': {
			'duration': '1000'
		},
		'formElement': evt.target
	}, options || {});
	var url = SL._fetchEventUrl(evt);
	dialog.postAndUpdateContent(url, options);
}



/** section: Impl
 * class SL.Tab
 * includes Options
 * 
 * Handles tabbed content.
 * 
 **/

/** section: Impl
 * SL.Tab(options)
 *     - options (Object): _(Optional)_ set of options

 * ##### Options
 * - `tabLinksSelector` (`String`): The CSS selector to determine the tab links (default: `a`)
 * - `tabListKey` (`String`): The ID of the tab links container element.
**/ 
SL.Tab = new Class({
	
	Implements: [Options, Events],

	options: {
		'tabLinksSelector': 'a'
	},

	tabList: null,
	tabContent: $A([]),

	initialize: function (tabList, options) {
		this.setOptions(options);
		this.options = $merge(this.options, options);
		this.tabList = document.id(tabList);
		this.tabLinks = this.tabList.getElements(this.options.tabLinksSelector);
		this.spinnerTarget = this.options.spinnerTarget || document.id('contentOverlayInner');

		this.tabLinks.each(function(tab)
		{
			// collect and cache the content boxes
			this.tabContent[tab.get('rel')] = document.id(tab.get('rel'));
			tab.addEvent('click', function(evt)
			{
				this.observeTab(evt);
			}.bind(this));
		}.bind(this));
	},


	/**
	 * SL.Tab#observeTab(evt)
	 *     - evt (Object): the event of the clicked tab link
	 * 
	 * when needed, gets the content of the clicked tab
	**/
	observeTab: function(evt)
	{
		evt = new Event(evt).stop();
		var target = evt.target;
		var rel = target.get('rel');
		var url = target.get('href');

		if (rel !== '')
		{
			var content = this.tabContent[rel];
			if (content)
			{
				if (url && url != '#' && content.innerHTML == '')
				{
					(new SL.ElementUpdater(url, content, {
						'spinnerTarget': this.spinnerTarget,
						'onSuccess': function()
						{
							if($defined(this.options.onReloadTab)) {
								this.options.onReloadTab.run(evt);
							}
							this.changeTab(target, content);
						}.bind(this)
					})).get();
				}
				else
				{
					if($defined(this.options.onChangeTab)) {
						this.options.onChangeTab.run(evt);
					}
					this.changeTab(target, content);
				}
			}
		}
	},
	

	/**
	 * SL.Tab#changeTab(evt)
	 *     - target (Element): the clicked tab link
	 *     - content (Element): the content tab
	 * 
	 * hides the actually visible tab content and shows the clicked tab content
	**/
	changeTab: function(target, content)
	{		
		// hide/deactivate (old) active tab
		var activeTab = this.tabList.getElement('.active');
		if($defined(activeTab)) {
			this.tabContent[activeTab.getChildren('a')[0].get('rel')].addClass('hide');
			activeTab.removeClass('active');
		}

		// show/activate clicked tab
		target.getParent().addClass('active');
		content.removeClass('hide');

		if (SL.Registry.has('activeDialog')) SL.Registry.get('activeDialog')[0].adaptSize();
	}

});



/** section: Impl
 * SL.StartupTabs() -> undefined
 *   - settings (`Object`): options as defined by [[SL.Tab]]
 *
**/
SL.StartupTabs = function(settings)
{
	if (!settings.tabListKey) return;
	var tabListKey = settings.tabListKey;
	delete settings['tabListKey'];
	var tab = new SL.Tab(tabListKey, settings);
	SL.Registry.add('sl.tabs.'+tabListKey, {tabListKey: tab});
}



/** section: Impl
 * SL.TabSetup() -> undefined
 * 
 * Uses [[Startups]] namespaces:
 * - `sl.startups.tabs` for the Tab settings. A single registry value is
 *   - setting (`Object`): options as defined by [[SL.Tab]]
 *
**/
SL.TabSetup = function () {
	SL.Registry.get('sl.startups.tabs').each(function (settings){
		SL.StartupTabs(settings);
	});
};
SL.Registry.add('sl.impl.startups', SL.TabSetup);






/** section: Impl
 * SL.FlyOut(options)
 *     - options (Object): _(Optional)_ set of options
 *
 * Handles flyouts, content which will be shown when another element is hovered or clicked
 *
 * ##### Options
 * - `linkKey` (`String`): The ID of the link
 * - `contentKey` (`String`): The ID of the content element which will be shown/hidden.
**/ 
SL.FlyOut = new Class({
	
	Implements: [Options, Events],

	options: {
		userEvent: 'hover',
		clickCancelElement: document
	},

	link: null,
	content: null,

	initialize: function (options) {

		this.setOptions(options);
		this.link = document.id(this.options.linkKey);
		this.content = document.id(this.options.contentKey);
		this.clickCancelElement = (this.options.clickCancelElement !== false) ? document.id(this.options.clickCancelElement) : false;

		if (!this.content || !this.link) return;

		switch(this.options.userEvent)
		{
			case 'click':
				if(this.clickCancelElement) {
					var observeDoc = function (evt)
					{
						evt = new Event(evt).stop();
						this.content.addClass('hide');
						this.clickCancelElement.removeEvent('click',boundDocObserver);
					}
					var boundDocObserver = observeDoc.bind(this);
				}

				this.link.addEvent('click', function(evt)
				{
					evt = new Event(evt).stop();
					if (this.clickCancelElement && this.content.hasClass('hide')) {
						this.clickCancelElement.addEvent('click',boundDocObserver);
					}
					this.content.toggleClass('hide');
				}.bind(this));
				break;
			case 'checkboxToggle':
				this.link.addEvent('click', function(evt) {
					this.content.toggleClass('hide');
				}.bind(this));
				break;
			default:
			case 'hover':
				this.content.addEvents({
					'mouseleave': function(evt)
					{
						evt = new Event(evt).stop();
						this.content.addClass('hide');
					}.bind(this)
				});
				this.link.addEvents({
					'mouseenter': function(evt)
					{
						evt = new Event(evt).stop();
						this.content.removeClass('hide');
					}.bind(this),
					'mouseleave': function(evt)
					{
						evt = new Event(evt).stop();
						var coord = this.content.getCoordinates();
						if (evt.event.clientX < coord.left || evt.event.clientX > coord.right || evt.event.clientY < coord.top || evt.event.clientY > coord.bottom) {
							this.content.addClass('hide');
						}
					}.bind(this)
				});
				break;
		}
	}

});

SL.FlyOutSetup = function () {
	SL.Registry.get('sl.startups.flyouts').each(function (settings){
		var contentKey = settings.contentKey;
		var flyOut = new SL.FlyOut(settings);
		SL.Registry.add('sl.flyouts.'+contentKey, {contentKey: flyOut});
	});
};
SL.Registry.add('sl.impl.startups', SL.FlyOutSetup);



SL.ScrollbarSetup = function() {
	SL.Registry.get('sl.startups.scrollbars').each(function (settings){
		var contentKey = settings.contentKey;
		var scrollContainer  = settings.scrollContainer;
		var scrollBar        = settings.scrollBar;
		var scrollKnob       = settings.scrollKnob;
		var scrollbar = new ScrollBar(scrollContainer, scrollBar, scrollKnob, settings);
		SL.Registry.add('sl.scrollbars.'+contentKey, {contentKey: scrollbar});
	});
}
SL.Registry.add('sl.impl.startups', SL.ScrollbarSetup);


/** section: Impl
 * SL.TagboxSetup() -> undefined
 *   - settings (`Object`): options as defined in vendor/slTag.js
 *
**/
SL.TagboxSetup = function()
{
	SL.Registry.get('sl.startups.tagbox').each(function (settings){
		SL.Registry.add('sl.tagbox.'+settings.id, new slTag(settings));
	});
}
SL.Registry.add('sl.impl.startups', SL.TagboxSetup);

