﻿/// <reference path="jquery-1.4.1-vsdoc.js" />
/// <reference path="jquery.extensions.js" />

$.factory.create({

	giftSelectController: function(selector, messages) {
		var 
		self = this,
		_$ = window.$,
		_selector,
		_messages,
		_timeout,

		addBehaviour = function() {
			_selector.submit(function() {
				var data = _selector.disable().getData();
				/*_messages.clear();*/

				serviceChannel.orderGift(
					notificationDispatcher.getAttendee(),
					data,

					function() { // success
						_messages.success(data);
						_selector.hide().enable();
					},

					function(xhr, status) { // error
						switch (xhr.status) {
							case 409:
								_messages.limit(
									_$.parseJSON('{ "expiration": ' + xhr.responseText + ' }')
									);
								break;
							case 402:
								break;
							default:
								_messages.error();
								break;
						};

						_selector.enable();
					}
				);
			});

			_selector.hide(function() {
				_timeout && clearTimeout(_timeout);
				_messages.clear();
			});
		}

		;

		// ctor

		_selector = selector;
		_messages = messages;

		addBehaviour();
		return self;
	},

	giftSelectPresenter: function(data) {
		var 
		_$ = window.$,
		self = this,
		_overlay,
		_curtain,
		_container,
		_notify,
		_form,
		_attendee,

		_checks,
		_checked,
		_periods,
		_comment,

		bindData = function(data) {
			var template = _container.find('.gifts-list li.template');
			var container = template.parent(':first');

			for (var i = data.length; i--; ) {
				var item = template.bindo(data[i]).prependTo(container);
				_$.fn.fixpng && item.find('.png').fixpng();
			}

			template.remove();
			return self;
		},

		attachBehaviour = function() {
			var $ = _$;

			$.notify('show-gift-selector', self.show);

			$.notify('attendee-profile', function(attendee) {
				_attendee = attendee;
			});

			self.scan('#gift-cancel').click(self.hide);
			_checks.click(check).filter(':checked').click();

			_form.submit(function(e) {
				e.preventDefault();
			});
		},

		bindHotkeys = function() {
			var hotkeys = _$.hotkeys;

			if (!hotkeys)
				return;

			hotkeys.listen(hotkeys.keys.escape, self.hide, 'gifts-presenter');
		},

		clearHotkeys = function() {
			_$.hotkeys.clearAllKeys('gifts-presenter');
		},

		check = function() {
			_checked && _checked.parents('li:first').removeClass('selected');
			(_checked = _checks.filter(':checked')).parents('li:first').addClass('selected');
		}

		// events listeners
		onHide = [],
		onShow = []

		;

		self.show = function(fn) {
			if (_$.isFunction(fn))
				return onShow.push(fn);

			notificationDispatcher.freeze(function(name) {
				return name != 'account-state';
			});

			_container.find('.attendee-name').bindo({ attendee: _attendee }, false);
			_overlay.show();
			_curtain.css({ opacity: 0, display: 'block' }).stop().animate({ opacity: .75 }, 200);

			_container
				.stop()
				.animate({ top: _container.restore('top') }, 700, 'easeOutExpo')
				.find('input[name=gift-id]:first')
				.attr('checked', 'checked')
				.click()
				;

			bindHotkeys();

			for (var i = onShow.length; i-- > 0; )
				onShow[i].call(self);

			return self;
		};

		self.hide = function(fn) {
			var $ = _$;

			if ($.isFunction(fn)) {
				onHide.push(fn);
				return self;
			}

			_container.stop().animate({ top: -_container.restore('height') + 'px' });
			_curtain.stop().animate({ opacity: 0 }, 200, 'easeOutExpo', function() {
				_overlay.hide(); // todo: _overlay.hide as callback ?
			});

			self.reset();

			for (var i = onHide.length; i-- > 0; )
				onHide[i].call(self);

			$.hotkeys.clearGroup('gifts-presenter');
			notificationDispatcher.unfreeze();

			$.notify('gift-selector-closed', self);

			return self;
		};

		self.reset = function() {
			_form.reset();
			check();

			return self;
		};

		self.disable = function() {
			_form.find('input, select, textarea').attr('disabled', 'disabled');
			return self;
		};

		self.enable = function() {
			_form.find('input, select, textarea').removeAttr('disabled');
			return self;
		};

		self.getData = function() {
			return {
				giftID: _checks.filter(':checked').val() || 0,
				expirationPeriod: _periods.filter(':checked').val() || 0,
				coverMessage: _comment.val() || '',
				member: _attendee
			};
		};

		// public events
		self.submit = function(fn) {
			_form.submit(fn);
		};

		// ctor
		_container = self.scan('#gift-selector');
		bindData(data);

		_form = _container.find('form:first');
		_checks = _form.find('input[name="gift-id"]');
		_periods = _form.find('input[name="period"]');
		_comment = _form.find('#gift-messagebox');

		_overlay = self.scan('#pop-wrapper');
		_curtain = _overlay.find('#overlay');
		_notify = _container.find('#gift-notifications');

		_container
			.store('top', _container.css('top'))
			.css({ top: '-1000px' })
			.removeClass('hidden')
			;

		_overlay
			.removeClass('hidden')
			.each(function() {
				var height = _container.height();

				_container
					.store('height', height)
					.css({
						top:
							-height + 'px'
					})
					;
			})
			.hide()
			;

		attachBehaviour();
		return self;
	},

	giftSelectNotificationsPresenter: function() {
		var 
		self = this,
		_$ = window.$,
		_timeout,
		_classes = {},

		notify = function(type, temp, data) {
			var msg = self.find('.' + type).bindo(data || {}, false).parent();
			_timeout && (_timeout = clearTimeout(_timeout));

			msg.hasClass('template')
				? msg.clone().removeClass('template').addClass(type).appendTo(msg.parent())
				: msg.hasClass(type)
					? msg.animate({ opacity: .5 }).animate({ opacity: 1 })
					: _classes[type]
						= !!msg
							.addClass(type)
							.store('height', msg.height())
							.height(0)
							.animate({ height: msg.restore('height') + 'px' }, function() {
								msg.css({ height: 'auto' });
							})
				;

			if (!temp)
				return;

			_timeout = setTimeout(function() {
				msg.animate({ height: 0 }, function() {
					delete _classes[type];
					msg.removeClass(type).css({ height: 'auto' });
				});
			}, 30000);

		}

		;

		self.process = function() {
		};

		self.success = function(data) {
			data['coverMessage'] = data['coverMessage']
				.replace(/&/g, '&amp;')
				.replace(/</g, '&lt;')
				.replace(/>/g, '&gt;')
				.replace(/\n/g, '<br />');

			notify('success', false, data);
			_$.notify('message-log-updated', this);

			return self;
		};

		self.error = function() {
			notify('error', true);
			return self;
		};

		self.limit = function(data) {
			notify('limit-exceeded', false, data);
			return self;
		};

		self.clear = function() {
			_timeout && clearTimeout(_timeout);

			for (var type in _classes)
				self.removeClass(type);

			return self.stop(true, true);
		};

		// ctor
		return self;
	},

	giftCostPresenter: function(prices) {
		var 
		self = this,
		_prices,
		_container,
		_lifetimes,
		_price,
		_period,
		_periodS,

		getCost = function() {
			return /*_lifetimes.filter(':checked').val()*/7 * _prices.daily + _prices.base;
		},

		update = function() {
			//var period = _lifetimes.filter(':checked').val();
			var period = 7;

			_price.text(getCost());
			_period.text(period);
			_periodS.css({ display: period > 1 ? 'inline' : 'none' });
		},

		addBehaviour = function() {
			_lifetimes.click(function() {
				update();
			});
		}

		;

		// ctor

		_prices = prices;
		_price = self.scan('#gift-total-cost');
		_period = self.scan('#gift-order-period');
		_periodS = self.scan('#gift-order-period-s');
		_lifetimes = self.find('#gift-options input[name="period"]');

		addBehaviour();
		update();

		return self;
	},

	giftReceiver: function() {
		var 
		self = this,
		_$ = window.$,
		_received = []

		;

		self.process = function(notifications, attendee) {
			var $ = _$, gift, orderID;

			self.timestamp = null; // для совместимости со старым invitesReceiver

			for (var i = 0, length = notifications.length; i < length; i++) {
				gift = notifications[i];
				orderID = gift['order-id'];

				if ($.inArray(orderID, _received) === -1) {
					_received.push(orderID);
					gift.fresh = true;
				}
			}

			$.notify('gift-received', [notifications, attendee]);
		}

		// ctor
		return self;
	},

	giftReceivedController: function(presenter) {
		var 
		self = this,
		_$ = $,
		_presenter = presenter,
		_presented = [],

		process = function(gifts, attendee) {
			for (var i = 0, length = gifts.length; i < length; i++) {
				var gift = gifts[i];
				var orderID = gift['order-id'];

				if (!orderID)
					return;

				if (attendee === gift.sender.id && _$.inArray(orderID, _presented) === -1) {
					_presenter.received(gift);
					_presented.push(orderID);
				}
			}
		},

		flush = function() {
			_presented = [];
		}

		;

		// ctor
		_$.notify('gift-received', process);
		/*_$.notify('attendee-changed', flush);*/

		return self;
	},

	giftReceivedMessagePresenter: function() {
		var 
		self = this,
		_$ = $,
		_container,
		_translationEnabled = _$.storage.get('translation-enabled'),

		addMessageBehaviour = function(msg) {
			var $ = _$;

			if (!$.browser.msie)
				msg
					.css({ opacity: 0 })
					.animate({ opacity: 1 }, 200)
					;

			msg.find('input.gift-reply').click(function() {
				$.notify('show-gift-selector');
			});

			if (_translationEnabled)
				$.notify('translate-me', [msg.find('.translation'), function() {
					$.notify('message-log-updated', this);
				} ]);

			var image = msg.find('img.received-gift-image').css({ display: 'none' });
			image.fixpng && image.fixpng();

			setTimeout(function() {
				animate(msg.find('.animation'), image);
			}, 1000);
		},

		show = function(type, data) {
			if (!data)
				throw 'Gift data is empty.';

			addMessageBehaviour(self.bindo(data).removeClass('template').addClass(type).appendTo(_container));

			_$.notify('message-log-updated', this);

			return self;
		},

		animate = function(viewport, image) {
			var $ = _$;
			var keyframes = [
				{
					top: '-20px',
					height: image.height() + 'px'
				}, {
					display: 'block',
					top: '-20px'
				}, {
					top: '10px',
					height: (image.height() - 10) + 'px'
				}, {
					top: '0px',
					height: image.height() + 'px'
				}
			];

			if (!$.browser.msie) {
				keyframes[0]['opacity'] = 0;
				keyframes[1]['opacity'] = .5;
				keyframes[2]['opacity'] = 1;
			}

			$.factory.cartoon.getx(viewport, 8, 800)
				.attach(
					3,
					$.factory.keyframes.getx(image, keyframes)
					.soften(100)
				)
				.play(function() {
					$.browser.msie
						? setTimeout(function() { viewport.css({ display: 'none' }) }, 1400)
						: viewport.delay(600).animate({ opacity: 0 }, 800);
				});

			return self;
		}

		;

		self.received = function(gift) {
			show('received', gift);
			return self;
		};

		// ctor
		_container = self.parent(':first');

		_$.notify('translation-toggled', function(state) {
			_translationEnabled = state;
		});

		return self;
	}

});
