﻿(function ($, window) {
	function fitcherData(data, curSection) {
		this.curSection = curSection || 0;
		if (!(data instanceof Object)) {
			throw new Error('Неверный формат входных данных');
		}
		this.Sections = [];
		for (var sectNo = 0, sectCnt = data.length; sectNo < sectCnt; sectNo++) {
			this.Sections[sectNo] = {Previews : data[sectNo]};
		}
		this.preloadSection(this.curSection);
	}
	
	fitcherData.prototype = {
		preloadSection : function (sectNo) {
			if (this.Sections[sectNo].isLoaded) {
				return true;
			}
			var oFData = this;
			this.Sections[sectNo].loadedCnt = this.Sections[sectNo].Previews.length;
			for (var prevNo = 0, prevCnt = this.Sections[sectNo].Previews.length; prevNo < prevCnt; prevNo++) {
				var Preview = this.Sections[sectNo].Previews[prevNo];
				if (Preview.imgLoaded) {
					continue;
				}
				Preview.Image = new Image();
				Preview.Image.src = Preview.imgSrc;
				if (Preview.Image.complete) {
					this.imageLoaded(sectNo, Preview);
				} else {
					(function () {
						Preview.Image.onload = function () {
							oFData.imageLoaded(sectNo, Preview);
						};
					})();
				}
			}
		},
		addLoadHandler : function (sectNo, handler) {
			var oFData = this;
			if (this.Sections[sectNo].isLoaded) {
				handler.call(this);
			} else {
				this.Sections[sectNo].onload = function () {
					handler.call(oFData);
				};
			}
		},
		removeLoadHandler : function (sectNo) {
			this.Sections[sectNo].onload = null;
		},
		imageLoaded : function (sectNo, Preview) {
			var oFData = this;
			Preview.imgLoaded = true;
			oFData.Sections[sectNo].loadedCnt--;
			if (!oFData.Sections[sectNo].loadedCnt) {
				oFData.Sections[sectNo].isLoaded = true;
				if (typeof oFData.Sections[sectNo].onload == 'function') {
					oFData.Sections[sectNo].onload.call(this);
				}
			}
		}
	};
	
	function Fitcher(jParent, data, options) {
		var oFitcher = this;
		this.optValues = $.extend(true, {}, this.defOptions, options);
		if (!(data instanceof fitcherData)) {
			try { 
				data = new fitcherData(data, this.optValues.curSection); 
			} catch (ex) { 
				return false; 
			}
		}
		this.Data = data;
		if (typeof jParent == 'string') {
			$(function () {
				try { 
					jParent = $(jParent);
				} catch (ex) {
					return false;
				}
				oFitcher.initElements(jParent);
			});
		} else {
			this.initElements(jParent);
		}
	}
	
	Fitcher.prototype = {
		defOptions : {
			cssSelectors : {
				//Sections : 'div.menu_but_grey ul li',
				Main : {
					View : 'li.item',
					PrevCont : 'section.js_prev_container',
					Previews : 'section.js_prev_container > div a',
					Sections : 'div.menu_but_grey li a',
					FullView : 'ul.block_recom'
				},
				viewData : {
					ViewImg : 'a.img',
					ViewRate : 'div.rat i.rating',
					ViewName : 'div.name a',
					ViewDescr : 'div.descr',
					ViewLinks : 'div.foot a'
				},
				addElems: {
					Preview: {},
					View: {}
				}
			},
			cssClasses : {
				actSection : 'on',
				actPreview : 'on',
				rateScore : ['rating_sm_1', 'rating_sm_1_5', 'rating_sm_2', 'rating_sm_2_5', 'rating_sm_3', 'rating_sm_3_5', 'rating_sm_4', 'rating_sm_4_5', 'rating_sm_5', 'rating_sm_5']
			},
			curSection : 0,
			Timeout : 5000,
			fadeTimeout : 300
		},
		initElements : function (jParent) {
			var oFitcher = this, sectNo = 0, oOldItSlider, cssSelecotrs = this.optValues.cssSelectors;
			if (!(jParent instanceof $)) {
				return false;
			}
			this.jParent = jParent;
			oOldItSlider = this.jParent.data('itSliderObj');
			if (oOldItSlider) {
				return oOldItSlider;
			}
			for (var selName in cssSelecotrs.Main) {
				this['j' + selName] = this.jParent.find(cssSelecotrs.Main[selName]);
			}
			this.jSections.filter(':gt(' + (this.Data.Sections.length - 1) + ')').parent().hide();
			for (var selName in cssSelecotrs.viewData) {
				this['j' + selName] = this.jView.find(cssSelecotrs.viewData[selName]);
			}
			this.addElems = {};
			for (var parentName in cssSelecotrs.addElems) {
				if (cssSelecotrs.addElems.hasOwnProperty(parentName) && this['j' + parentName] instanceof $) {
					if (!this.addElems[parentName]) {
						this.addElems[parentName] = {}
					}
					for (var selName in cssSelecotrs.addElems[parentName]) {
						if (cssSelecotrs.addElems[parentName].hasOwnProperty(selName)) {
							var elName = 'j' + selName.substr(0,1).toUpperCase() + selName.substr(1);
							this.addElems[parentName][elName] = this['j' + parentName].find(cssSelecotrs.addElems[parentName][selName])
						}
					}
				}
			}
			this.jSections.each(function (prevNo) {
				var jLink = $(this);
				jLink.bind('click.Fitcher', function () {
					oFitcher.Data.preloadSection(prevNo);
					oFitcher.Data.addLoadHandler(prevNo, function () {
						oFitcher.fadeSection(prevNo);
						oFitcher.jSections.parent().removeClass(oFitcher.optValues.cssClasses.actSection)
												   .eq(prevNo).addClass(oFitcher.optValues.cssClasses.actSection);
					});
					return false;
				});
			});
			this.jView.bind('mouseover.Fitcher', function () {
				oFitcher.updateOver(true);
				oFitcher.updateTimeout(true);
			}).bind('mouseout.Fitcher', function () {
				oFitcher.updateOver();
			});
			this.jPreviews.parent().each(function (prevNo) {
				var jPrev = $(this);
				jPrev.bind('mouseover.Fitcher', function () {
					oFitcher.updateOver(true);
					oFitcher.fadeView(prevNo);
					oFitcher.updateTimeout(true);
				}).bind('mouseout.Fitcher', function () {
					oFitcher.updateOver();
				});
			});
			this.Data.addLoadHandler((sectNo = this.curSection = this.optValues.curSection), function () {
				oFitcher.drawSection(sectNo, false);
				oFitcher.Data.removeLoadHandler(sectNo);
			});
		},
		drawSection : function (sectNo, fade) {
			var oSection = this.Data.Sections[sectNo], oFitcher = this;
			this.curSection = sectNo;
			this.updateTimeout();
			if (typeof fade == 'undefined') {
				fade = true;
			}
			this.jPreviews.each(function (index) {
				var jPreview = $(this), Preview = oSection.Previews[index];
				jPreview.text(Preview.Name).attr('href', Preview.Url);
				oFitcher.drawAddElems(oFitcher.addElems.Preview, Preview.addData);
			});
			if (!fade) {
				this.drawView(0);
			}
		},
		fadeSection : function (sectNo) {
			var oFitcher = this;
			this.jFullView.fadeOut(this.optValues.fadeTimeout, function () {
				oFitcher.drawSection(sectNo);
				oFitcher.drawView(0);
				oFitcher.jFullView.fadeIn(oFitcher.optValues.fadeTimeout);
			});
		},
		drawAddElems: function (oElems, oData) {
			if (typeof oElems == 'object') {
				for (var elName in this.addElems.Preview) {
					if (oElems.hasOwnProperty(elName)) {
						var jElem = oElems[elName];
						if (jElem instanceof $ && jElem.length) {
							if (typeof oData[elName] == 'object') {
								for (var paramName in oData[elName]) {
									if (oData[elName].hasOwnProperty(paramName)) {
										switch (paramName) {
										case 'href':
										case 'title':
										case 'src':
											jElem.attr(paramName, oData[elName][paramName]);
											break;
										case 'name':
											jElem.text(paramName, oData[elName][paramName]);
											break;
										}
									}
								}
							} else {
								jElem.hide();
							}
						}
					}
				}
			}
		},
		drawView : function (prevNo) {
			var Preview = this.Data.Sections[this.curSection].Previews[prevNo], rateKey = Math.floor(Preview.Rate * 2) - 2;
			this.jViewImg.css('background-image', 'url(' + Preview.Image.src + ')').attr('href', Preview.Url);
			this.jViewRate.removeClass(this.optValues.cssClasses.rateScore.join(' '))
						  .addClass(this.optValues.cssClasses.rateScore[rateKey])
						  .attr('title', 'Рейтинг '+ Preview.Rate + ' из 5');
			this.jViewName.text(Preview.Name).attr('href', Preview.Url);
			this.jViewDescr.text(Preview.Desc);
			this.jViewLinks.each(function (index) {
				var jLink = $(this), oLink = Preview.Links[jLink.is('.rec') ? 'review' : 'trailer']; //TODO сделать что-то более универсальное для ссылок
				if (oLink && typeof oLink == 'object') {
					jLink.attr({
						'href': oLink.url,
						'title': oLink.title
					}).show();
				} else {
					jLink.hide();
				}
			});
			this.drawAddElems(this.addElems.Preview, Preview.addData);
			this.jPrevCont.find('> div').removeClass(this.optValues.cssClasses.actPreview)
										.eq(prevNo).addClass(this.optValues.cssClasses.actPreview);
			this.curPrev = prevNo;
		},
		fadeView : function (prevNo, callback) {
			if (prevNo == this.curPrev) {
				return false;
			} 
			callback = callback || false;
			var oFitcher = this;
			this.jView.fadeOut(this.optValues.fadeTimeout, function () {
				oFitcher.drawView(prevNo);
				oFitcher.jView.fadeIn(oFitcher.optValues.fadeTimeout);
				if (typeof callback == 'function') {
					callback();
				}
			});
		},
		nextPrev : function (fade) {
			if (typeof fade == 'undefined') {
				fade = true;
			}
			var prevNo = this.curPrev + 1;
			if (prevNo == this.jPreviews.length) {
				prevNo = 0;
			}
			if (fade) {
				this.fadeView(prevNo);
			} else {
				this.drawView(prevNo);
			}
		},
		updateTimeout : function (reset) {
			var oFitcher = this;
			if (this.prevInterval) { 
				clearInterval(this.prevInterval);
				this.prevInterval = false;
			}
			if (!reset) {
				this.prevInterval = setInterval(function () {
					oFitcher.nextPrev();
				}, this.optValues.Timeout);
			}
		},
		updateOver : function (reset) {
			var oFitcher = this;
			if (this.overTimeout) {
				clearTimeout(this.overTimeout);
				this.overTimeout = false;
			}
			if (!reset) {
				this.overTimeout = setTimeout(function () {
					oFitcher.updateTimeout();
				}, 100);
			}
		}
	};
	
	window.fitcherData = fitcherData;
	window.Fitcher = Fitcher;
	
	$.fn.goFitcher = function(data, options){
		new Fitcher($(this), data, options);
	}
})(jQuery, self);
