/**
 * lightgallery.js v1.0
 * Author: Dmitri Ischenko - ischenkodv@gmail.com
 * Freely distributable under MIT-style license.
 */
var lightgallery = (function(){
var LG = {
	isOpen		: false,	// if library open?
	images		: [],		// list of images
	container	: null,		// container which holds image
	picture		: null,		// image
	current		: null,		// index of the current image showing
	loaderImage	: null,		// image loader
	minPadding	: 20,		// minimal distance between container and window

	/**
	 * Initialize gallery
	 */
	init : function(){

		var b=document.getElementsByTagName('body')[0];

		// create overlay and container
		b.appendChild( this.overlay = ce('div',{id:'LG_overlay'}) );
		b.appendChild( this.container = this.createContainer() );

		// create <img> element to load images
		this.loaderImage = ce('img',{src:''});
		this.loaderImage.onload=function(){
			var l = LG;
			l.hideLoadingIcon();
			l.loaderImage.__is_loaded__=true;
			l.picture.setAttribute("src", l.loaderImage.src);
			l.setContPos(true, false);
			l.preload(l.current);
		}

		// define the difference between container and image size
		this.dy = this.container.offsetHeight;
		this.dx = parseInt(this.container.getAttribute('cellspacing')*3);
	},

	/**
	 * Add link to list of working gallery links (add event and add photos associated with link
	 */
  addLink:function (link) {
    addEvent(link,'click', this.showImage);
    link.__gallery__ = link.id;
		link.__index__ = 0;
  },
  
	/**
	 * Open gallery
	 */
	open : function(){
		// set overlay size
		var s = this.overlay.style;
		var ar = getPageSize();
		this.overlayWidth = ar[0];
		this.overlayHeight = ar[1];
		s.width = ar[0] + "px";
		s.height = ar[1] + "px";
		s.display = 'block';
		// display container
		this.picture.style.display='block';
		this.setContPos();
		this.container.style.visibility = 'visible';
		this.container.style.display = 'block';
		this.isOpen = true;
	},

	/**
	 * Close gallery
	 */
	close : function(){
		LG.overlay.style.display = 'none';
		LG.container.style.visibility = 'hidden';
		LG.container.style.display = 'none';
		LG.isOpen = false;
		LG.loaderImage.src=LG.picture.src='';
	},

	createContainer : function(){
		this.picture = ce('img', {id:'LG_pic',width:300,height:300});
		this.prevBtn = ce('td', 0, ce('div', {'class':'LG_prevLink',title:'Предыдущая',
							events:{
								click:LG.prev,
								mouseover:function(){this.className='LG_prevLinkOver'},
								mouseout:function(){this.className='LG_prevLink'}
							}
						})
					);
		this.nextBtn = ce('td', 0, ce('div',{'class':'LG_nextLink',title:'Следующая',
							events:{
								click:LG.next,
								mouseover:function(){this.className='LG_nextLinkOver'},
								mouseout:function(){this.className='LG_nextLink'}
							}
						})
					);
		this.titleBar = ce('td', {'class':'LG_titleBar'});
		this.imgIndex = ce('div', {'class':'LG_imgIndex'});
		this.panel = ce('table', {id:'LG_panel',width:'100%'},
						ce('tbody',0,
							ce('tr',0,
								this.prevBtn,
								this.titleBar,
								this.nextBtn
							)
						)
					);
		var cont = ce('table', {id:'LG_container',cellpadding:0,cellspacing:2,
						events:{
							dblclick:LG.close
						}
					},
                    ce('tbody',0,
                        ce('tr',0,
                        	ce('td',{style:'width:300px'},
								
								this.imgIndex,
								ce('div',{
									'class':'LG_closeBtn',title:'Закрыть',
									events:{
										'click':this.close,
										mouseover:function(){this.className='LG_closeBtnOver'},
										mouseout:function(){this.className='LG_closeBtn'}
									}
								})
							)
						),
						ce('tr',0,
							ce('td',0,this.picture)
						),
						ce('tr',0,
							ce('td',0,this.panel)
						)
					)
				);
		return cont;
	},

	zoomIn : function(){
		LG.Zoom(1.1);
	},

	zoomOut : function(){
		LG.Zoom(.9);
	},

	zoomNormal : function(){
		var l=LG,p=l.picture,i=l.loaderImage;
		if(p.width == i.width && p.height == i.height)
			return;
		l.Zoom(1);
	},

	Zoom : function(coef){
		var l=LG,p=l.picture,i=l.loaderImage;
		l.hideContent();
		l.setContPos(true, coef);
	},

	/**
	 * Set the size and position of the container
	 * @param {Boolean} isSlow - animated resizing
	 * @param {Number} vScale - scale of the image: 1 - full size, >1 - zoom in, <1 - zoom out
	 */
	setContPos : function(isSlow, vScale){
		var i = this.loaderImage, p = this.picture, s = this.container.style, overlayStyle = this.overlay.style, overlayWidth = this.overlayWidth, overlayHeight = this.overlayHeight,
		iWidth = i.width,iHeight = i.height,pWidth,pHeight,w,h,dx = this.dx, dy = this.dy, padding = this.minPadding;

		// width and height of the viewport
		var ar = getPageSize();
		var wScr = ar[2];
		var hScr = ar[3];

		// define width and height of the container
		if(i.__is_loaded__ && !vScale){
			// container to the size of the viewport
			var dim_pic = iWidth/iHeight;
			var dim_scr = wScr/hScr;
			if(wScr > (iWidth+dx+padding) && hScr > (iHeight+dy+padding)){
				pWidth = p.width = iWidth;
				pHeight = p.height = iHeight;
			} else {
				if(dim_scr > dim_pic){
					pHeight = p.height = (hScr - dy - padding);
					pWidth = p.width = Math.floor(pHeight*dim_pic);
				}else{
					pWidth = p.width = (wScr - dx - padding);
					pHeight = p.height = Math.floor(pWidth * dim_pic);
				}
			}
			w = pWidth+dx;
			h = pHeight+dy;
		}else if(vScale==1){
			// full size
			w = i.width + dx;
			h = i.height + dy;
			p.width = i.width;
			p.height = i.height;
		}else if(vScale < 1 || vScale > 1){
			// zoom
			pWidth = p.width = Math.floor(p.width * vScale);
			pHeight = p.height = Math.floor(p.height * vScale);
			w = pWidth + dx;
			h = pHeight + dy;
		}else
			w = h =300;	// default size

		// here we set the minimal width of the container to 300px
		w = Math.max(w,300);

		// if image more that current document we need to resize overlay
		overlayStyle.width = ((w > overlayWidth)? w + 10 : overlayWidth) + 'px';
		overlayStyle.height = ((h > overlayHeight)? h + 10 : overlayHeight) + 'px';

		// correct coords according to scroll bars position
		var scr = getScrollXY();
		var y = (hScr>h ? Math.floor(Math.abs((hScr - h)/2)) : 0) + scr[1];
		var x = (wScr>w ? Math.floor(Math.abs((wScr - w)/2)) : 0) + scr[0];

		if(isSlow){
			var anime = new Movie(this.container, 5, 1);
			anime.addThread('width', null, w);
			anime.addThread('height', null, h);
			anime.addThread('top', null, y);
			anime.addThread('left', null, x);
			anime.addAction(function(){
				LG.showContent(true);
				LG.loaderImage.__is_loaded__=false;
			},4);
			anime.run();
		}else{
			s.top = y+"px";
			s.left = x+"px";
			s.width = w+"px";
			s.height = h+"px";
			this.showContent(true);
			i.__is_loaded__=false;
		}
	},

	showImage : function(e){
		var i = this.__index__, e = e || window.event;
		if(e){
			if(e.preventDefault)
				e.preventDefault();
			else
				e.returnValue=false;
		}

		if(this.__gallery__ && i>-1){
			LG.gallery = this.__gallery__;
			LG.show(i);
		}else
			LG.showSingle(this);
	},

	preload : function(index){
		if(window.opera) return;

		var gallery = this.images[this.gallery];
		if(!gallery)
			return;
		(new Image).src = (gallery[index+1] !== undefined) ? gallery[index+1].href : '';
		(new Image).src = (gallery[index-1] !== undefined) ? gallery[index-1].href : '';
	},

	/**
	 * Show single image
	 */
	showSingle : function(elem){
		if(!this.isOpen)
			this.open();

		this.hideContent(true);
		this.showLoadingIcon();
		this.loaderImage.__is_loaded__=false;

		this.loaderImage.src=elem.href;
		this.titleBar.innerHTML = elem.title;
		this.imgIndex.innerHTML = '';
		this.prevBtn.style.visibility = 'hidden';
		this.nextBtn.style.visibility = 'hidden';
	},

	/**
	 * Show gallery
	 */
	show : function(index){
		if(!index && this.gallery === null)
			return;

		if(!this.isOpen)
			this.open();

    if ( (this.images[this.gallery].length < 1) )
		  this.images[this.gallery].push({href: 'assets/templates/boromlya/images/miscs/nophoto.gif'});
		  
		var gallery = this.images[this.gallery];
		  
		if(index < 0 || index > gallery.length-1)
			return;

		this.hideContent(true);
		this.showLoadingIcon();
		this.loaderImage.__is_loaded__=false;

		this.loaderImage.src=gallery[index].href;

		//this.titleBar.innerHTML = gallery[index].title;
		this.titleBar.innerHTML = ( gallery[index].content ) ? gallery[index].content : gallery.content;
		this.imgIndex.innerHTML = '\u0424\u043E\u0442\u043E '+(index+1)+' \u0438\u0437 '+gallery.length;

    this.prevBtn.style.visibility = 'visible';
		this.nextBtn.style.visibility = 'visible';
		if(index === 0)
			this.prevBtn.style.visibility = 'hidden';
		if(index === gallery.length-1)
			this.nextBtn.style.visibility = 'hidden';

		this.current = index;
	},

	showLoadingIcon:function(){
		this.container.className='LG_loading';
	},
	hideLoadingIcon:function(){
		this.container.className = '';
	},

	/**
	 * Hide container content
	 */
	hideContent:function(isSlow){
		this.container.firstChild.style.display='none';
		setOpacity(this.picture, 0);
	},

	/**
	 * Show container content
	 */
	showContent:function(isSlow){
		if(isSlow){
			var anime = new Movie(this.picture, 5, 10);
			anime.addThread('opacity', 0, 100);
			anime.addAction(function(){LG.container.firstChild.style.display='block';}, 0);
			anime.run();
		}else{
			this.container.firstChild.style.display='block';
			setOpacity(this.container.firstChild, 100);
		}
	},

	// show next image
	next : function(){
		LG.show(++LG.current);
	},

	// show previous image
	prev : function(){
		LG.show(--LG.current);
	}
}

/**
 * Add event listener
 */
var addEvent = (function(){
	if (window.addEventListener){
		return function(obj,type,fn){obj.addEventListener( type, fn, false )}
	} else if (window.attachEvent){
		return function(obj,type,fn){
				obj["e"+type+fn] = fn;
				obj[type+fn] = function() {obj["e"+type+fn]( window.event )}
				obj.attachEvent( "on"+type, obj[type+fn] );
		}
	}
})()

function getStyle(elem, name) {
	var d = document.defaultView;
	if (elem.style[name])
		return elem.style[name];

	else if (elem.currentStyle)
		return elem.currentStyle[name];

	else if (d && d.getComputedStyle) {
		name = name.replace(/([A-Z])/g,"-$1");
		name = name.toLowerCase();

		var s = d.getComputedStyle(elem,"");
		return s && s.getPropertyValue(name);
	}
	return null;
}

function setOpacity() {
	setOpacity = arguments[0].filters ?
		function(elem,level){elem.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity="+level+")"} :
		function(elem,level){elem.style.opacity = level / 100}
}

function ce(tag, attr){
	if(tag){
		var elem = document.createElement(tag);

		if (attr){
			for (var name in attr){
				switch(name){
					case 'events':
						for(var j in attr[name]){
							addEvent(elem, j, attr[name][j])
						}
						break;
					default:
						var value = attr[name];
						if ( typeof value != "undefined" ) {
							if(name == 'class' || name == 'for'){
								name = { "for": "htmlFor", "class": "className" }[name] || name;
								elem[name] = value;
							} else
								elem.setAttribute(name, value);
						}
				}
			}
		}

		if(arguments.length>2){
			for(var i=2, len=arguments.length; i<len; i++){
				switch(typeof arguments[i]){
					case 'string':	elem.innerHTML += arguments[i];
							break;
					case 'object':	elem.appendChild(arguments[i]);
				}
			}
		}
		return elem;
	}
	return null;
}

/**
 * Class which makes and run animations
 * @param {Element} elem - target element
 * @param {Number} num_frames - number of frames
 * @param {Number} speed - time between each frame, msec
 */
function Movie(elem, num_frames, speed){
	if (!elem)
		return null;

	this.elem = elem;
	this.numFrames = num_frames || 0;
	this.frames = [];		// frames array
	this.speed = speed || 10;
}

/**
 * Add thread - the chain of actions to do on the element
 * @param {String} style - style name
 * @param {Number} startValue - value at the beginning of animation
 * @param {Number} endValue - end value
 * @param {Number} startFrame - frame, from which the animation of thread begin
 * @param {Number} endFrame - frame, which ends the animation
 */
Movie.prototype = {
addThread : function(style, startValue, endValue, startFrame, endFrame){
	if (!style || endValue === 'undefined' || endValue === null) return;

	if(style == 'opacity'){
		if(startValue !== 0)
			startValue = 100*parseFloat(startValue || getStyle(this.elem, style));
	}else{
		startValue = parseFloat(getStyle(this.elem, style));
	}

	startFrame = startFrame || 0;
	endFrame = endFrame || this.numFrames;

	var elem = this.elem, F = this.frames;

	var count = (endFrame - startFrame) || 1;
	if (startValue > endValue){
		var step = Math.ceil((startValue - endValue) / count);
		for (var i=0; i<count; i++){
			startValue = ((startValue - endValue) <= step)? endValue : Math.ceil(startValue - step);
			if (!F[i])
				F[i] = new MovieFrame();
			F[i].addAction(this.createAction(elem, style, startValue));
		}
	}else{
		var step = Math.ceil((endValue - startValue) / count);
		for (var i=0; i<count; i++){
			startValue = ((endValue - startValue) <= step)? endValue : Math.ceil(startValue + step);
			if (!F[i])
				F[i] = new MovieFrame();
			F[i].addAction(this.createAction(elem, style, startValue));
		}
	}
},

/**
 * Creation of the anonimous function that changes the style
 * @param {Element} elem - target element
 * @param {String} name - style name
 * @param {Number} value - style value
 */
createAction : function(elem, name, value){
	return (name == 'opacity')? function(){setOpacity(elem, value)} : function(){elem.style[name] = value+'px'}
},

/**
 * Add action to the frame specified
 * @param {Function} func - reference to the function or anonimous function
 * @param {Number} frameNumber - number of frame to put the action in
 */
addAction : function(func, frameNumber){
	this.frames[frameNumber].addAction(func);
},

/**
 * The step - run the next frame
 */
step : function(){
	var frame = this.frames.shift();

	if (frame)
		frame.exec();
	else
		clearInterval(this.interval);
},

/**
 * Show the animation
 */
run : function(){
	clearInterval(this.interval);
	this.step();	// ????? ?? ????????? ?????? ????

	var t = this;
	if (this.numFrames>1) {	// ????????? ????? ?? ?????????????
		this.interval = setInterval(function(){t.step()}, this.speed);
	}
}
}

/**
 * Class "movie frame" contains list of actions to run
 */
function MovieFrame(){
	this.actions = [];
}

MovieFrame.prototype = {
	/**
	 * Add action to the frame
	 * @param {Function} f - anonimous function or reference to the function
	 */
	addAction : function(f){
		this.actions.push(f);
	},

	/**
	 * Executes all actions of the frame
	 */
	exec : function(){
		var a = this.actions;
		for (var i=a.length; --i>-1;)
			a[i]();
	}
}

return LG;
})();

/**
 * Get the page and viewport size
 * @return {Array} - ?????????? ?????? ?? ?????????? ?????? ? ?????? ????????
 *					? ?????? ? ?????? ??????? ????? ????????
 */
function getPageSize(){
	var xScroll, yScroll, windowWidth, windowHeight, b = document.body, de = document.documentElement;
	if (window.innerHeight && window.scrollMaxY) {
		xScroll = b.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (b.scrollHeight > b.offsetHeight){ // all but Explorer Mac
		xScroll = b.scrollWidth;
		yScroll = b.scrollHeight;
	} else if (de && de.scrollHeight > de.offsetHeight){ // Explorer 6 strict mode
		xScroll = de.scrollWidth;
		yScroll = de.scrollHeight;
	} else { // Explorer Mac...would also work in Mozilla and Safari
		xScroll = b.offsetWidth;
		yScroll = b.offsetHeight;
	}

	if (self.innerHeight) { // all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (de && de.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = de.clientWidth;
		windowHeight = de.clientHeight;
	} else if (b) { // other Explorers
		windowWidth = b.clientWidth;
		windowHeight = b.clientHeight;
	}

	// for small pages with total height less then height of the viewport
	var pageHeight = (yScroll < windowHeight)? windowHeight : yScroll;

	// for small pages with total width less then width of the viewport
	var pageWidth = (xScroll < windowWidth)? windowWidth : xScroll;

	return [pageWidth,pageHeight,windowWidth,windowHeight];
}

/**
 * Get coords of scroll bars
 * @return {Array} - {coord horizontal, coord vertical}
 */
function getScrollXY() {
	var scrOfX = 0, scrOfY = 0, b = document.body, de = document.documentElement;
	if( typeof( window.pageYOffset ) == 'number' ) {
		//Netscape compliant
		scrOfY = window.pageYOffset;
		scrOfX = window.pageXOffset;
	} else if( b && ( b.scrollLeft || b.scrollTop ) ) {
		//DOM compliant
		scrOfY = b.scrollTop;
		scrOfX = b.scrollLeft;
	} else if( de && ( de.scrollLeft || de.scrollTop ) ) {
		//IE6 Strict
		scrOfY = de.scrollTop;
		scrOfX = de.scrollLeft;
	}
	return [ scrOfX, scrOfY ];
}
