var Controls = new Class({

	Implements:[Options, Events, Chain],

	options: {
		wrapper:null,
		items:null,
		text:null
	},

	initialize: function(options, next, prev) {
		this.setOptions(options);
		this.next = next;
		this.prev = prev;
		this.wrapper = this.options.wrapper;
		this.clickerBound = this.clickHandler.bind(this);
		this.items = this.options.items.map(function(item, i) {return item.set('rel', i+1)});
		this.wrapper.store('start', true);
		this.items[0].store('show', true);
		//this.helperText(this.items[0].getProperty('name'));
		this.initialEvents(next, prev);
	},

	initialEvents: function(next, prev) {
		$A(arguments).each(function(item) {
			item.addEvent('click', function(e) {
				this.clickHandler(e, item);
			}.bind(this));
		}, this);
	},

	helperText: function(name) {
		this.text = this.options.text;
		this.text.set('text', name);
	},

	clickHandler: function(e, elem) {
		new Event(e).stop();
		var items = this.items;
		var wrapper = this.wrapper;
		var current_item = items.filter(function(item) {return item.retrieve('show')})[0];
		var who = elem.get('class');
		var fx = new Fx.Morph(wrapper, {duration:500, wait:true, link:'cancel',
			onStart: function() {
				wrapper.store('lock', true);
			},
			onComplete: function() {
				current_item.eliminate('show')['get'+who.capitalize()+'']().store('show', true);
				wrapper.eliminate('lock');
				this.helperText(this.items.filter(function(item) {return item.retrieve('show')})[0].getProperty('name'));
			}.bind(this)
		});
		
		switch(who) {
			case 'next':
				if(this.wrapper.retrieve('end') || wrapper.retrieve('lock') || !current_item.getNext()) return;
				if((current_item.get('rel').toInt() + 1) == items.length) this.wrapper.store('end', true);
				else this.wrapper.eliminate('end');
				fx.start({
					'margin-left':wrapper.getStyle('margin-left').toInt() - current_item.getSize().x
				});
			break;
			case 'previous':
				this.wrapper.eliminate('end');
				if(current_item == items[0]) this.wrapper.store('start_end', true);
				else this.wrapper.eliminate('start_end');
				if(this.wrapper.retrieve('start_end') || wrapper.retrieve('lock')) return;
				fx.start({
					'margin-left':wrapper.getStyle('margin-left').toInt() + current_item.getSize().x
				});
			break;
		}
	}
});

Array.implement({
	max: function() {
		return Math.max.apply({}, this);
	}
});

var Gallery3d = new Class({

	Implements:[Options, Events],

	options: {
		field:null,
		elements:null,
		controls:null
	},

	initialize: function(options) {
		this.setOptions(options);
		this.elements = this.options.elements;
		this.actives = this.elements.filter(function(elem) {return !elem.hasClass('disable');});
		this.field = this.options.field;
		this.controls = this.options.controls;
		this.paddings = {
			'right':this.elements[0].getSize().x/2,
			'bottom':this.elements[0].getSize().y/2
		}
		this.constructGallery();
		this.elements.each(function(elem, i) {
			elem.addEvent('click', function(e) {
				clearInterval(this.interval);
				this.rotate(elem);
			}.bind(this));
		}.bind(this));
	},

	constructGallery: function() {
		var big_half_axle = this.field.getSize().x/2 - this.paddings.right,
			little_half_axle = this.field.getSize().y/2 - this.paddings.bottom;
		var elems_col = this.elements.length;
		var cent_x = big_half_axle,
			cent_y = little_half_axle;

		var angle = 360/elems_col;
		var rad = 180/Math.PI;
		this.angle = angle;
		this.elements.each(function(elem, i) {
			var param_x = Math.cos(angle*(i)/rad).toFixed(6).toFloat(),
				param_y = Math.sin(angle*(i)/rad).toFixed(6).toFloat();
			elem.setProperty('rel', i+1);
			elem.setStyles({
				'top': little_half_axle*param_y + cent_y,
				'left': big_half_axle*param_x + cent_x
			});
		});

		var top_coord_showed = this.elements.map(function(elem) {return elem.getStyle('top').toInt()}).max();
		var showed_elem = this.elements.filter(function(elem) {return elem.getProperty('rel').toInt() == 1})[0];
		this.changeHandler(showed_elem);
		this.changeEventHandler();
	},

	rotate: function(elem) {
		if(this.field.retrieve('active')) return;
		var big_half_axle = this.field.getSize().x/2 - this.paddings.right,
			little_half_axle = this.field.getSize().y/2 - this.paddings.bottom;
		var cent_x = big_half_axle,
			cent_y = little_half_axle;
		var angle = this.angle,
			elems = this.elements,
			col = this.elements.length;
		var rad = 180/Math.PI;
		var top_coord_showed = elems.map(function(elem) {return elem.getStyle('top').toInt()}).max();
		var showed_elem = elems.filter(function(elem) {return elem.getProperty('rel').toInt() == 1})[0];
		var target_rel = elem.getProperty('rel'),
			showed_rel = showed_elem.getProperty('rel');
		var	rotate_angle = (target_rel.toInt() < ((col - 1)/2 + 1))?this.angle*(showed_rel.toInt() - target_rel.toInt()):this.angle*(col - target_rel.toInt() + showed_rel.toInt());
		if(rotate_angle == 0 || rotate_angle == 360) return;
		this.elements.each(function(element, i) {
			var own_top = element.getStyle('top').toInt(),
				own_left = element.getStyle('left').toInt(),
				own_rel = element.getProperty('rel').toInt(),
				helper = 0;
			var own_angle = angle*(own_rel-1),
				rel = own_rel;
				if(target_rel.toInt() >= ((col - 1)/2 + 1)) {
					rel = rel + (col - target_rel.toInt() + 1);
					rel = (rel > col)?(rel - col):rel;
				}
				if(target_rel.toInt() < ((col - 1)/2 + 1)) {
					rel = rel - (target_rel.toInt() - showed_rel.toInt());
					rel = (rel < 1)?(col - rel):rel;
				}
				element.setProperty('rel', rel);
			this.interval = setTimeout(function() {
				this.field.store('active', true);
				var param_x = Math.cos((own_angle + helper)/rad).toFixed(6).toFloat(),
					param_y = Math.sin((own_angle + helper)/rad).toFixed(6).toFloat();
				element.setStyles({
					'top': little_half_axle*param_y + cent_y,
					'left': big_half_axle*param_x + cent_x
				});
				(rotate_angle < 0)?helper-=5:helper+=5;
				if(Math.abs(helper) - Math.abs(rotate_angle) < 0) {
					setTimeout(arguments.callee.bind(this), 30);
				}else{
					this.field.eliminate('active');
				}
			}.bind(this), 30);
		}.bind(this));
		this.changeHandler(elem);
	},

	changeEventHandler:function() {
		this.controls.each(function(control) {
			control.addEvent('click', function(e) {
				new Event(e).stop();
				if(control.hasClass('active')) return;
				var control_num = control.getChildren().get('html');
				var cross_elem = this.elements.filter(function(elem) {return (!elem.hasClass('disable') && (elem.getElement('.num').get('html') == control_num))})[0];
				cross_elem.fireEvent('click');
			}.bind(this));
		}.bind(this));
	},

	changeHandler:function(showed) {
		var showed_num = showed.getElement('.num').get('html'),
			showed_link = showed.getProperty('link');
		var descr_field = this.field.getParent().getParent().getElement('.description');
		var descr_showed_name = descr_field.getElement('.h1').getElement('span');
		var descr = showed.getElement('.cont_descr').get('html'),
			link_to = descr_field.getElement('.btn').getElement('a');
		descr_field.getElement('.txt').set('html', descr);
		descr_showed_name.set('html', showed.getElement('.product_name').get('html'));
		link_to.setProperty('href', showed_link);
		this.controls.map(function(elem) {return elem.removeClass('active')});
		this.controls.filter(function(item) {return item.getChildren().get('html') == showed_num})[0].addClass('active');
	}

});