/**********************************************************************
 *	Класс для манипуляции окнами
 **********************************************************************/

function am_window()
{
	this.multi_win = false;	//	Режим открытия нескольких окон. Если true, то можно открывать несколько окон, если false, то при открытии окна, все предыдущие закрываются
	this.windows_info = {};	//	Список созданных окон с набором ключевой информации по каждому окну
	this.windows = 0;		//	Счётчик создаваемых окон. Используется для формирования уникальных ID
	this.opened = 0;		//	Счётчик открытых окон. Используется для контроля нагрузки на браузер.
	this.open_limit = 10;	//	Максимально допустимое количество открытых одновременно окон (Не стоит создавать больше 10 окон одновременно)

/**********************************************************************
 *	Создание нового окна
 **********************************************************************/

	this.open = function(config)
	{
		if (!this.multi_win)
		{
			for (w in this.windows_info)
			{
				this.close(w, true);
			}
		}
		//	Проверяю можно ли открыть ещё одно окно
		if (this.opened >= this.open_limit)
		{
			return;
		}
		this.opened++;
		//	Формирую ID окна по его порядковому номеру
		this.windows++;
		config.id = 'win-'+this.windows;
		//	Позиция окна относительно других (при создании присваивается наибольший z-index из всех окон)
		config.zindex = 20 + this.windows * 10;
		//	Рисую окно
		if (this._window_draw(config))
		{
			//	Вставляю в окно содержимое
			this._window_add_content(config.id, config.content);
			//	Добавляю события для этого окна
			this._window_add_events(config.id);
			return config.id;
		}
		return false;
	}
	
/**********************************************************************
 *	Закрытие окна и удаление его из документа
 **********************************************************************/

	this.close = function(id, fast)
	{
		//	Если id не указан или null, закрываю все созданные окна
		if (typeof id == 'undefined' || id == null)
		{
			for (var w in this.windows_info)
			{
				this.close(w, fast);
			}
			return;
		}
		//	Если в массиве окон нет записи с таким id, то ничего не происходит
		if (typeof this.windows_info[id] != 'object')
		{
			return;
		}
		if (fast == true)
		{
			$('#'+id).remove();
		}
		else
		{
			$('#'+id).fadeOut(500, function(){
				$(this).remove();
			});
		}
		delete this.windows_info[id];
		this.opened--;
	}
	
/**********************************************************************
 *	Отрисовка нового окна и вставка его в документ
 **********************************************************************/

	this._window_draw = function(config)
	{
		//	Подготоваливаю конфиг к использованию
		config = this._check_params(config);
		//	Если конфиг не годен - ничего не происходит
		if (config == false)
		{
			return false;
		}
		//	Создаю окно, задаю его размеры и позицию
		var win = $('<div>')
				. addClass('am-window-container')
				. attr('id', config.id)
				. css({'z-index':config.zindex, 'width':config.params.width, 'height':config.params.height, 'left':config.params.left, 'top':config.params.top});
		//	Добавляю блоки шапки и контента
		win.append($('<div>').addClass('am-window-head')).append($('<div>').addClass('am-window-content'));
		//	Добавляю границы (окантовку) окна
		win.append($('<div>').addClass('am-window-border-top'))
		   .append($('<div>').addClass('am-window-border-right'))
		   .append($('<div>').addClass('am-window-border-bottom'))
		   .append($('<div>').addClass('am-window-border-left'))
		   .append($('<div>').addClass('am-window-border-lt'))
		   .append($('<div>').addClass('am-window-border-rt'))
		   .append($('<div>').addClass('am-window-border-rb'))
		   .append($('<div>').addClass('am-window-border-lb'))
		   .append($('<div>').addClass('am-window-border-bar'));
		//	Добавляю хендлеры для ресайза, если указано
		if (config.params.resizable == true)
		{
			win.find('div[class|="am-window-border"]').each(function(){
				var rc = $(this).attr('class').replace('border', 'resize');
				$(this).addClass('am-window-resize '+rc)
			});
		}
		var head = win.children('div.am-window-head');
		//	Добавляю блок заголовка
		head.append($('<div>').addClass('am-window-title').html(config.title))
		//	Добавляю к шапке окна хендлер для перетаскивания, если указано
		if (config.params.draggable == true)
		{
			head.addClass('am-window-draggable');
		}
		//	Добавляю иконку окна, если указано
		if (config.params.icon == true)
		{
			head.append($('<div>').addClass('am-window-icon'))
			head.children('.am-window-title').addClass('am-window-title-with-icon');
		}
		//	Если окно можно сворачивать, добавляю кнопку в шапку
		if (config.params.minimizable == true)
		{
			head.append($('<div>').addClass('am-window-minimize'));
		}
		//	Если окно можно разворачивать, добавляю кнопку в шапку
		if (config.params.maximazable == true)
		{
			head.append($('<div>').addClass('am-window-maximize')).append($('<div>').addClass('am-window-restore'));
		}
		//	Если окно можно закрывать, добавляю кнопку в шапку
		if (config.params.closable == true)
		{
			head.append($('<div>').addClass('am-window-close'));
		}
		//	Добавляю окно в документ
		$('body').append(win);
		this.windows_info[config.id] = {
			'params'	: config.params,
			'zindex'	: config.zindex,
			'obj'		: win
		};
		return true;
	}
	
/**********************************************************************
 *	Добавление событий для окна с указанным id
 **********************************************************************/

	this._window_add_events = function(id)
	{
		//	Если в массиве окон нет записи с таким id, то ничего не назначается
		if (typeof this.windows_info[id] != 'object')
		{
			return;
		}
		//	Вывод окна "наверх" по клику на нём
		$('#'+id).bind('mousedown', {am_window:this}, function(e){
			e.data.am_window._window_set_active($(this).attr('id'));
		});
		//	Перетаскивание окна за заголовок
		if (this.windows_info[id].params.draggable == true)
		{
			$('#'+id+' .am-window-draggable').bind('mousedown', function(e){
				var data = {
					win	: $(this).closest('.am-window-container')
				};
				data['dX'] = e.pageX - parseInt(data.win.css('left'));
				data['dY'] = e.pageY - parseInt(data.win.css('top'))
				$('body').bind('mousemove', data, function(e){
					e.data.win.css({'left':e.pageX - e.data.dX, 'top':e.pageY - e.data.dY});
				});
				$('body *').disableSelection();
			});
			$('#'+id).bind('mouseup', {'win':this.windows_info[id]}, function(e){
				$('body').unbind('mousemove');
				e.data.win.params.left = $(this).css('left');
				e.data.win.params.top = $(this).css('top');
				$('body *').enableSelection();
			});
		}
		//	Изменение размеров окна
		if (this.windows_info[id].params.resizable == true)
		{
			$('#'+id+' .am-window-resize').bind('mousedown', {'win':this.windows_info[id]}, function(){
				
			});
		}
		//	Закрытие окна
		if (this.windows_info[id].params.closable == true)
		{
			$('#'+id+' .am-window-close').bind('click', {'class':this, 'id':id}, function(e){
				e.data['class'].close(e.data['id']);
			});
		}
	}

/**********************************************************************
 *	Добавление содержимого в контентную зону окна
 **********************************************************************/
	
	this._window_add_content = function(id, content)
	{
		if (typeof this.windows_info[id] != 'object')
		{
			return false;
		}
		if (typeof content.type == 'undefined')
		{
			content.type = 'html';
		}
		if (typeof content.data == 'undefined')
		{
			content.data = '';
		}
		switch(content.type)
		{
			case 'grid':
				break;
			default:
				this.windows_info[id].obj.find('.am-window-content').html(content.data);
		}
	}
	
/**********************************************************************
 *	Вывод окна с указанным id на верхний слой
 **********************************************************************/
	
	this._window_set_active = function(id)
	{
		if (typeof this.windows_info[id] == 'undefined')
		{
			return;
		}
		
		var max_z = this.windows_info[id].zindex;
		
		for (w in this.windows_info)
		{
			if (w == id)
			{
				continue;
			}
			if(this.windows_info[w].zindex >= this.windows_info[id].zindex)
			{
				if (this.windows_info[w].zindex > max_z)
				{
					max_z = this.windows_info[w].zindex;
				}
				this.windows_info[w].zindex -= 10;
				this.windows_info[w].obj.css({'z-index':this.windows_info[w].zindex});
			}
		}
		if (max_z != this.windows_info[id].zindex)
		{
			this.windows_info[id].zindex = max_z;
			this.windows_info[id].obj.css({'z-index':this.windows_info[id].zindex});
		}
	}
	
/**********************************************************************
 *	Проверка параметров для нового окна
 **********************************************************************/
	
	this._check_params = function(config)
	{
		if (typeof config != 'object')
		{
			return false;
		}
		//	Без ID окно не создаётся
		if (typeof config.id == 'undefined' || config.id.length == 0)
		{
			return false;
		}
		//	Конфигурация должна содержать объект с параметрами окна
		if (typeof config.params != 'object')
		{
			config.params = {};
		}
		//	Проверяю ширину окна
		if (typeof config.params.width == 'undefined')
		{
			config.params.width = 100;
		}
		config.params.width = parseInt(config.params.width);
		if (config.params.width < 100)
		{
			config.params.width = 100;
		}
		if (config.params.width > $(window).width())
		{
			config.params.width = $(window).width();
		}
		//	Проверяю высоту окна
		if (typeof config.params.height == 'undefined')
		{
			config.params.height = 40;
		}
		config.params.height = parseInt(config.params.height);
		if (config.params.height < 40)
		{
			config.params.height = 40;
		}
		if (config.params.height > $(window).height())
		{
			config.params.height = $(window).height();
		}
		//	Проверяю позицию окна по горизонтали
		if (typeof config.params.left == 'undefined')
		{
			config.params.left = 'center';
		}
		if (config.params.left == 'center')
		{
			config.params.left = ($(window).width() - config.params.width) / 2 + $(document).scrollLeft();
		}
		config.params.left = parseInt(config.params.left);
		if (config.params.left < 0)
		{
			config.params.left = 0;
		}
		if (config.params.left > $(document).width() - config.params.width)
		{
			config.params.left = $(document).width() - config.params.width;
		}
		//	Проверяю позицию окна по вертикали
		if (typeof config.params.top == 'undefined')
		{
			config.params.top = 'center';
		}
		if (config.params.top == 'center')
		{
			config.params.top = ($(window).height() - config.params.height) / 2 + $(document).scrollTop();
		}
		config.params.top = parseInt(config.params.top);
		if (config.params.top < 0)
		{
			config.params.top = 0;
		}
		if (config.params.top > $(document).height() - config.params.height)
		{
			config.params.top = $(document).height() - config.params.height;
		}
		//	Заголовок окна должен присутствовать, даже пустой
		if (typeof config.title == 'undefined')
		{
			config.title = '';
		}
		return config;
	}
}

/**********************************************************************
 *	Расширение jQuery для запрета выделения мышью
 **********************************************************************/

jQuery.fn.extend({
    disableSelection : function() {
            this.each(function() {
                    this.onselectstart = function() { return false; };
                    this.unselectable = "on";
                    jQuery(this).css('-moz-user-select', 'none');
            });
    },
    enableSelection : function() {
            this.each(function() {
                    this.onselectstart = function() {};
                    this.unselectable = "off";
                    jQuery(this).css('-moz-user-select', 'auto');
            });
    }
});
