var Widget = new Class({

	Implements: [Options, Events],

	options: {},

	initialize: function(options){
		this.setOptions(options);
		this.assignEvents();
	},

	assignEvents: function(){}

});

Widget.Focussed = new Class({

	Extends: Widget,

	options: {
		onFocus: function(container){
			container.addClass('focus');
		},
		onBlur: function(container){
			container.removeClass('focus');
		}
	},

	initialize: function(options){
		this.parent(options);
	},

	toggleFocus: function(state, container){
		this.fireEvent(state ? 'onFocus' : 'onBlur', container);
	}

});

Widget.Ajaxed = new Class({

	Extends: Widget,

	options: {
		onRequest: function(container){
			if(container){ container.addClass('loading'); };
		},
		onComplete: function(container){
			if(container){ container.removeClass('loading'); };
		},
		onFailure: function(container){
			if(container){ container.removeClass('loading'); };
		},
		requestType: 'basic',
		ajaxOptions: {}
	},

	initialize: function(options){
		this.parent(options);
	},

	getRequest: function(options){
		var request;
		switch (this.options.requestType){
			case 'html': request = new Request.HTML(); break;
			case 'json': request = new Request.JSON(); break;
			default: request = new Request();
		};
		request.setOptions($merge(options, this.options.ajaxOptions));
		return request;
	}

});

var Toggler = new Class({

	Extends: Widget,

	options: {
		property: {
			min: '#fff',
			max: '#999'
		},
		value: {
			min: 'скрыть',
			max: 'показать'
		},
		fxOptions: {
			property: 'color',
			duration: 150,
			fps: 100,
			wait: false
		}
	},

	initialize: function(element, options){
		this.element = $(element);
		if(!this.element) return

		this.parent(options);
		this.fx = new Fx.Tween(this.element, this.options.fxOptions);
	},

	getHow: function(how){
		switch (how){
			case 'in': case 1: case true: return how = true;
			case 'out': case 0: case false: return how = false;
		};
	},

	set: function(how){
		how = this.getHow(how);
		this.element.set('html', how ? this.options.value.max : this.options.value.min);
		return this;
	},

	start: function(how){
		how = this.getHow(how);
		this.fx.start(this.options.property.min).chain(function(){
			this.set(how);
			this.fx.start(this.options.property.max);
		}.bind(this));
		return this;
	}

});

var Accordion = new Class({

	Extends: Widget.Ajaxed,

	options: {/*
		onActive: $empty(toggler, section),
		onBackground: $empty(toggler, section),
		onSuccess: $empty(toggler, section),*/
		trigger: 'click',
		activeClass: 'active',
		activeSubmit: false,
		selfHidden: false,
		asynchron: false,
		instant: true,
		delay: 20,
		contentAttribute: 'content',
		injectPosition: 'bottom',
		save: false,
		cached: true,

		fxOptions: {
			duration: 350,
			fps: 100,
			wait: false
		},

		tabOptions: {
			className: 'contentTab',
			tag: 'li'
		},

		requestType: 'html',
		ajaxOptions: {
			'method': 'get'
		}
	},

	initialize: function(togglers, container, options){
		this.togglers = $$(togglers);
		this.container = $(container);
		if(this.togglers == '' || !this.container) return

		this.parent(options);
		this.elements = this.container.getElements('.' + this.options.tabOptions.className);
		this.sections = [];

		this.togglers.each(function(toggler){
			this.addSection(toggler);
		}.bind(this));
	},

	addElement: function(section, element){
		section.content = element || (element = new Element(this.options.tabOptions.tag, { 'class': this.options.tabOptions.className }).inject(this.container, this.options.injectPosition));
		section.fx = new Fx.Expand(section.content, this.options.fxOptions);
		if(!section.active) section.fx.hide();
		section.fx.addEvent('onStart', function(){
			if(!this.options.fxOptions.overflown) element.retrieve('wrapper').setStyle('overflow', 'hidden');
		}.bind(this));
		section.fx.addEvent('onComplete', function(){
			var wrapper = element.retrieve('wrapper');
			if(!this.options.fxOptions.overflown && wrapper.getStyle('height').toInt() != 0) wrapper.setStyle('overflow', 'visible');
			if(element.hasClass('loading')) section.fx.show();
		}.bind(this));
	},

	addSection: function(toggler, element){
		this.togglers.include(toggler);
		var index = toggler.get(this.options.contentAttribute) || this.togglers.indexOf(toggler);
		var test = toggler.hasClass(this.options.activeClass);
		if(element) this.elements.include(element);
		if(!this.sections[index]) this.sections[index] = {};
		var section = this.sections[index];
		section.index = index;
		if(!element) element = this.elements[index] || this.container.getElement('.' + this.options.tabOptions.className + '[content=' + index + ']');
		if(element){
			section.loaded = true;
			if(test) section.active = true;
			this.addElement(section, element);
		}
		if(test) this.select(toggler, section);
		toggler.addEvent(this.options.trigger, function(event) { event.stop(); this.display(toggler, index); }.bind(this));
		return this;
	},

	getContent: function(toggler, section){
		var url = toggler.get('url') || toggler.get('href');
		var element = section.content;
		var options = {
			'update': element,
			onComplete: function(){
				this.fireEvent('onComplete', element);
				if(!Browser.Engine.trident) element.retrieve('wrapper').setStyle('opacity', 0);
				this.show(toggler, section);
			}.bind(this),
			onCancel: function(){
				this.fireEvent('onComplete', element);
			}.bind(this),
			onFailure: function(){
				this.fireEvent('onFailure', element);
			}.bind(this),
			onSuccess: function(){
				section.loaded = true;
				this.fireEvent('onSuccess', [toggler, section]);
			}.bind(this)
		};
		this.request = this.getRequest(options);
		this.request.get(url);
		this.fireEvent('onRequest', element);
	},

	display: function(toggler, index){
		if(this.request) this.request.cancel();
		var section = this.sections[index];
		var test = toggler.hasClass(this.options.activeClass);
		if(!this.options.asynchron && this.activeToggler){
			if(this.activeToggler == toggler){
				if(this.options.selfHidden) this.toggle(toggler, section, test);
				return this.options.activeSubmit;
			}
			this.toggle(this.activeToggler, this.activeSection, true);
		}
		if(this.options.instant) this.toggle(toggler, section, test)
		else this.toggle.delay(this.options.delay, this, [toggler, section, test]);
		return false;
	},

	select: function(toggler, section){
		this.activeToggler = toggler;
		this.activeSection = section;
		if(!section.content){
		  this.addElement(section);
		} else if(!this.options.save){
  		section.content.retrieve('wrapper').inject(this.container);
  	};
		if(!section.loaded) this.getContent(toggler, section);
		this.show(toggler, section);
		this.fireEvent('onActive', [toggler, section]);
	},

	show: function(toggler, section){
		section.fx.rollIn();
	},

	hide: function(toggler, section){
		section.fx.rollOut().chain(function(){
			var form = section.content.getElement('form');
			if(form) form = form.retrieve('form');
			if(form) form.resetForm();
			if(!this.options.save){
  		  section.content.retrieve('wrapper')[this.options.cached ? 'dispose' : 'destroy']();
  		  if(!this.options.cached) section.content = section.loaded = false;
			};
		}.bind(this));
		this.fireEvent('onBackground', [toggler, section]);
	},

	toggle: function(toggler, section, state){
		if(state && !toggler.hasClass(this.options.activeClass)) return;
		this[state ? 'hide' : 'select'](toggler, section);
		toggler[state ? 'removeClass' : 'addClass'](this.options.activeClass);
	}

});

var LightBox = new Class({

	Extends: Accordion,

	options: {
		onBackground: function(toggler, section){
			window.removeEvent('keydown');
		},
		selfHidden: true,
		contentAttribute: 'pattern',
		injectPosition: 'top',
		tabOptions: {
			tag: 'div',
			className: 'content-box'
		},
		fxOptions: {
			overflown: false,
			wrapperClass: 'wrapper-box'
		},
		boxOptions: {
			minTop: 10,
			maxTop: 120,
			maxWidth: 700,
			minWidth: 10,
			layoutOpacity: 0.5,
			minOpacity: 0,
			maxOpacity: 1
		}
	},

	initialize: function(options){
		var togglers = $$('.lightbox');
		if(togglers == '') return

		this.build();
		this.parent(togglers, this.contents, options);
	},

	build: function(){
		this.windowHeight = document.getHeight();
		this.lightBox = new Element('div', {
			'id': 'lightbox',
			'styles': {
				'height': $('container').getHeight(),
				'display': 'none'
			}
		}).inject(document.body);
		this.layout = new Element('div', {
			'class': 'layout',
			'styles': { 'height': this.windowHeight },
			'events': { 'click': this.hideBox.bind(this) }
		}).inject(this.lightBox);
		this.box = new Element('div', { 'class': 'box corners' }).inject(this.lightBox);
		this.boxTop = new Element('div', { 'class': 'top' }).inject(this.box);
		new Element('div', { 'class': 'cn tl' }).inject(this.boxTop);
		new Element('div', { 'class': 'cn tr' }).inject(this.boxTop);
		this.main = new Element('div', { 'class': 'wrap' }).inject(this.box);
		this.close = new Element('a', {
			'href': '#',
			'class': 'close',
			'text': 'close',
			'events': { 'click': this.hideBox.bind(this) }
		}).inject(this.main);
		this.contents = new Element('div', { 'class': 'contents' }).inject(this.main);
		new Element('div', { 'class': 'clear' }).inject(this.main);
		this.boxBottom = new Element('div', { 'class': 'bottom' }).inject(this.box);
		new Element('div', { 'class': 'cn bl' }).inject(this.boxBottom);
		new Element('div', { 'class': 'cn br' }).inject(this.boxBottom);
		this.fx = {
			'layout': new Fx.Tween(this.layout, { property: 'opacity', duration: 250, fps: 100, wait: false }).set(0),
			'box': new Fx.TransMorph(this.box, { duration: 250, fps: 100, wait: false }).set({
				'width': this.options.boxOptions.minWidth,
				'opacity': this.options.boxOptions.minOpacity,
				'top': this.options.boxOptions.minTop
			})
		}
	},

	assignEvents: function(){
		this.fx.layout.addEvent('onComplete', function(){
			if(this.layout.getStyle('opacity') == this.options.boxOptions.layoutOpacity){
				this.fx.box.start({
					'width': this.options.boxOptions.maxWidth,
					'opacity': this.options.boxOptions.maxOpacity,
					'top': this.top + this.options.boxOptions.maxTop
				},{
					'width': 'expo:in:out',
					'top': 'back:out'
				});
			} else {
				this.lightBox.setStyle('display', 'none');
				this.busy = this.onhide = false;
			}
		}.bind(this));
		this.fx.box.addEvent('onComplete', function(){
			if(this.box.getStyle('width').toInt() == this.options.boxOptions.minWidth) this.fx.layout.start(0)
			else {
				this.opened = true;
				this.busy = false;
				this.show(this.activeToggler, this.activeSection);
			}
		}.bind(this));
		window.addEvent('keydown', function(e){
			if(this.opened){
				if(e.key == 'esc') this.hideBox();
			}
		}.bind(this));
	},

	addElement: function(section, element){
		this.parent(section, element);
		section.fx.addEvent('onStart', function(){
			this.box.removeClass('ready');
		}.bind(this));
		section.fx.addEvent('onComplete', function(){
			this.busy = false;
			if(!this.onhide){
				this.box.addClass('ready');
				this.close.focus();
			}
			if(section.content.retrieve('wrapper').getStyle('height').toInt() == 0 && this.onhide){
				this.opened = false;
				this.hideBox();
			}
		}.bind(this));
	},

	show: function(toggler, section){
		if(!this.busy){
			this.busy = true;
			if(!this.opened){
				this.lightBox.setStyle('display', '');
				this.top = $(window).getScroll().y;
				this.box.setStyle('top', this.top + this.options.boxOptions.minTop);
				this.fx.layout.start(this.options.boxOptions.layoutOpacity);
			} else this.parent(toggler, section);
		}
	},

	hideBox: function(){
		if(!this.busy){
			this.busy = true;
			this.onhide = true;
			if(!this.opened){
				this.fx.box.start({
					'width': this.options.boxOptions.minWidth,
					'opacity': this.options.boxOptions.minOpacity,
					'top':  this.top + this.options.boxOptions.minTop
				},{
					'width': 'expo:in:out',
					'top': 'back:in'
				});
			} else {
				if(this.request) this.request.cancel();
				this.toggle(this.activeToggler, this.activeSection, true);
			}
		}
		return false;
	}

});

var dropDown = new Class({

	Extends: Widget.Focussed,

	options: {/*
		onShow: $empty,
		onHide: $empty,*/
		animated: Browser.Engine.trident ? false : true
	},

	initialize: function(main, options){
		this.main = $(main);
		if(!this.main) return

		this.clickarea = this.main.getElement('.clickarea');
		this.popUpBox = this.main.getElement('.dropdown-box');
		this.popUpBoxLinks = this.popUpBox.getElements('li li');
		if(this.popUpBoxLinks == '') this.popUpBoxLinks = this.popUpBox.getElements('li');
		this.bounds = { 'toggleFocusFalse': this.toggleFocus.bind(this, false) };
		this.fx = new Fx.Tween(this.popUpBox, {
			property: 'opacity',
			duration: this.options.animated ? 300 : 0,
			fps: this.options.animated ? 100 : 10000,
			wait: false
		}).set(0);
		this.events = {	'toggleFocusFalse': this.toggleFocus.bind(this, false) };
		this.parent(options);
	},

	assignEvents: function(){
		this.clickarea.addEvents({
			'click': this.click.bind(this),
			'focus': this.toggleFocus.bind(this, true)
		});
		this.main.addEvents({
			'mouseenter': this.toggleEvents.bind(this, true),
			'mouseleave': this.toggleEvents.bind(this, false)
		});
		this.popUpBoxLinks.addEvent('mouseup', this.events.toggleFocusFalse);
		this.fx.addEvent('onComplete', function(){
			if(this.visible){
				this.fireEvent('onShow', this.main);
			} else {
				this.popUpBox.setStyle('display', 'none');
				this.fireEvent('onHide', this.main);
			}
		}.bind(this));
	},

	toggleEvents: function(state){
		this.clickarea[state ? 'removeEvent' : 'addEvent']('blur', this.events.toggleFocusFalse);
		if(this.visible && !state) this.clickarea.focus();
	},

	click: function(){
		this[this.visible ? 'hide' : 'show']();
		this.clickarea.focus();
		return false;
	},

	toggleFocus: function(state){
		if(!state) this.hide();
		this.parent(state, this.main);
	},

	show: function(){
		if(this.visible) return;
		this.visible = true;
		this.main.addClass('opened');
		this.popUpBox.setStyle('display', 'block');
		this.fx.start(1);
	},

	hide: function(){
		if(!this.visible) return;
		this.visible = false;
		this.main.removeClass('opened');
		this.fx.start(0);
	}

});

var actionBar = new Class({

	Extends: dropDown,

	initialize: function(main, options){
		if(!$(main)) return

		var elements = main.getElements('li');
		if(elements.length == 0){
			main.removeClass('active');
			return false;
		} else this.parent(main, options);
		this.startPosition();
	},

	startPosition: function(){
		this.popUpBox.setStyle('display', 'block');
		var mainWidth = this.main.offsetWidth;
		if(mainWidth >= this.popUpBox.offsetWidth){
			this.main.addClass('min');
			this.popUpBox.setStyle('display', 'none');
		}
	}

});

var Select = new Class({

	Extends: dropDown,

	options: {/*
		onSelect: $empty(element, selected),
		onSelection: $empty(element, selected),*/
		fixed: true,
		resetable: true,
		maxElements: 5
	},

	initialize: function(main, options){
		if(!$(main)) return

		this.parent(main, options);
		this.element = this.main.getElement('.current .element');
		this.hidden = this.main.getElement('input[type=hidden]');
		if(!this.hidden) this.simple = true;
		var sliderBox = this.main.getElement('.slider');
		this.elements = this.main.getElements('.list li');
		this.defaultValue = this.main.getElement('.list .default');
		this.mainId = this.main.get('label');
		if(this.mainId) this.label = $$('label[for=' + this.mainId + ']')[0];
		var selected = null;
		if(!this.simple){
			this.hidden.store('select', this);
			selected = this.main.getElement('.list li[selectValue=' + this.hidden.value + ']');
		} else selected = this.main.getElement('.list li.selected');
		if(this.defaultValue){
			this.resetButton = this.main.getElement('.reset');
			if(!selected) this.reset();
		}
		if(selected){
			this.selected = selected.addClass('selected');
			this.selectElement();
		}

		if(this.options.fixed && this.elements.length > this.options.maxElements){
			var height = 0;
			for(var i = 0; i < this.options.maxElements; i++){
				height += this.elements[i].offsetHeight;
			};
			sliderBox.setStyle('height', height);
			this.slider = new Slider(this.popUpBox, { mode: 'vertical', fxOptions: { transition: 'linear', duration: '250' } });
			this.popUpBox.addClass('arrowed');
		}
		this.assignEvents(true);
	},

	assignEvents: function(state){
		if(!state) return
		this.clickarea.addEvent((Browser.Engine.trident || Browser.Engine.webkit) ? 'keydown' : 'keypress', this.onCommand.bind(this));
		this.elements.each(function(element, index){
			this.addElementEvents(element, index);
		}.bind(this));
		if(this.options.resetable && this.resetButton) this.resetButton.addEvent('click', this.reset.bind(this));
		if(this.label) this.label.addEvent('click', this.click.bind(this));
		this.parent();
	},

	addElementEvents: function(element, index){
		element.addEvents({
			'click': this.selectElement.bind(this),
			'mouseenter': this.selectOver.bind(this, element)
		});
	},

	onCommand: function(e){
	},

	selectElement: function(){
		var selectedContent = this.selected.get('html');
		this.element.set('html', selectedContent);
		if(this.options.resetable && this.reseted){
			this.main.removeClass('reseted');
			this.reseted = false;
		}
		if(!this.simple){
			selectedValue = this.selected.get('selectValue');
			this.hidden.set('value', selectedValue);
		}
		this.fireEvent('onSelection', [this.element, this.selected]);
		return false;
	},

	selectOver: function(element, select){
		if(!element || element == this.selected) return;
		if(this.selected) this.selected.removeClass('selected');
		this.selected = element.addClass('selected');
		this.fireEvent('onSelect', [this.element, this.selected]);
		if(select) this.selectElement();
	},

	error: function(){

	},

	reset: function(){
	  this.fireEvent('onReset', [this.element, this.selected])
		if(this.selected) this.selected.removeClass('selected');
		this.selected = this.defaultValue;
		this.selectElement();
		this.main.addClass('reseted');
		this.reseted = true;
		return false;
	}

});

var DefaultField = new Class({

	Extends: Widget.Focussed,

	initialize: function(element, options){
		this.element = $(element);
		if(!this.element) return

		this.defaultValue = this.element.get('default');
		this.container = element.getParent('.parent-focussed');
		var wrapper = this.container.getElement('.main') || this.container.getElement('.wrap');
		this.fx = new Fx.Morph(wrapper, { duration: 300, fps: 100, wait: false });
		this.newElement = this.buildElement(element);
		this.parent(options);
		this.element.store('default', this).setStyle('background', 'none');
		this.addText();
	},

	assignEvents: function(){
		this.container.addEvent('click', this.focusField.bind(this));
		this.newElement.addEvent('focus', this.toggleFocus.bind(this, true));
		this.element.addEvents({
			'focus': this.toggleFocus.bind(this, true),
			'blur': this.toggleFocus.bind(this, false)
		});
	},

	focusField: function(){
		this.newElement.focus() || this.element.focus();
	},

	buildElement: function(element){
		return new Element(element.get('tag'), {
			'class': element.className,
			'value': this.defaultValue,
			'styles': {
				'background': 'none'
			}
		}).inject(element, 'after').setStyle('display', 'none');
	},

	start: function(now){
		this.fx.start({
			'border-color': now[0],
			'background-color': now[1]
		});
	},

	toggleFocus: function(state){
		this[state ? 'removeText' : 'addText']();
		this.parent(state, this.container);
	},

	removeText: function(){
		this.start(['#666', '#fff']);
		if(this.newElement.hasClass('default')){
			this.newElement.setStyle('display', 'none').removeClass('default');
			this.element.setStyle('display', 'inline-block');
			this.element.focus();
		}
	},

	addText: function(){
		this.start(['#D9D9D9', '#fafafa']);
		if(this.element.value.match(/^\s*$/) || this.element.value == this.defaultValue){
			this.element.set('value', '').setStyle('display', 'none');
			this.newElement.setStyle('display', 'inline-block').addClass('default');
		}
	},

	reset: function(){
		this.element.set('value', '');
		this.addText();
	},

	error: function(){
		this.start(['#e78585', '#fbe8e8']);
	}

});

var CustomField = new Class({

	Extends: Widget,

	options: {
		//onChecked: $empty(input, myInput, label),
		//onUnchecked: $empty(input, myInput, label),
	},

	initialize: function(element, options){
		this.element = $(element);
		if(!this.element) return

		this.parent(options);
		this.build();
	},

	build: function(){
		this.element.setStyle('display', 'none');
		var checked = this.element.get('checked');
		var input = new Element('div', { 'class': this.element.get('type') == 'radio' ? 'radio' : 'checkbox', 'inputId': this.element.id }).inject(this.element, 'after');
		var label = document.getElement('label[for=' + this.element.id + ']') || document.getElement('label[inputId=' + this.element.id + ']');
		var links = label.getElements('a');
		if(checked) this.fireEvent('onChecked', [this.element, input, label]);

		this.assignEvents(input, label, links);
	},

	assignEvents: function(input, label, links){
		if(!input || !label) return;
		[input, label].each(function(element){
			element.addEvents({
				'click': function() { this.toggle(element) }.bind(this),
				'mouseenter': function() { this.toggle(element, true, true) }.bind(this),
				'mouseleave': function() { this.toggle(element, true, false) }.bind(this)
			});
		}.bind(this));

		links.each(function(link){
			link.addEvent('click', function(){
				window.open(this.href, '_blank');
			});
		}.bind(this));
	},

	toggle: function(element, hovered, state){
		var targetAttribute = element.get('for') || element.get('inputId');
		var input   = $(targetAttribute),
		    myInput = document.getElement('div[inputId=' + targetAttribute + ']'),
		    label   = document.getElement('label[for=' + targetAttribute + ']') || document.getElement('label[inputId=' + targetAttribute + ']');
		hovered ? this.toggleHover(myInput, label, state) : this[input.get('checked') ? 'uncheck' : 'check'](input, myInput, label);
		return false;
	},

	check: function(input, myInput, label){
		input.set('checked', true);
		myInput.addClass('checked');
		label.addClass('checked');
		this.fireEvent('onChecked', [input, myInput, label]);
		if(input.get('type') == 'radio') this.uncheckByName(input);
	},

	uncheck: function(input, myInput, label){
		if(input.get('type') == 'radio' && input.get('checked')) return;
		input.set('checked', false);
		myInput.removeClass('checked');
		label.removeClass('checked');
		this.fireEvent('onUnchecked', [input, myInput, label]);
	},

	uncheckByName: function(input){
		$$('input[name="'+ input.get('name') + '"]').each(function(element){
			var myInput = document.getElement('div[inputId=' + element.id + ']'), label = document.getElement('label[for=' + element.id + ']');
			if(element != this.element) this.uncheck(element, myInput, label);
		}, this);
	},

	toggleHover: function(myInput, label, state){
		[myInput, label].each(function(element){
			element[state ? 'addClass' : 'removeClass']('hovered');
		});
	}

});

var Slider = new Class({

	Extends: Widget,

	options: {
		mode: 'horizontal',
		auto: false,
		circular: false,
		wheels: true,
		fxOptions: {
			duration: 800,
			fps: 100,
			wait: false,
			wheelStops: false,
			transition: 'linear'
		},
		delayTransition: true
	},

	chain: {
		fx: function(){
			if(this.end){
				if(this.begin){
					this.position[this.scroll] = this.maxOffset - this.minOffset;
					this.currentElement = this.lastElement;
				} else {
					this.position[this.scroll] = this.minOffset;
					this.currentElement = this.firstElement;
				}
				this.set(this.position);
			}
			this.busy = false;
		}
	},

	initialize: function(main, options){
		this.main = $(main);
		if(!this.main) return

		this.box = this.main.getElement('.slider');
		this.parent(options);
		this.setMode();
		this.boxOffset = this.box[this.offset];
		this.elementsBox = this.main.getElement('ul');
		this.elements = this.elementsBox.getElements('li');
		if(!this.testOffset()) return;
		this.buildArrows();
		this.firstElement = this.currentElement = this.elementsBox.getFirst('li');
		this.lastElement = this.elementsBox.getLast('li');
		this.fx = new Fx.Scroll(this.box, this.options.fxOptions);
		this.elementsBox.setStyle(this.layout, this.elementsOffset);
		this.count = 0;
		this.position = [0, 0];
		this.set(this.position);
		if(this.options.circular) this.setCircular();
		if(this.options.auto) this.startTimer(true, true);
		this.assignEvents(true);
	},

	assignEvents: function(state){
		if(!state) return;
		if(this.options.wheels) this.box.addEvent('mousewheel', this.wheel.bind(this));
		if(this.options.auto){
			this.main.addEvents({
				'mouseenter': function() { this.timerController(false) }.bind(this),
				'mouseleave': function() { this.timerController(true, true, true) }.bind(this)
			});
		}
	},

	timerController: function(state, moveState, auto){
		if(state) this.timer = this.startTimer.delay(100, this, [moveState, auto])
		else {
			$clear(this.timer);
			this.stopTimer();
		};
	},

	setMode: function(){
		switch(this.options.mode){
			case 'vertical': this.scroll = 1; this.layout = 'height'; this.offset = 'offsetHeight'; break;
			default: this.scroll = 0; this.layout = 'width'; this.offset = 'offsetWidth';
		};
	},

	testOffset: function(){
		this.elementsOffset = 0;
		this.elements.each(function(element){
			this.elementsOffset += element[this.offset];
		}.bind(this));
		this.maxOffset = this.elementsOffset - this.boxOffset;
		if(this.maxOffset <= 0) return false
		else return true;
	},

	buildArrows: function(){
		this.arrowsPrevious = new Element('div', {
			'class': 'arrows prev hidden',
			'events': {
				'mouseenter': function() { this.timerController(true, false) }.bind(this),
				'mouseleave': function() { this.timerController(false) }.bind(this)
			}
		}).inject(this.box, 'before');
		this.arrowsNext = new Element('div', {
			'class': 'arrows next',
			'events': {
				'mouseenter': function() { this.timerController(true, true) }.bind(this),
				'mouseleave': function() { this.timerController(false) }.bind(this)
			}
		}).inject(this.box, 'after');
	},

	setCircular: function(){
		var element = this.firstElement, circularElement = this.lastElement, circularOffset = 0;
		while(circularOffset < this.boxOffset){
			circularOffset += element[this.offset];
			circularElement = this.buildElement(element, circularElement, 'after');
			element = element.getNext('li');
		};
		this.buildElement(this.lastElement, this.firstElement, 'before');
		this.minOffset = this.lastElement[this.offset];
		this.position[this.scroll] = this.minOffset;
		circularOffset += this.minOffset;
		this.maxOffset = this.minOffset + this.elementsOffset;
		this.elementsBox.setStyle(this.layout, this.elementsOffset + circularOffset);
		this.arrowsPrevious.removeClass('hidden');
		this.set(this.position);
	},

	buildElement: function(circularElement, element, state){
		return circularElement.clone().addClass('clone').inject(element, state);
	},

	startTimer: function(state, auto){
		if(this.interval) return false;
		var delay = auto ? 7000 : (this.options.delayTransition ? (200 - (10 * this.count)).limit(70, 200) : 203);
		this.interval = this.auto.periodical(delay, this, [state, auto]);
	},

	stopTimer: function(){
		if(!this.interval) return false;
		this.interval = $clear(this.interval);
		this.count = 0;
	},

	auto: function(state, auto){
		this[state ? 'moveIn' : 'moveOut'](auto);
		if(!this.options.circular){
			this.count++;
			if(auto){
				this.interval = $clear(this.interval);
				this.startTimer(this.end ? !state : state, auto);
			} else {
				if(!this.end){
					this.interval = $clear(this.interval);
					this.startTimer(state);
				} else this.stopTimer();
			}
		}
	},

	set: function(position){
		this.fx.set(position[0], position[1]);
	},

	start: function(position){
		this.fx.start(position[0], position[1]);
		if(this.options.circular) this.fx.chain(this.chain.fx.bind(this));
	},

	moveOut: function(auto){
		if(!this.options.circular){
			if(this.position[this.scroll] <= 0) return;
			this.arrowsNext.removeClass('hidden');
		} else {
			if(!this.busy) this.busy = true;
			else return;
		}
		this.position[this.scroll] -= this.currentElement.getPrevious('li')[this.offset];
		this.currentElement = this.currentElement.getPrevious('li');
		if(this.position[this.scroll] <= 0){
			if(!this.options.circular) this.arrowsPrevious.addClass('hidden')
			else this.begin = true;
			this.end = true;
		} else this.end = false;
		this.start(this.position);
	},

	moveIn: function(auto){
		if(!this.options.circular){
			if(this.position[this.scroll] >= this.maxOffset) return;
			this.arrowsPrevious.removeClass('hidden');
		} else {
			if(!this.busy) this.busy = true;
			else return;
		}
		this.position[this.scroll] += this.currentElement[this.offset];
		this.currentElement = this.currentElement.getNext('li');
		if(this.position[this.scroll] >= this.maxOffset){
			if(!this.options.circular) this.arrowsNext.addClass('hidden')
			else this.begin = false;
			this.end = true;
		} else this.end = false;
		this.start(this.position);
	},

	wheel: function(e){
		e.wheel < 0 ? this.moveIn() : this.moveOut();
		return false;
	}

});

var Exchange = new Class({

	Extends: Widget,

	initialize: function(main, options){
		this.main = $(main);
		if(!this.main) return

		this.input = this.main.getElement('input[type=text]');
		this.wmLinks = this.main.getElements('.dotted');
		this.click = $lambda(false);
		this.build();
		this.parent(options)
	},

	assignEvents: function(){
		this.input.addEvent((Browser.Engine.trident || Browser.Engine.webkit) ? 'keydown' : 'keypress', this.keydown.bind(this));
		this.wmLinks.addEvent('click', this.click);
	},

	build: function(){
		this.links = [];
		this.wmLinks.each(function(link, index){
			this.links[index] = {
				'rate': link.get('rate').toFloat(),
				'value': link.getElement('span')
			};
			this.links[index].fx = new Fx.Tween(this.links[index].value, { duration: 200, fps: 100, property: 'color', wait: false });
		}.bind(this));
	},

	keydown: function(e){
		if((e.key.length > 1) || (e.key.toInt() > -1) || (e.code >= 96 && e.code <= 105)){
			switch (e.key){
				case 'up': this.input.value++; break;
				case 'down': this.input.value--; break;
			}
			this.set.delay(200, this);
		} else return false;
	},

	set: function(){
		this.wmLinks.each(function(link, index){
			var value = this.links[index].rate * this.getValue();
			value = value.toFloat().round(2);
			link.href = link.href.replace(/[0-9.]+$/, value);
			this.links[index].fx.start('#eee').chain(function(){
				this.links[index].value.set('html', value);
				this.links[index].fx.start('#333');
			}.bind(this));
			if(value <= 0) link.addEvent('click', this.click)
			else link.removeEvent('click', this.click);
		}.bind(this));
	},

	getValue: function(){
		this.inputValue = this.input.value.toFloat();
		if(!this.inputValue) this.inputValue = 0;
		this.cap(this.inputValue.limit(0, 999));
		return this.inputValue;
	},

	cap: function(at){
		this.input.value = this.inputValue = at.round(2);
	}

});

var ManagableSearch = new Class({

	Extends: Widget,

	initialize: function(main, options){
		this.main = $(main);
		if(!this.main) return

		this.names = this.main.getElements('p a');
		this.element = this.main.getElement('input[type=text]');
		this.elementDefault = this.element.retrieve('default');
		this.parent(options);
	},

	assignEvents: function(){
		this.names.each(function(link){
			link.addEvent('click', this.click.bind(this, link));
		}.bind(this));
	},

	click: function(link){
		this.elementDefault.removeText();
		this.element.focus();
		this.element.set('value', link.get('login'))
		return false;
	}

});

var Form = new Class({

	Extends: Widget.Ajaxed,

	options: {/*
		onSuccess: $empty,*/
		requestType: 'json',
		anounced: true,
		clickableSubmit: true,
		ajaxOptions: {
			'method': 'post'
		},
		fxOptions: {
			duration: 300,
			wait: false,
			fps: 100
		}
	},

	initialize: function(form, options){
		this.form = $(form);
		if(!this.form) return

		this.formBox = this.form.getElement('.form') || this.form;
		this.submitButtons = this.form.getElements('.submit');
		this.elements = this.form.getElements('input[default], textarea[default], .select input[type=hidden]');
		this.form.store('form', this);
		this.simple = this.form.get('simple');
		this.parent(options);
		if(!this.simple) this.setIteractions();
	},

	assignEvents: function(){
		if(!this.simple){
			this.form.addEvent('submit', this.submitForm.bind(this));
			if(this.submitButtons.length > 0 && this.options.clickableSubmit) this.submitButtons.addEvent('click', this.submitForm.bind(this));
		} else {
			this.submitButtons.addEvent('click', function(element){
			  if(mpWysiwyg) mpWysiwyg.write();
				this.form.submit();
				return false;
			}.bind(this));
		}
	},

	setIteractions: function(){
		this.interactions = this.form.get('interactions').split(':');
		this.getDelay(0);
		if(this.interactions[2]) this.getDelay(2);
		this.targetContainer = this.form.get('target');
	},

	getDelay: function(action){
		if(!this.delay) this.delay = [];
		var test = this.interactions[action].split('.');
		if(test[1]){
			this.interactions[action] = test[0];
			this.delay[action] = test[1].toInt();
		} else this.delay[action] = 1000;
	},

	submitForm: function(){
		if(!this.busy){
			this.busy = true;
			if(this.options.anounced && this.anounced) this.start(false);
			if(!this.request){
				this.request = this.getRequest($merge({
					'url': this.form.action,
					onComplete: function(){
						this.busy = false;
						this.fireEvent('onComplete', this.submitButtons);
					}.bind(this),
					onFailure: function(){
						this.fireEvent('onFailure', this.submitButtons);
					}.bind(this),
					onSuccess: function(response){
						if(this.options.anounced && !this.anounce) this.getAnounce();
						if(response.state.test('ok', 'i')){
							this.onSuccess(response);
						} else if(response.state.test('fail', 'i')) this.setErrors(response.errors);
					}.bind(this)
				}, this.options.ajaxOptions));
			}
			this.request.send(this.form);
			this.fireEvent('onRequest', this.submitButtons);
		}
		return false;
	},

	getFx: function(container, state, finish){
		return animation = {
			'height': finish ? 'auto' : container.offsetHeight,
			'opacity': finish ? 1 : (state ? 1 : 0),
			'visibility': finish ? '' : 'visible'
		};
	},

	onSuccess: function(response){
		if(this.options.anounced && response.message){
			this.updateAnounce(response.message, false);
			this.start(true);
		}
		( function(){
			this.resetForm();
			switch (this.interactions[0]){
				case 'link': window.location = response.link; break;
				case 'update':
					if(this.targetContainer){
						this.targetContainer = $(this.targetContainer) || document.getElement(this.targetContainer);
					} else this.targetContainer = this.form;
					var wrapper = this.targetContainer.retrieve('success-wrapper');
					if(!wrapper){
						wrapper = new Element('div').inject(this.targetContainer, 'before').adopt(this.targetContainer);
						this.targetContainer.store('success-wrapper', wrapper);
					};
					wrapper.get('morph', this.options.fxOptions).start(this.getFx(this.targetContainer, false)).chain(function(){
						switch (this.interactions[1]){
							case 'replace': this.targetContainer.empty(); this.targetContainer.set('html', response.html); break;
							case 'add':
								this.successed = true;
								this.targetContainer.addClass('successed');
								this.successWrapper = new Element('div', {
									'html': response.html,
									'class': 'success-wrapper'
								}).inject(this.targetContainer);
								break;
						};
						response.html.stripScripts(true);
						wrapper.get('morph', this.options.fxOptions).start(this.getFx(this.targetContainer, true)).chain(function(){
							wrapper.setStyles(this.getFx(null, null, true));
						}.bind(this));
						var scroll = $(response.scroll);
						if(scroll) $scroller.toElement(scroll);
						if(this.interactions[2]){
							(function(){
								switch (this.interactions[2]){
									case 'link': window.location = response.link; break;
									case 'reload': window.location.reload();
								};
							}).delay(this.delay[2], this);
						};
					}.bind(this));
					break;
				default: window.location.reload();
			}
			this.fireEvent('onSuccess', response);
		}).delay(this.delay[0], this);
	},

	start: function(how){
		this.anounced = how;
		this.fx[how ? 'rollIn' : 'rollOut']();
	},

	getAnounce: function(){
		this.anounce = new Element('div', { 'class': 'anounce-box corners white' }).inject(this.formBox, 'top');
		new Element('div', { 'class': 'cn tl' }).inject(this.anounce);
		new Element('div', { 'class': 'cn tr' }).inject(this.anounce);
		var main = new Element('div', { 'class': 'main' }).inject(this.anounce);
		this.head = new Element('h3').inject(main);
		new Element('b').inject(main);
		this.list = new Element('ul').inject(main);
		this.fx = new Fx.Expand(this.anounce, { overflown: false, duration: 200, wait: false }).hide();
		new Element('div', { 'class': 'cn bl' }).inject(this.anounce);
		new Element('div', { 'class': 'cn br' }).inject(this.anounce);
	},

	resetAnounce: function(){
		this.anounce.set('class', 'anounce-box corners white');
		this.list.empty().addClass('');
	},

	updateAnounce: function(messages, error){
		this.resetAnounce();
		this.anounce.addClass(error ? 'error' : 'success');
		var test = messages.length == 1;
		this.head.set('html', error ? (test ? messages[0][1] : 'Поправь все ошибки и попробуй еще разок.') : messages);
		if(error && !test){
			messages.each(function(error){
				new Element('i').inject(new Element('li', { html: error[1] }).inject(this.list));
			}.bind(this));
		}
	},

	resetForm: function(){
		if(this.options.anounced && this.anounced) this.start(false);
		if(this.successed){
			this.successed = false;
			var wrapper = this.targetContainer.retrieve('success-wrapper');
			wrapper.get('morph', this.options.fxOptions).start({ 'opacity': 0 }).chain(function(){
				this.targetContainer.removeClass('successed');
				wrapper.setStyles(this.getFx(null, null, true));
				this.successWrapper.destroy();
			}.bind(this));
		};
		this.elements.each(function(element){
			var object = element.retrieve('default') || element.retrieve('select');
			object.reset();
		});
	},

	setErrors: function(errors){
		if(!errors) return false;
		if(this.options.anounced){ this.updateAnounce(errors, true); };
		this.start(true);
		errors.each(function(error){
			this.elements.each(function(element){
				if(element.get('name').test(error[0])){
					var object = element.retrieve('default') || element.retrieve('select');
					object.error();
				}
			}.bind(this))
		}.bind(this));
	}

});

var submitButton = new Class({

  Extends: Widget,

  initialize: function(element){
    this.element = $(element);
    if(!this.element) return;

    this.input = this.element.getNext('input[type=submit]');
    this.parent.apply(this, arguments);
  },

  assignEvents: function(){
    this.element.addEvent('click', this.click.bind(this));
  },

  click: function(){
    this.input.click();
    return false;
  }

});

var Unread = new Class({

	Extends: Widget.Ajaxed,

	options: {
		requestType: 'json',
		ajaxOptions: {
			method: 'get'
		}
	},

	initialize: function(element, options){
		this.element = $(element);
		if(!this.element) return

		this.url = this.element.get('url');
		this.bound = { 'read': this.read.bind(this) }
		this.link = this.element.getElement('.newMessage');
		this.parent(options);
	},

	assignEvents: function(){
		this.element.addEvent('mouseenter', this.bound.read);
		this.link.addEvent('click', $lambda(false));
	},

	read: function(){
		if(!this.busy){
			this.busy = true;
			if(!this.request){
				this.request = this.getRequest($merge({
					onComplete: function(){
						this.busy = false;
						this.fireEvent('onComplete', this.link);
					}.bind(this),
					onFailure: function(){
						this.fireEvent('onFailure', this.link);
					}.bind(this),
					onSuccess: function(response){
						if(response.state.test('ok', 'i')){
							this.element.removeClass('new').removeEvent('mouseenter', this.bound.read);
						}
					}.bind(this)
				}, this.options.ajaxOptions));
			}
			this.request.get(this.url);
			this.fireEvent('onRequest', this.link);
		}
	}

});

var Inline = new Class({

	Extends: Widget,

	options: {
		fxOptions: {
			duration: 300,
			wait: false
		}
	},

	initialize: function(main, options){
		this.main = $(main);
		if(!this.main) return

		this.form = this.main.getElement('form');
		this.links = {
			'forward': this.main.getElement('p a'),
			'back': this.main.getElement('.back-button')
		};
		this.defaultField = this.form.getElement('input[default]').retrieve('default');
		this.parent(options);
		this.fx = new Fx.Slide(this.form, this.options.fxOptions);
		if(this.main.hasClass('active')) this.click(true)
		else this.fx.hide();
	},

	assignEvents: function(){
		this.links.forward.addEvent('click', function() { this.click(true) }.bind(this));
		this.links.back.addEvent('click', function() { this.click(false) }.bind(this));
	},

	click: function(state){
		this.fx[state ? 'slideIn' : 'slideOut']();
		if(state && this.defaultField) this.defaultField.focusField();
		return false;
	}

});

var VideoBar = new Class({

	Extends: Widget,

	initialize: function(link, options){
		this.link = $(link);
		if(!this.link) return

		this.box = this.link.getParent('li').getNext('li.exchange');
		this.fx = new Fx.Slide(this.box, { duration: 300, fps: 100, wait: false }).hide();
		this.parent(options);
	},

	assignEvents: function(){
		this.link.addEvent('click', this.click.bind(this));
	},

	click: function(){
		this.link.toggleClass('active');
		this.fx.toggle();
		return false;
	}

});

var Video = new Class({

	initialize: function(element, options){
		this.element = $(element);
		if(!this.element) return

		var video = {
			'height': this.element.get('height').toInt(),
			'width': this.element.get('width').toInt()
		};
		this.element.setStyle('width', video.width);
		var flash = this.element.getElement('.flash-video') || new Element('div', {
			'class': 'flash-video',
			'styles': {
				'width': video.width,
				'height': video.height,
				'overflow': 'hidden'
			}
		}).inject(this.element, 'top');
		var params = this.element.get('params');
		new Swiff(this.element.get('src'), {
			'height': video.height,
			'width': video.width,
			'container': flash,
			'params': {
				'allowFullScreen': true
			},
			'vars': params ? JSON.decode(params) : {}
		});
	}

});

var myTips = new Class({

	Extends: Widget,

	options: {
		fxOptions: {
			fps: 100,
			wait: false,
			duration: Browser.Engine.trident ? 0 : 150,
			property: 'opacity'
		},
		offset: {
			'x': 0,
			'y': 0
		},
		showDelay: 0,
		hideDelay: 50
	},

	styles: {
		tip: {
			'top': 0,
			'left': 0,
			'display': 'none',
			'position': 'absolute'
		},
		show: {
			'display': 'block',
			'margin': 0,
			'width': '250px',
			'white-space': 'normal'
		},
		hide: {
			'display': 'none',
			'opacity': 0
		},
		auto: {
		  'width': 'auto',
		  'white-space': 'nowrap'
		}
	},

	initialize: function(elements, options){
		this.elements = $$(elements);
		if(this.elements == '') return

		this.parent(options);
	},

	assignEvents: function(elements){
		(elements || this.elements).each(function(element){
  		var title = element.get('title');
  		element.erase('title');
  		element.addEvents({
  			'mouseenter': function() { this.show(element, title) }.bind(this),
  			'mouseleave': this.hide.bind(this)
  		});
		}.bind(this));
	},

	build: function(){
		if(this.tip) return;
		this.tip = new Element('div', { 'class': 'tip-wrap rounded-rixel', 'styles': this.styles.tip }).inject(document.body);
		var tip = new Element('div', { 'class': 'tip' }).inject(this.tip);
		this.tipTitle = new Element('div', { 'class': 'tip-title' }).inject(tip);
		this.tipTitleSpan = new Element('span').inject(this.tipTitle);
		new Element('i', { 'class': 'tip-arrow' }).inject(this.tip);
	},

	show: function(element, title){
		if(!this.tip) this.build();
		this.tip.setStyles(this.styles.show).set('class', 'tip-wrap rounded-pixel');
		this.tipTitleSpan.set('html', title);
		var coords = element.getCoordinates();
		delete coords.right;
		delete coords.bottom;
		if(this.tipTitleSpan.offsetWidth < 210) this.tip.setStyles(this.styles.auto);
		var styles = {
			'top': coords.top + this.options.offset.y.toInt() - (this.tip.offsetHeight + 3),
			'left': coords.left + this.options.offset.x.toInt() + (coords.width / 2) - (this.tip.offsetWidth / 2)
		};
		if(styles.left < 0 || styles.left <= document.getScroll().x){
			styles.left = coords.left + this.options.offset.x.toInt() - 10;
			this.tip.addClass('left');
		} else if((coords.left + this.tip.offsetWidth - document.getScroll().x) >= document.getWidth()){
			styles.left = coords.left + this.options.offset.x.toInt() + coords.width + 10;
			this.tip.setStyle('margin-left', -this.tip.offsetWidth).addClass('right');
		}
		if(styles.top < document.getScroll().y){
			styles.top = coords.top + this.options.offset.y.toInt() + coords.height + 3;
			this.tip.addClass('top');
		}
		this.tip.setStyles(styles);
		$clear(this.timer);
		this.timer = (function(){
			this.tip.setStyle('opacity', 1);
		}).delay(this.options.showDelay, this);
	},

	hide: function(){
		$clear(this.timer);
		this.timer = (function(){
			this.tip.setStyles(this.styles.hide);
		}).delay(this.options.hideDelay, this);
	}

});

var Position = new Class({

	Extends: Widget,

	initialize: function(options){
		this.topBox = document.getElement('.moved.top');
		this.bottomBox = document.getElement('.moved.bottom');
		if(this.topBox && this.bottomBox){
			this.upLink = document.getElement('.up a');
			this.fx = {
				'up': new Fx.Tween(this.upLink, { duration: 200, property: 'top' }),
				'bottom': new Fx.Tween(this.bottomBox, { property: 'opacity', duration: Browser.Engine.trident ? 0 : 300, fps: 100, wait: false })
			};
			this.parent(options);
			if(Cookie.read('onTop') == 'true'){
				this.up = true;
				this.upLink.addClass('onTop');
				this.bottomBox.inject(this.topBox, 'before');
			}
		}
	},

	assignEvents: function(){
		this.upLink.addEvent('click', this.click.bind(this));
	},

	click: function(){
		if(!this.busy){
			this.busy = true;
			this.up ? this.move(false) : this.move(true);
		}
		return false;
	},

	move: function(state){
		Cookie.write('onTop', state);
		this.fx.bottom.start(0).chain(function(){
			this.bottomBox.inject(this.topBox, state ? 'before' : 'after');
			this.upLink[state ? 'addClass' : 'removeClass']('onTop');
			$scroller.toElement(this.bottomBox);
			this.fx.bottom.start(1).chain(function(){
				this.up = state;
				this.busy = false;
			}.bind(this));
		}.bind(this));
	}

});

var UploadAvatar = new Class({

	Extends: Widget,

	initialize: function(main, options){
		this.main = $(main);
		if(!this.main) return

		this.input = this.main.getElement('input');
		this.textarea = this.main.getElement('span');
		this.parent(options);
	},

	assignEvents: function(){
		this.input.addEvent('change', this.change.bind(this));
	},

	change: function(){
		this.textarea.set('html', this.input.value);
	}

});

var GiveIgp = new Class({

	Extends: Widget.Ajaxed,

	options: {
		requestType: 'json'
	},

	initialize: function(link, igp, options){
		this.link = $(link);
		this.igp = $(igp);
		if(!this.link || !this.igp) return

		this.parents = {
			'link': this.link.getParent('.give'),
			'igp': this.igp.getParent('.coins')
		};
		this.form = new Element('form', { 'styles': { 'display': 'none' } }).inject(this.link, 'after');
		new Element('input', { 'type': 'hidden', 'name': '_method', 'value': 'put' }).inject(this.form);
		this.fx = new Fx.Tween(this.link, { duration: Browser.Engine.trident ? 0 : 300, property: 'opacity', wait: false, fps: 100 });
		this.parent(options);
	},

	assignEvents: function(){
		this.link.addEvent('click', this.click.bind(this));
	},

	click: function(){
		if(!this.busy){
			this.busy = true;
			var options = {
				'url': this.link.href,
				'method': 'post',
				onComplete: function(){
					this.fireEvent('onComplete', this.link);
				}.bind(this),
				onCancel: function(){
					this.fireEvent('onComplete', this.link);
				}.bind(this),
				onFailure: function(){
					this.fireEvent('onFailure', this.link);
				}.bind(this),
				onSuccess: function(responseJSON, responseText){
					this.fx.start(0).chain(function(){
						this.parents.link.destroy();
						this.busy = false;
					}.bind(this));
					this.igp.set('html', responseJSON);
					this.parents.igp.removeClass('hidden');
				}.bind(this)
			};
			this.request = this.getRequest(options);
			this.request.send(this.form);
			this.fireEvent('onRequest', this.link);
		}
		return false;
	}

});

var Textarea = new Class({

	Extends: Widget,

	initialize: function(element, options){
		this.element = $(element);
		if(!this.element) return

		this.element.setStyle('height', 'auto').rows = 3;
		this.parent(options);
	},

	assignEvents: function(){
		this.element.addEvents({
			'keyup': function() { this.test(this.element) }.bind(this),
			'blur': function() { this.test(this.element) }.bind(this)
		});
	},

	test: function(textarea){
		 textarea.rows = textarea.value.split('\n').length.limit(3, 35);
	}

});

var User = new Class({

	Implements: [Options],

	options: {
		fxOptions: {
			'top': 10,
			'left': 15,
			'width': 243,
			'height': 135,
			'minOpacity': 0.2,
			'maxOpacity': 0.95
		}
	},

	initialize: function(user, options){
		this.user = $(user);
		if(!this.user) return

		this.userImg = this.user.getElement('img');
		this.userLogin = this.user.get('login');
		this.userUrl = this.user.href;
		this.setOptions(options);
		this.assignEvents();
	},

	build: function(){
		this.popupBox = new Element('div', { 'id': 'popupUser', 'styles': { 'visibility': 'hidden' } }).inject(document.body);
		this.popupImg = new Element('img', { 'class': 'user-img', 'src': this.userImg ? this.userImg.src : '' }).inject(this.popupBox);
		this.infoBox = new Element('div', { 'class': 'info' }).inject(this.popupBox);
		this.fx = {
			'box': new Fx.TransMorph(this.popupBox, { duration: 250, fps: 100, wait: false }).set({
				'left': this.coords.left,
				'top': this.coords.top,
				'width': this.coords.width,
				'height': this.coords.height,
				'opacity': this.options.fxOptions.minOpacity
			}),
			'img': new Fx.Morph(this.popupImg, { duration: 250, fps: 100, wait: false }).set({
				'width': this.coords.width - 4,
				'height': this.coords.height - 4,
				'top': 0,
				'left': 0
			}),
			'fade': new Fx.Tween(this.infoBox, { duration: Browser.Engine.trident ? 0 : 250, fps: 100, property: 'opacity', wait: false }).set(0)
		}
		this.showBox();
	},

	assignEvents: function(){
		this.user.addEvent('click', this.click.bind(this));
		this.bound = { 'blur': this.hideContent.bind(this) };
	},

	getCoords: function(){
		this.coords = this[this.userImg ? 'userImg' : 'user'].getCoordinates();
		if(!this.userImg)
		  this.coords.width = this.coords.height = 16;
		delete this.coords.right;
		delete this.coords.bottom;
	},

	click: function(){
		if(!this.opened){
			this.user.focus();
			this.getCoords();
			this.popupBox ? this.showBox() : this.build();
		} else this.user.blur();
		return false;
	},

	showBox: function(){
		this.opened = true;
		this.user.addEvent('blur', this.bound.blur);
		this.popupBox.setStyle('visibility', 'visible');
		this.fx.box.start({
			'left': this.coords.left + this.options.fxOptions.left,
			'top': this.coords.top + this.options.fxOptions.top,
			'width': this.options.fxOptions.width,
			'height': Users[this.userLogin] ? Users[this.userLogin].height : this.options.fxOptions.height,
			'opacity': this.options.fxOptions.maxOpacity
		},{
			'left': 'sine:in',
			'top': 'back:out'
		}).chain(function(){
			Users[this.userLogin] ? (this.userInfo ? this.showContent() : this.updateContent()) : this.createContent();
		}.bind(this));
		this.fx.img.start({
			'width': 50,
			'height': 50,
			'top': 12,
			'left': 12
		},{
			'left': 'sine:in',
			'top': 'back:out'
		});
	},

	hideBox: function(){
		this.getCoords();
		if(this.request) this.request.cancel();
		this.user.removeEvent('blur', this.bound.blur);
		this.fx.box.clearChain();
		this.fx.box.start({
			'left': this.coords.left,
			'top': this.coords.top,
			'width': this.coords.width,
			'height': this.coords.height,
			'opacity': this.options.fxOptions.minOpacity
		},{
			'left': 'sine:out',
			'top': 'back:in'
		}).chain(function(){
			this.popupBox.setStyle('visibility', 'hidden');
			this.opened = false;
		}.bind(this));
		this.fx.img.start({
			'width': this.coords.width - 4,
			'height': this.coords.height - 4,
			'top': 0,
			'left': 0
		},{
			'left': 'sine:out',
			'top': 'back:in'
		});
	},

	hideContent: function(){
		if(this.visible){
			this.fx.fade.start(0).chain(function(){
				this.visible = false;
				this.hideBox();
			}.bind(this));
		} else this.hideBox();
	},

	showContent: function(){
		this.visible = true;
		this.fx.fade.start(1);
	},

	createContent: function(){
		var userInfo = new Element('div').inject(this.infoBox);
		this.request = new Request.HTML({
			'update': userInfo,
			onRequest: function(){
				this.popupBox.addClass('loading');
			}.bind(this),
			onComplete: function(){
				this.popupBox.removeClass('loading');
			}.bind(this),
			onCancel: function(){
				this.popupBox.removeClass('loading');
			}.bind(this),
			onSuccess: function(){
				this.userInfo = userInfo;
				Users[this.userLogin] = {
					'content': this.userInfo,
					'height': this.userInfo.getHeight()
				}
				this.fx.box.start({
					'height': Users[this.userLogin].height
				});
				this.showContent();
			}.bind(this)
		}).get(this.userUrl);
	},

	updateContent: function(){
		this.userInfo = new Element('div').inject(this.infoBox);
		Users[this.userLogin].content.clone().inject(this.userInfo);
		this.showContent();
	}

});

var Users = [];

var Wysiwyg = new Class({

	initialize: function(main, params){
		this.main = $(main);
		if(!this.main) return

		this.textareaBox = this.main.getElement('.textarea');
		this.textarea = this.main.getElement('textarea');
		this.toolBar = new Element('div', { 'class': 'textile-bar' }).inject(this.textareaBox, 'before');
		this.fx = new Fx.Slide(this.toolBar, { duration: 310, fps: 100, wait: false });
		this.opened = true;
		this.hideToolBarLink = this.main.getElement('.hideWysiwyg');
		this.fxText = new Fx.Tween(this.hideToolBarLink, { property: 'color', duration: 150, fps: 100, wait: false });
		$each(params.buttons,function(element){
			new Element('a', { 'class': element }).addEvent('click', this.exec.bind(this, element)).inject(this.toolBar);
		}.bind(this));

		this.hideToolBarLink.addEvent('click', this.toogleToolbar.bind(this));
	},

	toogleToolbar: function(){
		if(!this.busy){
			this.busy = true;
			this.fx.toggle().chain(function(){
				this.busy = false;
			}.bind(this));
			this.fxText.start('#fff').chain(function(){
				this.opened = !this.opened;
				this.hideToolBarLink.set('html', this.opened ? 'Скрыть WISIWYG' : 'Показать WISIWYG');
				this.fxText.start('#7F7F7F');
			}.bind(this));
		}
		return false;
	},

	exec: function(b){
		this.button = _BUTTONS[b];
		this.textarea.insertAroundCursor({ before: this.button[0], after: this.button[0], defaultMiddle: this.button[2]});
		return false;
	}

});

var _BUTTONS = {
	strong: ['*','*','жирный'],
	em: ['_','_','курсив'],
	u: ['+','+','подчеркнутый'],
	s: ['-','-','перечеркнутый']
};

var notWorkYet = new Class({

	initialize: function(){
		if($$('a.not_ready') == '') return

		this.links = $$('.not_ready');
		this.build();

		this.links.addEvent('click', this.show.bind(this));
	},

	build: function(){
		this.windowHeight = document.getHeight();
		this.notReady = new Element('div', {
			'id': 'notReadyYet',
			'styles': {
				'height': this.windowHeight
			},
			'events': {
				'click': this.hide.bind(this)
			}
		}).inject(document.body);
		this.layout = new Element('div', { 'class': 'layout' }).inject(this.notReady);
		this.fxLayout = new Fx.Tween(this.layout, { property: 'opacity', duration: 300, fps: 100, wait: false }).set(0);
		this.img = new Element('img', { 'src': '/images/new_layout/not_ready_yet.jpg', 'alt': 'не ругай, насяльника' }).inject(this.notReady);
		this.fxImg = new Fx.Morph(this.img, { duration: 400, fps: 100, wait: false, transition: 'bounce:out' }).set('.noneImg');
	},

	show: function(){
		if(!this.busy){
			this.busy = true;
			this.notReady.addClass('active');
			this.fxLayout.start('0.8').chain(function(){
				this.fxImg.start('.yepImg').chain(function(){
					this.busy = false;
				}.bind(this));
			}.bind(this));
		}
		return false;
	},

	hide: function(){
		if(!this.busy){
			this.busy = true;
			this.fxImg.start('.noneImg').chain(function(){
				this.fxLayout.start('0').chain(function(){
					this.notReady.removeClass('active');
					this.busy = false;
				}.bind(this));
			}.bind(this));
		}
		return false;
	}

});

function mpTips(elements){
	new myTips(elements);
};

function VideoNavigator(container){
	container = $(container);
	if(!container) return;
	new Accordion(container.getElements('.show-video a'), container, {
		onActive: function(toggler, section){
			toggler.getElement('b').set('html', 'Скрыть видео');
			section.content.getElements('.embeded-video').each(function(element){
				new Video(element);
			});
		},
		onBackground: function(toggler, section){
			$scroller.toElement(section.content);
			toggler.getElement('b').set('html', 'Показать видео');
			section.content.getElements('object').each(function(element){
				element.destroy();
			});
		},
		asynchron: true,
		save: true,
		tabOptions: {
			className: 'video-files'
		}
	});
};

function testCount(value){
	value = value.toString();
	var end;
	if(value.test('[2-4]$') && !value.test('1[2-4]$')) end = 'я'
	else if(value.test('1$') && !value.test('11$')) end = 'й'
	else end = 'ев';
	return end;
}

window.addEvent('domready', function(){

	/* scroller */
	$scroller = new Fx.Scroll(window, { duration: 300, fps: 100, wait: false, wheelStops: false, offset: { 'x': 0, 'y': -50 } });

	/* popup */
	$$('.dropdown').each(function(element){
		element.hasClass('action-bar') ? new actionBar(element) : new dropDown(element);
	});
	new Select('Selector', { fixed: false });
	$$('.room-selector').each(function(element){
  	new Select(element, { maxElements: 3 });
	});
	$$('.select').each(function(element){ new Select(element); });

	/* Fields */
	$$('input[default], textarea[default]').each(function(element){ new DefaultField(element); });
	$$('input[type=radio], input[type=checkbox]').each(function(element){ new CustomField(element); });
	$$('.suggester').each(function(element){
		new Autocompleter.Request.JSON(element, element.get('url'), {
			'minLength': 1,
			'multiple': element.get("multy") == 'true',
			'postVar': 'q',
			'ajaxOptions': {
				'method': 'get'
			}
		});
	});

	/* Slider */
	new Slider('bannerSlider', { auto: true, circular: true, delayTransition: false, wheels: false });

	/* Accordion */
	new Accordion('#roomSelector .list .room', 'shopPokerroms', {
		contentAttribute: 'roomId',
		tabOptions: {
			className: 'room',
			tag: 'li'
		},
		fxOptions: {
			wrapperClass: 'roomWrapper'
		}
	});
	new Accordion('#dataminingSelector .list .room', 'dataMiningPokerroms', {
		contentAttribute: 'roomId',
		tabOptions: {
			className: 'room',
			tag: 'li'
		},
		fxOptions: {
			wrapperClass: 'roomWrapper'
		}
	});

	var blogHiddens = [];
	var blogContents = [];
	new Accordion('#Selectors .list li', 'blogSelector', {
		onActive: function(toggler, section){
			if(blogHiddens[section.index]) blogHiddens[section.index].inject(blogContents[section.index]);
		},
		onBackground: function(toggler, section){
			if(!blogHiddens[section.index]){
				blogHiddens[section.index] = section.content.getElement('input[type=hidden]');
				blogContents[section.index] = section.content.getElement('.current .main');
			}
			if(blogHiddens[section.index]) blogHiddens[section.index].destroy();
		},
		contentAttribute: 'selectValue',
		tabOptions: {
			tag: 'li'
		},
		fxOptions: {
			wrapperClass: 'blogWrapper',
			overflown: false
		}
	});
	$$('.tabs.vertical.ajax').each(function(element){
		new Accordion(element.getElements('.titles-tabs li'), element.getElement('.contents-tabs'), {
			tabOptions: {
				tag: 'div'
			},
			fxOptions: {
				wrapperClass: 'wrapperTab',
				overflown: element.hasClass('vis') ? false : true
			}
		});
	});
	var blogoTest = false;
	$Blogoconference = new Accordion('#Blogoconference .item.ajax .section, #Blogoconference .title, #Blogoconference .titleTab', 'blogoContents', {
		onActive: function(){
			if(!blogoTest) blogoTest = true
			else $scroller.toElement('Blogoconference');
		},
		fxOptions: {
			wrapperClass: 'wrapperTab'
		}
	});
	new Accordion('#Blogoconference .item.ajax, #Blogoconference .heading-title', 'Blogoconference', {
		trigger: 'mouseup',
		save: true,
		tabOptions: {
			className: 'heading-blogs'
		}
	});
	new Accordion('#Help .helpBox a', 'Help', {
		selfHidden: true,
		fxOptions: {
			wrapperClass: 'helpWrapper'
		},
		tabOptions: {
			className: 'helpContent'
		}
	});
	$$('.navigator-box.ajax').each(function(element){
		fx = new Toggler(element.getElement('.toggler span'), {
			property: {
				min: '#666',
				max: '#fff'
			},
			value: {
				min: 'скрыть',
				max: 'показать'
			}
		});
		new Accordion(element.getElements('.toggler'), element, {
			onActive: function(toggler){
				fx.start('out');
			},
			onBackground: function(toggler){
				fx.start('in');
			},
			selfHidden: true,
			save: true,
			tabOptions: {
				className: 'navigator'
			}
		});
	});
	$$('.navigator.ajax').each(function(element){
		new Accordion(element.getElements('.item'), element, {
		  save: true,
			tabOptions: {
				className: 'item-content'
			}
		});
	});
	$$('.videos.ajax').each(function(element){
		new Accordion(element.getElements('.video-item'), element, {
			tabOptions: {
				className: 'video-content'
			}
		});
	});
	$$('.posts').each(function(element){
		VideoNavigator(element);
	});
	$Blogs = [];
	$$('.other_posts').each(function(element){
		new Accordion(element.getElements('.action-bar a'), element, {
			onActive: function(toggler){
				toggler.set('html', 'скрыть');
			},
			onBackground: function(toggler){
				toggler.set('html', 'показать');
			},
			selfHidden: true,
			tabOptions: {
				className: 'related-posts',
				tag: 'div'
			}
		});
	});
	var contributorsBox = $('Contributors');
	if(contributorsBox){
		$contributors = {
			'container': contributorsBox.getElement('.contributors'),
			'moreSection': contributorsBox.getElement('.more-section'),
			'fxWrappers': [],
			'wrappers': []
		};
		new Accordion('#Contributors .addMore', $contributors.container, {
			onActive: function(toggler, section){
				var fxWrapper = $contributors.fxWrappers[section.index] || ( $contributors.fxWrappers[section.index] = section.content.retrieve('wrapper') );
				fxWrapper.inject($contributors.container);
				var wrapper = $contributors.wrappers[section.index] || ( $contributors.wrappers[section.index] = section.content.getElement('.wrapper') );
				toggler.set('html', '<b>убрать</b>').inject(wrapper);
			},
			onBackground: function(toggler, section){
				toggler.set('html', '<b>Добавить еще одного</b>').inject($contributors.moreSection);
				section.content.getElements('input[default], .select input[type=hidden]').each(function(element){
					var object = element.retrieve('default') || element.retrieve('select');
					object.reset();
				});
			},
			asynchron: true,
			tabOptions: {
				className: 'contributor'
			},
			fxOptions: {
				overflown: false
			}
		});
	}
	$$('.hand.ajax').each(function(element){
		new Accordion(element.getElements('.action-bar a'), element, {
			onActive: function(toggler){
				toggler.set('html', 'скрыть');
			},
			onBackground: function(toggler){
				toggler.set('html', 'показать');
			},
			selfHidden: true,
			tabOptions: {
				className: 'hand-content'
			}
		});
	});


	/* Position */
	$first = true;
	//new Position();

	/* Lightbox */
	myLightBox = new LightBox();

	/* Comments */
	var commentsContainer = $('commentsBox');
	if(commentsContainer){
		var $comment, $commentToggler;
		$commentHeader = commentsContainer.getElement('h2')
		$commentForm = new Accordion(commentsContainer.getElements('.add_comment_button'), commentsContainer, {
			onActive: function(toggler, section){
				$commentToggler = toggler;
				var parent = toggler.getParent('.commentContent');
				if(!parent){
					var button = true;
					parent = toggler.getParent('.wrapper');
				}
				if(!$comment){
					$comment = {
						'wrapper': section.content.retrieve('wrapper'),
						'input': section.content.getElement('input#comment_parent_id'),
						'textarea': section.content.getElement('textarea').retrieve('default')
					};
				}
				$comment.wrapper.inject(parent, button ? 'after' : 'bottom');
				$comment.input.value = parent.get('commentId') || 'lol';
				( function(){ $comment.textarea.focusField(); }).delay(100);
				$scroller.toElement(section.content);
			},
			onBackground: function(toggler, section){
				section.content.retrieve('form').resetForm();
			},
			selfHidden: true,
			instant: false,
			delay: 310,
			tabOptions: {
				className: 'new_comment',
				tag: 'form'
			}
		});
		new Accordion(commentsContainer.getElements('.title-box h2'), 'commentsBoxMain', {
			tabOptions: {
				className: 'comments main',
				tag: 'ul'
			}
		});
		new Form('wysiwygForm', {
			onSuccess: function(){
				$commentToggler.fireEvent('click');
				$comment.wrapper.inject(commentsContainer);
				var value = $commentHeader.get('text').toInt(), end;
				value++;
				end = testCount(value);
				value += ' комментари' + end;
				$commentHeader.set('text', value);
			}
		});
	};

	/* Give */
	var postIgp = $('postIGP');
	if(postIgp){ new GiveIgp(postIgp.getElement('.give a'), postIgp.getElement('.coins span')); }

	/* Search */
	new ManagableSearch('managableSearch');
	if(location.hash){
		var $hash = location.hash;
		var $id = $($hash.split('#')[1]);
		if($id){
			$id.addClass('active');
			$scroller.toElement($id);
		}
	}

	$$('.submit-link').each(function(element){
		var form = element.getParent('form');
		element.addEvent('click', function(){
			form.submit();
			return false;
		});
	});

	/* Wysiwyg */
	mpWysiwyg = null;
	$$('.wysiwyg').each(function(wysiwyg){
		if(!wysiwyg.hasClass('max')){
			wysiwyg.getElements('textarea').each(function(element){
				new Textarea(element);
			});
		}
		if(wysiwyg.hasClass('ajax')){
			mpWysiwyg = new Wysiwyg(wysiwyg, {
				buttons: ['strong', 'em', 'u', 's']
			});
		}
	});
	$$('textarea').each(function(element){
		element.addEvent('keydown', function(e){
			var form = element.getParent('form');
			var test = form.retrieve('form');
			if(form && (e.control || e.meta) && e.key == 'enter') test ? form.fireEvent('submit') : form.submit();
		});
	});

	/* User */
	$$('a.popup-user').each(function(user){ new User(user); });

	/* Exchange */
	$$('.exchange').each(function(element){
		new Exchange(element);
	});

	/* Video bar */
	$$('.buy-igp').each(function(link){
		new VideoBar(link);
	});

	/* Tips */
	mpTips('.bonus li.closed b strong, .bonus p.close b[title], acronym[title], .bug .info a, .bonus p strong[title]');

	/* Unread */
	$$('li.message.new').each(function(element){
		new Unread(element);
	});

	/* Inline */
	$$('.room-name').each(function(room){
		new Inline(room);
	});
	new Form('pokerroom_name_form');

	/* Video */
	$$('.postMain .embeded-video').each(function(element){
		new Video(element);
	});

	/* Not Work Yet */
	new notWorkYet();

	/* error box */
	$$('.error-box').each(function(element){
		element.addEvent('outerClick', function(){
			window.location = element.get('url');
		});
	});

	$$('.cookie').each(function(element){
		element.addEvent('click', function(){
			Cookie.dispose('onTop');
			Cookie.dispose('_rails_session');
			window.location.reload();
			return false;
		});
	});

	$$('.upload-avatar').each(function(element){
		new UploadAvatar(element);
	});

});

