// Depends on: jQuery.ui, in3s.fileUploader.
//
//
//		<div id="gallery_add_dialog">
//			<input id="file" type="file" name="file"> 
//		</div>

// Добавляем к типу Array метод indexOf, если браузер его не поддерживает.
if (!Array.prototype.indexOf)
{
	Array.prototype.indexOf = function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from =	(from < 0)
			? Math.ceil(from)
			: Math.floor(from);
			
		if (from < 0)
			from += len;

		for (; from < len; from++)
		{
			if (from in this && this[from] === elt)
				return from;
		}
		
		return -1;
	};
};

	
jQuery.widget('in3s.galleryViewer', {

	_pageNumbers: [null, null, null],
	_buffer: {},
	_photoCount: 0,
	_addDialog: null,

	//
	//	This method is used to prevent event listeners of the same group to be triggered.
	//
	//	Mozilla uses e.stopPropagation(), but IE uses cancelBubble = true.
	//
	_stopPropagation: function(e)
	{
		if(typeof(e.stopPropagation) != "undefined")
		{
			e.stopPropagation();
		}
		if(typeof(e.cancelBubble) != "undefined")
		{
			e.cancelBubble = true;
		}
	},

	// 
	// 
	//
	_editPanel: function(el, option)
	{
		var sel = this;
		switch (option)
		{
			case 'show' : 
				// create edit panel
				var el_p = document.createElement('DIV');
				el.appendChild(el_p);
				el_p.className = 'editPanel';
				el_p.style.width = el_p.offsetParent.clientWidth + 'px';//'100%';
				el_p.style.height = '29px';
				el_p.style.position = 'absolute';
				el_p.style.cursor = 'default !important';
				el_p.style.backgroundColor = '#EEE';
				el_p.style.top = (el_p.parentNode.clientHeight - el_p.offsetHeight) + 'px';
				el_p.style.left = '0px';
				el_p.onclick = function(e){var e = e || event; sel._stopPropagation(e)};
				
				// create 'delete' panel button
				var el_b = document.createElement('IMG');
				el_b.title = 'Удалить';
				el_b.src = '/img/trash.gif';
				el_b.style.width = '25px';
				el_b.style.height = '25px';
				el_b.style.margin = '2px';
				el_b.style.cssFloat = 'right';
				el_b.style.styleFloat = 'right';
				el_b.style.cursor = 'pointer';
				el_b.onclick = function(){sel._delete(el.url)};
				el_p.appendChild(el_b);

				// create 'favorites' panel button
				el_b = document.createElement('IMG');
				el_b.title = 'Избранное';
				el_b.src = el.fav ? '/img/star_on.gif' : '/img/star_off.gif';
				el_b.style.width = '25px';
				el_b.style.height = '25px';
				el_b.style.margin = '2px';
				el_b.style.cssFloat = 'left';
				el_b.style.styleFloat = 'left';
				el_b.style.cursor = 'pointer';
				el_b.onclick = function(){sel._toggleFavorites(el)};
				el_p.appendChild(el_b);

				// create 'order' panel button
				el_b = document.createElement('INPUT');
				el_b.type = 'text';
				el_b.value = el.i + 1;
				el_b.style.width = '25px';
				el_b.style.height = '23px';
				el_b.style.margin = '2px';
				el_b.style.border = '0px';
				el_b.style.cssFloat = 'left';
				el_b.style.styleFloat = 'left';
				el_b.style.textAlign = 'center';
				el_b.onkeypress = function(e)
					{
						var e = e || event;
						
						if (e.keyCode == 13)
						{
							sel._setOrder(el.url, this.value - 1);
						}
					};
				el_p.appendChild(el_b);

				break;
			case 'hide' :
				var el_p = jQuery('.editPanel', el).get(0);
				if (el_p)
				{
					el.removeChild(el_p);
				}
				break;
		}
	},
	
	_setOrder: function(id, order)
	{
		var sel = this;
		
		if (order >= 0 && order < this._photoCount)
		{
			jQuery.get(
				"g_order.php",
				{id: id, tid: this.options.topic_id, o: order},
				function(data)
				{
					sel._refresh();
				}
			)
		}
	},
	
	_toggleFavorites: function(el)
	{
		var sel = this;
		
		if (el.fav)
		{
			jQuery.get(
				"g_favorite.php",
				{id: el.url},
				function(data)
				{
					sel._refresh();
				}
			);			
		}
		else
		{
			jQuery.get(
				"g_favorite.php",
				{id: el.url,
				  a: 'add'},
				function(data)
				{
					sel._refresh();
				}
			);			
		}
	},
	
	_delete: function(id)
	{
		if (window.confirm('Удалить фотографию?'))
		{
			var sel =this;
			
			jQuery.get(
				"g_delete.php",
				{id: id},
				function(data)
				{
					sel._refresh();
				}
			);
		}
	},
	
	_setAlbumPhoto: function(id)
	{
		var jel = jQuery('.album_photo img', this.element);

		var sel = this;
		
		if(id)
		{
			jel.load(
				function()
				{
					jel.fadeIn('slow'); 
					/*сюда вставить запуск отсчета счетчика слайдшоу*/
					if (sel.options.runSlideShow && sel._photoCount > 0)
					{
						window.clearTimeout(sel._intervalId);						
						sel._intervalId = window.setTimeout(function(){sel._nextPhoto()}, sel.options.slideShowDelay);
					}
				}
				);

			jel.fadeOut('slow', 
				function()
				{
					jel.get(0).src = 'g_image.php?id=' + id
				});
		}
		else
		{
			jel.fadeOut('slow', 
				function()
				{
					jel.get(0).src = ''
				});
		}
	},

	_init: function()
	{
		var sel = this;

		// bind "nextPhoto" acion to large photo onclick event.
		jQuery('.album_photo', this.element)
			.click(
				function()
				{
					sel._nextPhoto();
				}
			);
		
		// bind fade effect and click behaviour to thumbnails
		jQuery('.album_thumb', this.element)
			.hover(
				function()
				{
					jQuery(this).fadeTo('fast', 1);
					/*if (this.options.editable)
					{
						this._editPanel('show');
					}*/
				},
				function()
				{
					jQuery(this).fadeTo('fast', .5);
					/*this._editPanel('hide');*/
				}
			)
			.click( 
				function()
				{
					sel._slideShow('stop');
					sel._setData('currentPhoto', this.i);
				}
			);
			
		// append editPanel to thumbnails
		jQuery('.album_thumb', sel.element)
			.each(
				function()
				{
					if (sel.options.editable)
					{
						sel._editPanel('show');
					}
				}
			);

		// bind "scroll" action to 'album_back' button
		jQuery('.album_back', this.element)
			.hover(
				function()
				{
					sel._moveBack();
				},
				function()
				{
					sel._moveBack('stop');
				}
			)
			.click(
				function()
				{
					sel._moveBack('page');
				}
			);

		// bind "start/stop" action to 'album_slideshow' button
		jQuery('.album_slideshow', this.element)
			.click(
				function()
				{
					sel._slideShow('toggle');
				}
			);

		// bind "scroll" action to 'album_next' button
		jQuery('.album_next', this.element)
			.hover(
				function()
				{
					sel._moveNext();
				},
				function()
				{
					sel._moveNext('stop');
				}
			)
			.click(
				function()
				{	
					sel._moveNext('page');
				}
			);			

		this._albumHolder_el = document.createElement('DIV');
		this._albumHolder_el.className = 'album_holder';
		
		jQuery('.album_thumbs', this.element)
			.css('width', this.options.thumbsWindowWidth)
			.append(this._albumHolder_el);

		// append editPanel to thumbnails
		jQuery('.album_thumb', sel.element)
			.each(
				function()
				{
					if (sel.options.editable)
					{
						sel._editPanel('show');
					}
				}
			);
			
		if (this.options.editable)
		{
			// preload image
			jQuery('<img>', document).attr('src', '/img/star_on.gif');
			jQuery('<img>', document).attr('src', '/img/star_off.gif');
			jQuery('<img>', document).attr('src', '/img/trash.gif');
		}
		// перерисовать, чтобы отреагировать на defaults.
		this._refresh();
	},
	
	_intervalId: null, // for window.setInterval in _slideShow
	
	_slideShow: function(option)
	{
		var sel = this;
		
		switch (option)
		{
			case 'toggle':
				if (this.options.runSlideShow)
				{
					this._slideShow('stop');
				}
				else
				{
					this._slideShow('start');
				}
				break;
			case 'start':
				if (!this._intervalId && this._photoCount > 0)
				{
					this.options.runSlideShow = true;
					//jQuery('.album_slideshow', this.element).get(0).style.backgroundImage = "url('/img/stop.png')";
					var el = jQuery('.album_slideshow', this.element).get(0);
					el.src = "/img/stop.png";
					el.title = "Остановить слайд-шоу";
					el.alt = "Остановить слайд-шоу";
					this._nextPhoto();
					//this._intervalId = window.setInterval(function(){sel._nextPhoto()}, sel.options.slideShowDelay);
				}
				break;
			case 'stop':
				if (this._intervalId)
				{
					window.clearTimeout(this._intervalId);
					this._intervalId = null;
					var el = jQuery('.album_slideshow', this.element).get(0);
					el.src = "/img/start.png";
					el.title = "Запустить слайд-шоу";
					el.alt = "Запустить слайд-шоу";
					//jQuery('.album_slideshow', this.element).get(0).style.backgroundImage = "url('/img/start.png')";
					this.options.runSlideShow = false;
				}
				break;
		}
	},


	_nextPhoto: function()
	{
		var n = this.options.currentPhoto;
		
		n++;
		
		if (n >= this._photoCount)
		{
			n = 0;
		}
		
		if (this._photoCount == 0)
		{
			n = -1;
		}
		
		this._setData('currentPhoto', n);
	},
	
	_moveBack: function(option)
	{
		var sel = this;
		switch (option)
		{
			case 'stop' :
				jQuery('.album_holder', this.element).stop();
				break;
			case 'page' :
				var m = this._canMoveBack(this.options.thumbsWindowWidth);
				if (m > 0)
				{
					jQuery('.album_holder', this.element)
						.stop()
						.animate(
							{left: '+=' + m + 'px'},
							'normal',
							function()
							{
								sel._checkNeedPage();
							}
						);
				}
				break;
			default :
				//var sel = this;
				var m = this._canMoveBack(100);
				if (m > 0)
				{
					
					
					jQuery('.album_holder', this.element)
						.animate(
							{left: '+=' + m + 'px'},
							700,
							function()
							{
								sel._checkNeedPage();
								sel._moveBack(option);
							}
						);
					
				}
				break;
		}
	},
	
	_moveNext: function(option)
	{
		var sel = this;
		switch (option)
		{
			case 'stop' :
				jQuery('.album_holder', this.element).stop();
				break;
			case 'page' :
				var m = this._canMoveNext(this.options.thumbsWindowWidth);
				if (m > 0)
				{
					jQuery('.album_holder', this.element)
						.stop()
						.animate(
							{left: '-=' + m + 'px'},
							'normal',
							function()
							{
								sel._checkNeedPage();
							}
						);
				}
				break;
			default :
				var m = this._canMoveNext(100);
				if (m > 0)
				{
					jQuery('.album_holder', this.element)
						.animate(
							{left: '-=' + m + 'px'},
							700,
							function()
							{
								sel._checkNeedPage();
								sel._moveNext(option);
							}
						);
				}
				break;
		}
	},

	// scroll into view thumbnail with specified photoNumber and load buffer page if necessary
	_moveTo: function(photoNumber)
	{
		var sel = this;
		var jel = jQuery('.album_holder', this.element);
		
		var photoCenterPx = photoNumber * this.options.thumbWidth + this.options.thumbWidth / 2;
		var winCenterPx = -jel.position().left + this.options.thumbsWindowWidth / 2;
		
		var delta = winCenterPx - photoCenterPx;
		
		if (delta > 0)
		{
			delta = this._canMoveBack(delta);
		}
		else
		{
			delta = (-1) * this._canMoveNext((-1) * delta);
		}
		
		
		jel.animate(
			{left: '+=' + delta + 'px'},
			'normal',
			function()
			{
				sel._checkNeedPage();
			}
		);
	},
	
	// checks if unloaded buffer page scrolls into view, and loads it.
	_checkNeedPage: function()
	{
		var jel = jQuery('.album_holder', this.element);
		
		var pn = this._getPageNumberByPx(this.options.thumbsWindowWidth - jel.position().left);
		
		if (this._pageNumbers.indexOf(pn) == -1)
		{
			this._loadPage(pn);
		}
		
		pn = this._getPageNumberByPx(-jel.position().left);
		
		if (this._pageNumbers.indexOf(pn) == -1)
		{
			this._loadPage(pn);
		}
	},

	_canMoveBack: function(px)
	{
		var jel = jQuery('.album_holder', this.element);
		
		var tail = -jel.position().left;

		if (tail > 0)
		{
			return (tail < px) ? tail : px;
		}
		else
		{
			return 0;
		}
	},
	
	_canMoveNext: function(px)
	{
		var jel = jQuery('.album_holder', this.element);
		
		var tail = jel.width() + jel.position().left - this.options.thumbsWindowWidth;

		if (tail > 0)
		{
			return (tail < px) ? tail : px;
		}
		else
		{
			return 0;
		}
	},
	
	// not only clears buffer but clear thumbnails and large image
	_clearBuffer: function()
	{
		for (b in this._buffer)
		{
			this._removePage(this._buffer, b);
		}
		
		this._buffer = {};
	},
	
	// get photo-count from service and reload photos and move to currentPhoto.
	_refresh: function()
	{
		this._refreshEditable();
		
		this._getPhotoCount();
	},
	
	// get photo-count from service and reload photos and move to currentPhoto.
	_getPhotoCount: function()
	{
		var sel = this;
		
		jQuery.get(
			"g_count.php", 
			{tid: this.options.topic_id}, 
			function(data)
			{
				sel._photoCount = data;
				sel._refreshPhotoCount();
			}
		);		
	},
	
	_refreshEditable: function()
	{
		// сюда спрятать создание и показ-прятание кнопки gallery_add_btn и диалога gallery_add_dialog
		
		if (this.options.editable  && !this._addDialog && this.options.topic_id != 'fav')
		{			
			// Add dialog
			this._addDialog = jQuery("<div><input id='file' type='file' name='file'></div>");
			this._addDialog.insertAfter(this.element);
			this._addDialog.dialog(
			{
				autoOpen: false,
				modal: true,
				width: 600,
				title:'',
				buttons: 
				{
					"Отмена": function() 
					{
						jQuery(this).dialog("close");
						
					},
					"Ок": function() 
					{
						jQuery(this).dialog("close");
					}
				}
			});
			
			// Add fileuploader
			if (jQuery.in3s.fileUploader)
			{
				var sel = this;
				jQuery('#file', this._addDialog.element)
					.fileUploader({
						topic_id: this.options.topic_id,
						afterFileUpload: function(e, data)
						{
							if (data.statusCode == '0')
							{
								sel._refresh();
							}
						}
					});
			}
			
		}
		if (!this.options.editable  && this._addDialog)
		{
			//this._addDialog.remove();
		}
		
		if (this.options.editable && !this._addButton && this.options.topic_id != 'fav')
		{
			this._addButton = jQuery("<div class='gallery_add_btn'></div>");
			this._addButton.appendTo(jQuery('#album_add', this.element));
			var sel = this;
			this._addButton.click(function()
			{
				sel._addDialog.dialog('open');
				return false;
			});
		}
		if (!this.options.editable && this._addButton)
		{
			//this._addButton.remove();
		}
	},
	
	_refreshCurrentPhoto: function()
	{
		// get page number with current photo.
		var pn = this._getPageNumber(this.options.currentPhoto);
		
		// if page not in buffer, load page, and redraw gallery components.
		// else just redraw gallery components.
		if (this._pageNumbers.indexOf(pn) == -1)
		{
			this._loadPage(pn);
		}
		else
		{
			this._drawCurrentPhoto();
		}
	},
	
	// redraw gallery control according with new currentPhoto value. 
	// Refresh counter and large photo.
	// Do not load buffer. Do not scroll into view.
	_drawCurrentPhoto: function()
	{
		// update photo counter
		this._drawPhotoCount();
		
		this._moveTo(this.options.currentPhoto);

		var photo = this._getBufferPhotoByOrder(this.options.currentPhoto);
		
		if (photo)
		{
			// update large photo.
			this._setAlbumPhoto(photo.id);
		
			// remove active style from all thumbnails;
			jQuery('.album_thumb_active', this.element)
				.removeClass('album_thumb_active');
				
			// set active className to thumbnail;
			jQuery(photo.el)
				.addClass('album_thumb_active');
		}
		else
		{
			// clear large photo.
			this._setAlbumPhoto(null);			
		}
	},

	// redraw photo count.
	_drawPhotoCount: function()
	{
		if (this._photoCount > 0)
		{
			// update photo counter
			jQuery('.album_counter', this.element)
				.html((this.options.currentPhoto + 1) + '&nbsp;из&nbsp;' + this._photoCount);
		}
		else
		{
			// update photo counter
			jQuery('.album_counter', this.element)
				.html('В&nbsp;этом&nbsp;альбоме&nbsp;пока&nbsp;нет&nbsp;фотографий.');			
		}
	},

	// refresh gallery when photo count has changed.
	// move to currentPhoto.
	_refreshPhotoCount: function()
	{
		this._clearBuffer();

		// update thumbnails_holder
		this._albumHolder_el.style.width = (this._photoCount * this.options.thumbWidth) + 'px';
		
		// adjust the currentPhoto value to fit into photoCount.
		var cp = this.options.currentPhoto;
		if (cp >= this._photoCount)
		{
			cp = this._photoCount - 1;
		}
		if (cp < 0 && this._photoCount > 0)
		{
			cp = 0;
		}
		
		this.options.currentPhoto = cp;
		this._refreshCurrentPhoto();
		
		// redraw some gallery control parts.
		this._drawPhotoCount();
		
		// refresh slide-show
		if (this.options.runSlideShow)
		{
			if (this._photoCount > 0)
			{
				this._slideShow('start');
			}
			else
			{
				this._slideShow('stop');
			}
		}
	},

	_setData: function(key, value)
	{
		switch(key)
		{
			case 'runSlideShow' :
				if (this.options.runSlideShow != value)
				{
					this.options.runSlideShow = value;
					this._slideShow(this.options.runSlideShow ? 'start' : 'stop');
				}
				break;
				
			case 'editable' :
				if (this.options.editable != value)
				{
					this.options.editable = value;
					this._refreshEditable();
				}
				break;

			case 'currentPhoto' :
				if (this.options.currentPhoto != value)
				{
					this.options.currentPhoto = value;
					this._refreshCurrentPhoto();
				}
				break;
		}

		jQuery.widget.prototype._setData.apply(this, arguments);
	},

	_getBufferPhotoByOrder: function(order)
	{
		for (var b in this._buffer)
		{
			for (var i in this._buffer[b])
			{
				if (this._buffer[b][i].i == order)
				{
					return this._buffer[b][i];
				}
			}
		}
		
		return null;
	},
	

	_loadPage: function(pn)
	{
		var needLoad = [];	// page numbers.
		var noRefresh = [];	// buffer positions.

		// remember to load page.
		needLoad[0] = pn;
		
		// remember to load next page, if we need to. Or set it to norefresh status.
		var i = this._pageNumbers.indexOf(pn + 1);
		if (i == -1)
		{
			needLoad.push(pn + 1);
		}
		else
		{
			noRefresh.push(i);
		}
		
		// remember to load previous page, if we need to. Or set it to norefresh status.
		i = this._pageNumbers.indexOf(pn - 1);
		if (i == -1)
		{
			needLoad.push(pn - 1);
		}
		else
		{
			noRefresh.push(i);
		}
		
		// load all necessary pages.
		for (var i = 0, len = this._pageNumbers.length; i < len; i++)
		{
			
			if(noRefresh.indexOf(i * 1) == -1)
			{
				this._removePage(this._buffer, i);
				
				pageNumber = needLoad.pop();
				
				this._pageNumbers[i] = pageNumber;
				
				this._loadPageInBuffer(i, pageNumber);
			}
		}	
	},
	
	
	_getPageNumber: function(photoNumber)
	{
		return Math.floor(photoNumber / this.options.photosOnPage);
	},
	
	_getPageNumberByPx: function(px)
	{
		var r = Math.floor(px / (this.options.photosOnPage * this.options.thumbWidth));
		return (r > 0) ? r : 0;
	},

	
	_removePage: function(buffer, bufferIndex)
	{
		var page = buffer[bufferIndex];
		
		if (page)
		{
			for (p in page)
			{
				if (page[p].el && page[p].el.parentNode)
				{
					page[p].el.parentNode.removeChild(page[p].el);
				}
			}
			
			page = null;
			this._pageNumbers[bufferIndex] = null;
		}
	},
	
	
	// loads page into buffer and draws it onto scrollwindow.
	_loadPageInBuffer: function(bufferIndex, pageNumber)
	{
		if (pageNumber >= 0)
		{
			var sel = this;
			jQuery.get(
				"g_page.php", 
				{tid: this.options.topic_id, 
				start: (pageNumber * this.options.photosOnPage), 
				count: this.options.photosOnPage},
				function(data){
					sel._buffer[bufferIndex] = eval(data);
					sel._drawPage(bufferIndex);
				}
			);
		}
	},


	_drawPage: function(bufferIndex)
	{
		var sel = this;
		
		var page = this._buffer[bufferIndex];
		
		for (var p in page)
		{
			if (typeof page[p] != 'function')
			{
				var thumb = document.createElement('DIV');
				thumb.className = 'album_thumb';
				thumb.innerHTML = '<table><tr><td><img src="g_image.php?id=' + page[p].id + '_s"></td></tr></table>';
				thumb.style.position = 'absolute';
				thumb.style.left = (page[p].i * this.options.thumbWidth) + 'px';
				thumb.url = page[p].id;
				thumb.i = page[p].i;
				thumb.fav = (page[p].fav != '');

				// bind fade effect to thumbnails
				jQuery(thumb)
					.hover(
						function()
						{
							jQuery(this).fadeTo('normal', 1);
							/*if (sel.options.editable)
							{
								sel._editPanel(this, 'show');
							}*/
						},
						function()
						{
							jQuery(this).fadeTo('normal', .5);
							/*sel._editPanel(this, 'hide');*/
						}
					)
					.click( 
						function()
						{
							sel._slideShow('stop');
							sel._setData('currentPhoto', this.i);
							//sel._moveTo(sel.options.currentPhoto);
						}
					);

				page[p].el = thumb;
				
				this._albumHolder_el.appendChild(thumb);
				
				// append editPanel to thumbnails
				jQuery(thumb)
					.each(
						function()
						{
							if (sel.options.editable)
							{
								sel._editPanel(this, 'show');
							}
						}
					);			


				if (page[p].i == this.options.currentPhoto)
				{
					this._drawCurrentPhoto();
					//this._moveTo(this.options.currentPhoto);
				}
			}
		}
	}
});

jQuery.extend(jQuery.in3s.galleryViewer, {
	defaults: {
		topic_id: '',
		currentPhoto: 0,
		photosOnPage: 7,		// count of photos on virtual page.
		thumbWidth: 110,
		thumbsWindowWidth: 600,		// width in pixels of thumbnails scroller window.
		slideShowDelay: 6000,
		runSlideShow: false,
		editable: false			// set true to turn album in to edit mode.
	}
});
