/**
 * Основные утилиты, используемые на форуме.
 * Объект имеет глобальную область видимости.
 * Доступен из любого скрипта и участка форума.
 *
 * @author Setteros <setteros@theabyss.ru>
 * @copyright Copyright © 2008-2010, Theabyss.ru
 * @access public
 * @package Tools
 * @version 2.0.0
 */

var Extratools =
{
	Mp3PlayerStartId: 0,
	CachedLastPosts: new Array(),
	TooltipOffset: 10,
	ScrollbarWidth: 20,
	PostEffectsAllowed: true,
	AllowedDialogAttributes: ['_queryMonitor', '_title', '_width', '_height', '_modal', '_draggable', '_resizable', '_dialogId', '_autoClose', '_afterClose'],
	DialogAutocloseInterval: 3000, // Секунд

	QueryMonitor: {
		_previousHash: null,
		_queryMonitorIntervalHandle: null,
		_interval: 200,

		/**
		 * Устанавливает hash часть ссылки в адресной строке браузера
		 * @param value string		hash к устрановке
		 * @param silently boolean	Флаг, указывающий, меняется ли hash без оповещения подписчиков на эвент
		 */
		SetHash: function(value, silently){
			if( Boolean(silently) )
				this._previousHash = value

			window.location.hash = value;
		},

		/**
		 * Активация менеджера
		 */
		Start: function(){
			var self = this;
			if( null != self._queryMonitorIntervalHandle )
				return;

			self._queryMonitorIntervalHandle = setInterval( function(){
				self._monitor();
			}, self._interval );
		},

		/**
		 * Остановка менеджера
		 */
		Stop: function(){
			clearInterval(this._queryMonitorIntervalHandle);
		},

		_monitor: function(){
			var query = this._getQueryString();
			if( this._previousHash != query )
				$(document).trigger('querymonitor', [this._parseQueryToObj(query)]);

			this._previousHash = query;
		},

		_getQueryString: function(){
			var hash = $.trim(window.location.hash);
			if( '' != hash && null != hash.match(/^#\/.+?$/) ){
				hash = hash.replace(/^#\//, '');
			}

			return hash;
		},

		_parseQueryToObj: function(queryString){
			var obj = {}
			var parts = queryString.split('/');
			for( var i = 0; i < parts.length - 1; i += 2 )
				obj[parts[i]] = parts[i+1];

			return obj;
		},

		GetQuery: function(){
			return this._parseQueryToObj(this._getQueryString());
		},

		/**
		 * Метод для удобной проверки, содержит ли объект нужные методы
		 * @param queryObj object	Объект
		 * @param params array		Массив свойств
		 * @param andFlag boolean	Флаг, указывающий, как ищутся свойства. Через OR по умолчанию
		 */
		IsExpectedQuery: function(queryObj, params, andFlag){
			var count = 0;
			for( var n in params )
				if( !queryObj[params[n]] )
					count++;

			if( $.isEmptyObject(queryObj) ||
				(Boolean(andFlag) && count == 0) ||
				(!Boolean(andFlag) && count < params.length) )
				return true;

			return false;
		}
	},

	/**
	 * Индикатор загрузки
	 */
	Loader: {
		_loader: null,

		_initLoader: function(){
			this._loader = $('<div />', {
				id: 'loader-wrapper'
			}).append($('<div />', {
				id: 'loader-shadow',
				className: 'ui-widget-shadow ui-corner-all'
			})).append($('<div />',{
				id: 'loader'
			})).appendTo('body');
		},

		Show: function(){
			if( null === this._loader ){
				this._initLoader();
			}
			this._loader.show();
		},

		Hide: function(){
			this._loader.hide();
		}
	},
	
	ParseInteractiveLinks: function(){
		var self = this;

		$( "a.interactive" )
		.die('click')
		.live('click', function(){
			var opt = $.data(this, 'options'),
			obj = $(this),
			href = obj.attr('href');
			if( !opt )
			{
				opt = {}

				var allowed = self.AllowedDialogAttributes; // Допустимые атрибуты тега A
				for( var n in allowed )
					if( obj.attr(allowed[n]) != "undefined" )
						opt[String(allowed[n]).replace('_', '')] = isNaN(obj.attr(allowed[n])) ? obj.attr(allowed[n]) : Number(obj.attr(allowed[n]));

				$.data(this, 'options', opt);
			}
			
			self.OpenWindow(href, opt);

			return false;
		});
	},

	/**
	 * Асинхронный подзапрос на сервер.
	 */
	AsyncRequest: function( url, data, callback, params )
	{
		if ( $.isFunction( data ) )
		{
			params = callback || params;
			callback = data;
			data = {};
		}

		if( !$.isPlainObject(params) )
			params = {};

		var defParams = {
			type: 'html',
			method: 'GET',
			loader: true
		}

		$.extend(defParams, params);

		if( defParams.type == 'json' )
			url = ipb_var_base_url + ['act=jsonout', url].join('&');

		var self = this;
		$.ajax({
			type: defParams.method,
			url: url,
			data: data,
			beforeSend: function()
			{
				if( defParams.loader )
					self.Loader.Show();
			},
			complete: function(XMLHttpRequest, textStatus)
			{
				if( defParams.loader )
				{
					if( textStatus != 'success' )
						self.ShowError( jsfile_error_lang, textStatus );

					self.Loader.Hide();
				}
			},
			success: function( answer )
			{
				if( defParams.type == 'json' )
					if( answer.status > 0 )
					{
						self.ShowError( jsfile_error_lang, answer.data );
						return;
					}

				if( $.isFunction(callback) )
					callback( defParams.type == 'json' ? answer.data : answer );
			}
		});
	},

	/**
	 * Всплывающая подсказка
	 */
	Tooltip: function( target, data )
	{
		var tools = this;
		var div = $( "#tooltip" );
		var CalculatePosition = function( x, y )
		{
			var width = $( document ).width() - tools.TooltipOffset;

			width -= $.browser.msie ? tools.ScrollbarWidth : 0;

			return ({
				top: y + tools.TooltipOffset,
				left: width <= x + div.outerWidth() ? x - div.outerWidth() - tools.TooltipOffset : x + tools.TooltipOffset
			});
		}

		div
		.clearQueue()
		.html( $( "<span />", {
			'class': 'ui-icon ui-icon-comment'
		} ) )
		.append( $( "<div />" ).html( data ) )
		.addClass( 'ui-state-highlight ui-corner-all' );

		target
		.unbind( 'mousemove' )
		.unbind( 'mouseout' )
		.mousemove(
			function( e )
			{
				var pos = CalculatePosition( e.pageX, e.pageY );

				div.css( {
					'top': pos.top,
					'left': pos.left
				});
			} )
		.mouseout(
			function()
			{
				div.fadeOut( 'fast', function(){
					$( this ).hide();
				} );
			} );

		if( div.is(":hidden") )
			div
			.css({
				'position': 'absolute',
				'opacity': 0
			})
			.show()
			.fadeTo( 'fast', 0.9 );
	},

	/**
	 * МП3 плеер
	 */
	InitMp3Player: function( link )
	{
		var url = link.attr( "href" );
		link.replaceWith( $( "<div />", {
			'id': 'mp3player_' + this.Mp3PlayerStartId
		} ) );

		swfobject.embedSWF(
			'uppod/uppod.swf',
			'mp3player_' + this.Mp3PlayerStartId,
			'250',
			'22',
			'9.0.115',
			false,
			{
				'm': 'audio',
				'st': ipb_var_image_url + '/uppod/mp3player.txt',
				'file': url,
				'uid': 'mp3player_' + this.Mp3PlayerStartId
			},
			{
				'id': 'mp3player_' + this.Mp3PlayerStartId,
				'allowFullScreen': false,
				'allowScriptAccess': 'always',
				'wmode': 'transparent'
			} );

		this.Mp3PlayerStartId++;
	},

	/**
	 * Диалоговое окно с ошибкой
	 */
	ShowError: function( title, body )
	{
		$( "<div />" )
		.html(
			$( "<div />", {
				'class': 'ui-state-error ui-corner-all',
				'css': {
					'text-align': 'left'
				}
			})
			.html(
				$( "<p />" )
				.html( $( "<span />", {
					'class': 'ui-icon ui-icon-alert',
					'css': {
						'float': 'left',
						'margin': '0em 0.5em'
					}
				}) )
				.append( body )
				) )
		.dialog( {
			'modal': true,
			'resizable': false,
			'title': title,
			'buttons': {
				'Ok': function() {
					$(this).dialog('close');
				}
			}
		})
		.dialog('moveToTop');
	},

	/**
	 * Окно с загружаемыми данными посредством асинхронного запроса
	 */
	OpenWindow: function( url, dialogopt, callback )
	{
		// Устанавливаем переменные
		var defaultopt = $.extend({
			'autoOpen': false,
			'queryMonitor': false
		}, dialogopt || {}),
		self = this, 
		div =  $( "<div />", {
			'css': {
				'opacity': 0.9,
				'text-align': 'left'
			}
		} );

		// Проверяем, задан ли ID
		if( defaultopt.dialogId )
		{
			// Если айди задан, и диалоговое окно уже создано - выходим
			if( $('#' + defaultopt.dialogId).length > 0 )
				return;

			// Устанавливаем ID
			div.attr('id', defaultopt.dialogId);
		}

		var loadAndParse = function( answer )
		{
			// Если в ответе нет необходимости, сразу закрываем окно
			if( $.trim(answer) == '' )
				div.dialog( 'close' );

			var t = div.html( answer );

			var links = t.find( "a.interactive" );
			var forms = t.find( "form.interactive" );

			// Преобразуем ссылки
			links.click( function(){
				self.AsyncRequest($( this ).attr('href'), function( html ){
					loadAndParse( html );
				});

				return false;
			});

			// Преобразуем формы
			forms.submit( function(){
				var fields = $(this).serialize();

				self.AsyncRequest($( this ).attr('action'), fields, function( html ){
					loadAndParse( html );
				}, {
					method: 'post'
				} );

				return false;
			});
			
			// Если интерактивных элементов нет, закрываем окно через несколько секунд
			if( defaultopt.autoClose && links.length == 0 && forms.length == 0 )
			{
				setTimeout( function(){
					div.dialog( 'close' );
				}, self.DialogAutocloseInterval );
			}
		}

		if( defaultopt.queryMonitor ){
			self.QueryMonitor.SetHash('/', true);
			$( document ).bind( 'querymonitor.popupwindow', function( event, query ){
				self.AsyncRequest(url, query, function( html ){
					loadAndParse( html );
				});
			});
		}

		self.AsyncRequest(url, function( answer ){
			// Создаем диалог
			div.dialog( defaultopt )
			.bind( "dialogclose", function(){
				div.dialog('destroy'); // Удаляем диалог
				div.remove(); // Удаляем слой из DOM
				if( defaultopt.queryMonitor )
					$( document ).unbind('querymonitor.popupwindow');
			});

			// Загружаем внутренности и парсим
			loadAndParse( answer );

			// Открываем
			div.dialog( 'open' );

			if( $.isFunction(callback) )
				callback();
		});
	},

	/**
	 * Загрузка первого и последнего сообщения топика
	 */
	GetForumPost: function( obj )
	{
		var tools = this;

		var LoadForumPost = function( obj )
		{
			var self = this;

			this.PostBody = "";
			this.Loaded = false;
			this.Owner = obj;
			this.Code = this.Owner.attr( "class" );
			this.TopicID = this.Owner.attr( "rel" );
			this.Data =
			{
				'act': "jsonout",
				'do': this.Code,
				'topic_id': this.TopicID
			}

			this.Show = function()
			{
				tools.Tooltip( this.Owner, '<img alt="Загрузка..." src="' + ipb_var_image_url + '/abyss_loader.gif" />' );

				if( !this.Loaded )
				{
					$.getJSON( "index.php", this.Data, function( answer ){
						self.callback_Answer( answer )
					} );
				}
				else
				{
					this._showPost();
				}
			}

			this.callback_Answer = function( answer )
			{
				if( answer.status > 0 )
				{
					return; // error
				}

				this.PostBody = answer.data;
				this.Loaded = true;

				this._showPost();
			}

			this._showPost = function()
			{
				if( this.PostBody == null )
				{
					return;
				}

				tools.Tooltip( this.Owner, this.PostBody );
			}
		}

		var id = obj.attr( "rel" ) + obj.attr( "class" );

		if( typeof this.CachedLastPosts[id] == "undefined" )
		{
			this.CachedLastPosts[id] = new LoadForumPost( obj );
		}

		this.CachedLastPosts[id].Show();
	},
	
	GoogleSearch: function(){
		var isVisible = false;
		$(document).keyup(function(event) {
			if( event.which == 70 && event.altKey && event.ctrlKey ){
				event.preventDefault();
				
				var div = $('#google-search');
				if( !isVisible ){
					div.show('slide', {
						'direction': 'up'
					}, 'slow', function(){
						$('input.gsc-input', div).focus();
					});
				}else{
					div.hide('slide', {
						'direction': 'up'
					}, 'slow');
				}
				
				isVisible = !isVisible;
			}			
		});
	},

	/**
	 * Различные эффекты в сообщениях топика
	 */
	PostEffects: function()
	{
		if( !this.PostEffectsAllowed )
			return;

		var tools = this;

		// Картинки
		(function()
		{
			$.getScript( 'jscripts/lib/jquery.easing.js', function(){
				$.getScript( 'jscripts/lib/jquery.mousewheel.js', function(){
					var images = "a[href$='.jpeg'],a[href$='.jpg'],a[href$='.bmp'],a[href$='.png'],a[href$='.gif']";

					$( "div[id^='post-']" ).each( function() {
						$( this ).find( images ).attr( 'rel', 'gallery-' + $( this ).attr( 'id' ) );
					});

					$( images )
					.fancybox({
						'overlayOpacity': 0.8,
						'hideOnContentClick': false,
						'overlayColor': '#000',
						'centerOnScroll': true,
						'padding': 3,
						'titleShow': false,
						'cyclic': true,
						'transitionIn': 'elastic',
						'transitionOut': 'elastic'
					}).addClass("media media-image");
				});
			});
		})();

		// Ролики
		(function()
		{
			var commonParams =  {
				"overlayOpacity": 0.8,
				"hideOnContentClick": false,
				"overlayColor": "#000",
				"centerOnScroll": true,
				"padding": 3,
				"width": 680,
				"height": 460,
				"titleShow": false,
				"transitionIn": "elastic",
				"transitionOut": "elastic",
				"type": "swf"
			}

			// Youtube
			$( "a[href^='http://www.youtube.com/watch?v=']" ).each(function()
			{
				var params = $.extend({}, commonParams, {
					href: $( this ).attr( "href" ).replace(/watch\?v=/i, 'v/')
				});

				$( this ).fancybox(params).addClass("media media-video");
			});

			// Vkontakte
			$( "a[href^='http://vkontakte.ru/video_ext.php?']" ).each(function()
			{
				var params = $.extend({}, commonParams, {
					type: 'iframe'
				});

				$( this ).fancybox(params).addClass("media media-video");
			});

			// Rutube
			$( "a[href^='http://rutube.ru/tracks/']" ).each(function()
			{
				var params = $.extend({}, commonParams, {
					href: $( this ).attr( "href" ).replace(/tracks\/\d+\.html\?v=/i, '').replace('http://rutube.ru', 'http://video.rutube.ru')
				});

				$( this ).fancybox(params).addClass("media media-video");
			});

			// Vimeo
			$( "a[href^='http://www.vimeo.com/']" ).each(function()
			{
				var href = $( this ).attr('href');
				if( href.search(/^http:\/\/www\.vimeo\.com\/\d+$/i) < 0 )
					return;

				var params = $.extend({}, commonParams, {
					type: 'iframe',
					href: href.replace('http://www.vimeo.com/', 'http://player.vimeo.com/video/')
				});

				$( this ).fancybox(params).addClass("media media-video");
			});
		})();

		// Медиа mp3
		(function()
		{
			var mp3 = $( "a[href$='.mp3']" );

			if( mp3.size() > 0 )
			{
				$.getScript( 'uppod/swfobject.js', function(){
					$.getScript( 'uppod/uppod_player.js', function(){
						if( !swfobject.hasFlashPlayerVersion("9.0.115") )
						{
							return;
						}

						mp3.each(function(){
							tools.InitMp3Player( $( this ) );
						});

						uppodStartsReport( function( playerid ){
							uppodStopAll( playerid );
						} );
					});
				});
			}
		})();

		// Тег HIDE
		(function()
		{
			var SetIcon = function( obj )
			{
				obj.each( function()
				{
					$( this ).css( "background-image", $( this ).next( "div.hidemain" ).is( ":visible" )
						? "url(" + ipb_var_image_url + "/topic_selected.gif)"
						: "url(" + ipb_var_image_url + "/topic_unselected.gif)" );
				});
			}

			$( "div.hidetop" )
			.each( function()
			{
				var self = this;
				$( self ).next( "div.hidemain.visible" ).slideDown( "slow", function() {
					SetIcon( $( self ) );
				} );
			})
			.unbind("click").click( function( e )
			{
				var self = this;
				e.preventDefault();
				if( e.ctrlKey )
				{
					var allinpost = {
						title: $( self ).nextAll( "div.hidetop" ),
						body: $( self ).nextAll( "div.hidemain" )
					}

					if( $( self ).next( "div.hidemain" ).is( ":hidden" ) )
					{
						allinpost.body.slideDown( "fast", function() {
							SetIcon( allinpost.title );
							SetIcon( $( self ) );
						} );
					}
					else
					{
						allinpost.body.slideUp( "fast", function() {
							SetIcon( allinpost.title );
							SetIcon( $( self ) );
						} );
					}
				}
				else
				{
					$( self )
					.next( "div.hidemain" )
					.slideToggle( "fast", function() {
						SetIcon( $( self ) )
					} );
				}

				return false;
			});
		})();
	}
}
