
var Promo = new Class({
	
	THUMB_WIDTH : 306,
	ZOOM_WIDTH  : 590,
	
	THUMB_IMAGE_PROP  : { width:288, height:174 },
	ZOOM_IMAGE_PROP   : { width:506, height:306 },
	IMAGE_PADDING     : 4,
	SHADOW_IMAGE_SIZE : 32,
	
	data : null,
	
	
	promo : null,
	wrap  : null,
	bg    : null,
	
	btn_prev : null,
	btn_next : null,
	jumpList : null,
	
	slides : null,
	
	windowWidth  : 0,
	wrapOffset   : 0,
	currentKey   : 0,
	sequenceKey  : 0,
	
	currentSlide    : null,
	motionDirection : "",
	isSequenceMode  : false,
	
	isAutoMode  : false,
	autoTimer   : null,
	isFirstView : false,
	
	
	
	// ----------------------------------------------------------------------------------------------------
	// Init
	
	initialize : function(_data) {
		this.data = _data;
		this.isFirstView = true;
		this.currentKey = _data.length - 1;
		
		this.promo = $("promo");
		this.wrap = new Element("div", { "id":"promo-wrap"});
		this.bg   = new Element("div", { "id":"promo-bg"});
		this.promo.adopt(this.wrap, this.bg);
		
		this.slides = new Array();
		this.maxWidth = this.ZOOM_WIDTH + this.THUMB_WIDTH * 4;
		
		this.initView();
		
		this.calcWindowSize();
		this.alignElements();
		this.setWindowListener();
		
		this.lockButtons();
		this.setAutoMode();
	},
	
	
	
	initView : function() {
		var self = this;
		
		this.createNav();
		this.createJumpList();
		
		var count = 0;
		var i, len;
		len = this.data.length;
		for(i=0; i<len; i++) {
			var prop = this.data[i];
			var slide = new this.Slide(i, prop, callback);
			
			slide.node.style.left = (i * this.THUMB_WIDTH) + "px";
			slide.shadow.style.width  = this.THUMB_IMAGE_PROP.width  - this.SHADOW_IMAGE_SIZE + "px";
			slide.shadow.style.height = this.THUMB_IMAGE_PROP.height - this.SHADOW_IMAGE_SIZE + "px";
			
			this.wrap.adopt(slide.node);
			this.slides.push(slide);
		}
		
		this.wrap.adopt(this.btn_prev, this.btn_next, this.jumpList);
		
		
		function callback() {
			count++;
			if(count === len) {
				self.switchSlide("next");
			}
		}
	},
	
	
	
	createJumpList : function() {
		var self = this;
		
		this.jumpList = new Element("ul");
		this.jumpList.id = "promo-jumplist";
		
		var i, len;
		len = this.data.length;
		for(i=0; i<len; i++) {
			var li = new Element("li");
			var a  = new Element("a");
			a.href = "#slide-" + (i+1);
			a.rel  = "key:" + i;
			a.onclick = function() {
				var key = Number( this.rel.replace(/key:(.+)/, "$1") );
				if(key === self.currentKey) {
					return false;
				}
				
				self.stopAutoPlay();
				self.jumpToSlide(key);
				return false;
			}
			
			li.adopt(a);
			this.jumpList.adopt(li);
		}
	},
	
	
	
	createNav : function() {
		var self = this;
		
		this.btn_prev = new Element("div");
		this.btn_prev.id = "promo-prev";
		
		this.btn_next = new Element("div");
		this.btn_next.id = "promo-next";
		
		var prevLink = new Element("a");
		var nextLink = new Element("a");
		
		prevLink.href = "javascript:void(0);";
		nextLink.href = "javascript:void(0);";

		prevLink.onclick = function() {
			self.stopAutoPlay();
			self.switchSlide("prev");
		}
		
		nextLink.onclick = function() {
			self.stopAutoPlay();
			self.switchSlide("next");
		}
		
		this.btn_prev.adopt(prevLink);
		this.btn_next.adopt(nextLink);
	},
	
	
	
	
	
	
	setAutoMode : function() {
		this.isAutoMode = true;
		//this.switchSlide("next");
		//this.startAutoPlay();
	},
	
	
	startAutoPlay : function() {
		var self = this;
		
		if(!this.isAutoMode) {
			return;
		}
		
		if(this.autoTimer) {
			clearTimeout(this.autoTimer);
		}
		
		
		this.autoTimer = setTimeout(function(){
			self.switchSlide("next");
		},
		4000);
	},
	
	
	stopAutoPlay : function() {
		this.isAutoMode = false;
		if(this.autoTimer) {
			clearTimeout(this.autoTimer);
		}
	},
	
	
	
	
	
	
	// ----------------------------------------------------------------------------------------------------

	setWindowListener : function() {
		var self = this;
		window.addEvent("resize", function(){
			self.calcWindowSize();
			self.alignElements();
		});
	},
	
	
	
	
	// ----------------------------------------------------------------------------------------------------

	switchSlide : function(mode) {
		if(this.isLockMotion) {
			return;
		}
		
		this.isLockMotion = true;
		
		var self = this;
		var len = this.slides.length;
		
		if(mode == "prev") {
			this.currentKey -= 1;
			if(this.currentKey < 0) {
				this.currentKey = len - 1;
			}
		}
		else if(mode == "next") {
			this.currentKey += 1;
			if(this.currentKey >= len) {
				this.currentKey = 0;
			}
		}
		
		this.motionDirection = mode;
		
		this.lockButtons();
		
		
		if(this.currentSlide) {
			this.zoomOutSlide(callback);
		}
		else {
			callback();
		}
		
		function callback() {
			self.moveSlides("motion");
		}
	},
	
	
	lockButtons : function() {
		var prev = this.btn_prev.getElementsByTagName("a")[0];
		var next = this.btn_next.getElementsByTagName("a")[0];
		
		$(prev).addClass("moving");
		$(next).addClass("moving");
		
		this.activateJumpButtons();
	},
	
	unlockButtons : function() {
		var prev = this.btn_prev.getElementsByTagName("a")[0];
		var next = this.btn_next.getElementsByTagName("a")[0];
		
		$(prev).removeClass("moving");
		$(next).removeClass("moving");
		
		this.activateJumpButtons();
	},
	
	
	activateJumpButtons : function() {
		var checkKey = (this.isSequenceMode) ? this.sequenceKey : this.currentKey;
		var btns = this.jumpList.getElementsByTagName("a");
		var len = btns.length;
		for(var i=0; i<len; i++) {
			var btn = btns[i];
			if(checkKey === i && !this.isFirstView) {
				btn.className = "active";
			}
			else {
				btn.className = "";
			}
		}
	},
	
	
	
	
	
	


	// ----------------------------------------------------------------------------------------------------

	zoomOutSlide : function(func) {
		var self = this;
		var slide = this.currentSlide;
		var img = slide.img;
		
		slide.swapThumb();
		
		slide.imgFx = new Fx.Morph(img, {duration: 200, transition: Fx.Transitions.Sine.easeOut, onComplete:callback });
		slide.imgFx.start({
			"width"  : this.THUMB_IMAGE_PROP.width,
			"height" : this.THUMB_IMAGE_PROP.height
		});
		
		slide.zoomFx = new Fx.Morph(slide.node, {duration: 200, transition: Fx.Transitions.Sine.easeOut });
		slide.zoomFx.start({
			"top"  : 75,
			"left" : slide.moveX
		});
		
		slide.shadowFx = new Fx.Morph(slide.shadow, {duration: 200, transition: Fx.Transitions.Sine.easeOut });
		slide.shadowFx.start({
			"width"  : this.THUMB_IMAGE_PROP.width - this.SHADOW_IMAGE_SIZE,
			"height" : this.THUMB_IMAGE_PROP.height - this.SHADOW_IMAGE_SIZE
		});
		
		function callback() {
			slide.node.style.zIndex = 1;
			func();
		}
	},
	
	
	
	
	
	
	zoomUpSlide : function(mode) {
		this.isSequenceMode = false;
		this.isFirstView = false;
		
		var self = this;
		var slide = this.slides[this.currentKey];
		slide.loadZoomImage(mode, this.data[this.currentKey], callback);
		
		function callback() {
			self.zoomUpMotion(mode);
		}
	},
	
	
	zoomUpMotion : function(mode) {
		var self = this;
		
		var slide = this.slides[this.currentKey];
		var img   = slide.img;
		
		var alignOffset = Math.floor((this.ZOOM_IMAGE_PROP.width - this.THUMB_IMAGE_PROP.width) / 2);
		var currentX = slide.moveX;
		
		slide.node.style.zIndex = 10;
		
		if(mode == "direct") {
			img.width  = this.ZOOM_IMAGE_PROP.width;
			img.height = this.ZOOM_IMAGE_PROP.height;
			
			slide.node.style.top = "12px";
			slide.node.style.left = (currentX - alignOffset) + "px";
			
			slide.shadow.style.width = this.ZOOM_IMAGE_PROP.width - this.SHADOW_IMAGE_SIZE + "px";
			slide.shadow.style.height = this.ZOOM_IMAGE_PROP.height - this.SHADOW_IMAGE_SIZE + "px";
			
			callback(mode);
		}
		else {
			slide.imgFx = new Fx.Morph(img, {duration: 300, transition: Fx.Transitions.Back.easeOut, onComplete:callback });
			slide.imgFx.start({
				"width"  : this.ZOOM_IMAGE_PROP.width,
				"height" : this.ZOOM_IMAGE_PROP.height
			});
			
			slide.zoomFx = new Fx.Morph(slide.node, {duration: 300, transition: Fx.Transitions.Back.easeOut });
			slide.zoomFx.start({
				"top"  : 12,
				"left" :currentX - alignOffset
			});
			
			slide.shadowFx = new Fx.Morph(slide.shadow, {duration: 300, transition: Fx.Transitions.Back.easeOut });
			slide.shadowFx.start({
				"width"  : this.ZOOM_IMAGE_PROP.width - this.SHADOW_IMAGE_SIZE,
				"height" : this.ZOOM_IMAGE_PROP.height - this.SHADOW_IMAGE_SIZE
			});
		}
		
		this.currentSlide = slide;
		
		
		function callback() {
			slide.swapZoom(mode, function(){ self.onSwapZoom(); });
		}
	},
	
	
	onSwapZoom : function() {
		this.isLockMotion = false;
		this.unlockButtons();
		this.startAutoPlay();
	},
	
	
	
	
	
	
	
	
	
	moveSlides : function(mode) {
		var self = this;
		var key = this.currentKey;
		
		var sideWidth   = Math.floor((this.windowWidth - this.ZOOM_WIDTH) / 2);
		var zoomOffset  = Math.floor((this.ZOOM_WIDTH - this.ZOOM_IMAGE_PROP.width - this.IMAGE_PADDING) / 2);
		var alignOffset = Math.floor((this.ZOOM_IMAGE_PROP.width - this.THUMB_IMAGE_PROP.width) / 2);
		
		var count = 0;
		var i, len;
		len = this.slides.length;
		
		for(i=0; i<len; i++) {
			var slide = this.slides[i];
			var posKey = this.checkPosition(i);
			

			if(posKey === 0) {
				slide.moveX = sideWidth - this.wrapOffset + zoomOffset - 2;
			}
			else if(posKey > 0) {
				slide.moveX = sideWidth - this.wrapOffset + this.ZOOM_WIDTH + this.THUMB_WIDTH * (posKey - 1) + 1;
			}
			else if(posKey < 0) {
				slide.moveX = sideWidth - this.wrapOffset - this.THUMB_WIDTH * (-posKey) + this.IMAGE_PADDING * 2;
			}
			
			
			if(self.motionDirection == "prev" && posKey == -2) {
				slide.node.style.left = (sideWidth - this.wrapOffset - this.THUMB_WIDTH * (-posKey + 1) + this.IMAGE_PADDING * 2) + "px";
			}
			else if(self.motionDirection == "next" && posKey == 2) {
				slide.node.style.left = (sideWidth - this.wrapOffset + this.ZOOM_WIDTH + this.THUMB_WIDTH * (posKey) + 1) + "px";
			}
			
			
			
			//slide.debug.innerHTML = slide.key + "/" + posKey;
			
			
			if(i === key) {
				slide.moveX += alignOffset;
			}
			
			
			var duration   = 500;
			var transition = Fx.Transitions.Sine.easeOut;
			if(this.isSequenceMode && Math.abs(this.currentKey - this.sequenceKey) >= 1) {
				duration = 200;
				transition = Fx.Transitions.linear;
			}
			
			
			if(mode === "direct") {
				toggleDisplay(slide, posKey);
				slide.node.style.left = slide.moveX + "px";
			}
			else {
				toggleDisplay(slide, posKey);
				slide.moveFx = new Fx.Morph(slide.node, {duration:duration, transition:transition, onComplete:callback});
				slide.moveFx.start({
					"left" : slide.moveX
				});
			}
		}
		
		
		
		if(mode == "direct") {
			if(!this.isFirstView) {
				self.zoomUpSlide(mode);
			}
		}
		
		
		function callback() {
			count++;
			if(count === len) {
				if(self.isSequenceMode) {
					self.moveSlidesSequence(mode);
				}
				else {
					self.zoomUpSlide(mode);
				}
			}
		}
		
		
		function toggleDisplay(_slide, _key) {
			if(Math.abs(_key) >= 4) {
				_slide.node.style.display = "none";
			}
			else {
				_slide.node.style.display = "block";
			}
			
			if(
			   (self.motionDirection == "next" && _key == 3) ||
			   (self.motionDirection == "prev" && _key == -3)
			 ){
				_slide.node.style.display = "none";
			}
		}
	},
	
	
	
	
	
	
	
	jumpToSlide : function(key) {
		if(this.isLockMotion) {
			return;
		}
		
		this.isLockMotion = true;
		
		var self = this;
		
		this.isSequenceMode = true;
		this.sequenceKey = key;
		
		
		var direction;
		var half = Math.ceil(this.slides.length / 2);
		
		if(key - this.currentKey > 0) {
			if(key - this.currentKey <= half) {
				direction = "next";
			}
			else {
				direction = "prev";
			}
		}
		else {
			if(key - this.currentKey <= -half) {
				direction = "next";
			}
			else {
				direction = "prev";
			}
		}
		
		this.motionDirection = direction;
		this.lockButtons();
		
		
		if(this.currentSlide) {
			this.zoomOutSlide(callback);
		}
		else {
			callback();
		}
		
		function callback() {
			self.moveSlidesSequence(key);
		}
	},
	
	
	
	moveSlidesSequence : function() {
		var len = this.slides.length;
		
		if(this.sequenceKey === this.currentKey) {
			this.zoomUpSlide("motion");
		}
		else {
			var nextKey;
			if(this.motionDirection == "next") {
				nextKey = (this.currentKey + 1 >= len) ? 0 : (this.currentKey + 1);
			}
			else {
				nextKey = (this.currentKey - 1 < 0) ? (len - 1) : (this.currentKey - 1);
			}
			this.currentKey = nextKey;
			this.moveSlides("motion");
		}
	},
	
	
	
	
	
	
	// ----------------------------------------------------------------------------------------------------

	checkPosition : function(num) {
		var key = this.currentKey;
		var len = this.slides.length;
		var half = Math.ceil(len / 2);
		var pos;
		
		if(num === key) {
			pos = 0;
		}
		else {
			if(Math.abs(num - key) < half) {
				pos = num - key;
			}
			else if(num - key > 0) {
				pos = num - key - len;
			}
			else {
				pos = num - key + len;
			}
		}
		
		
		if(half <= 3) {
			if(this.motionDirection == "prev" && pos == -3) {
				pos = 3;
			}
			else if(this.motionDirection == "next" && pos == 3) {
				pos = -3;
			}
		}
		
		return pos;
	},
	
	
	
	
	
	
	
	
	
	
	
	
	
	// ----------------------------------------------------------------------------------------------------
	// Aligner
	
	alignElements : function() {
		var halfWidth = Math.floor((this.windowWidth - this.ZOOM_WIDTH) / 2);
		
		if(this.isLockMotion) {
			return;
		}
		
		if(this.windowWidth > this.maxWidth) {
			this.wrap.style.width = this.maxWidth + "px";
			this.wrapOffset = Math.floor((this.windowWidth - this.maxWidth) / 2);
		}
		else {
			this.wrap.style.width = "100%";
			this.wrapOffset = 0;
		}
		this.wrap.style.left = this.wrapOffset + "px";
		
		this.btn_prev.style.left = (halfWidth - this.wrapOffset) + "px";
		this.btn_next.style.left = (halfWidth - this.wrapOffset + this.ZOOM_WIDTH - this.btn_next.getSize().x) + "px";
		this.moveSlides("direct");
	},
	
	
	
	
	
	
	
	
	// ----------------------------------------------------------------------------------------------------
	// Functions
	
	calcWindowSize : function() {
		this.windowWidth = $("wrap").getSize().x;
	},
	
	
	
	
	
	
	
	
	
	// ----------------------------------------------------------------------------------------------------
	// SubClass - Slide
	
	Slide : new Class({
		
		node     : null,
		btn      : null,
		img      : null,
		key      : 0,
		moveX    : 0,
		moveFx   : null,
		zoomFx   : null,
		imgFx    : null,
		fadeFx   : null,
		shadowFx : null,
		
		loadingIcon : null,
		loadingTimer : null,
		loadingState : "",
		
		zoomImg : null,
		shadow  : null,
		debug   : null,
		
		
		initialize : function(_key, _prop, _func) {
			this.key = _key;
			
			this.node = new Element("div");
			this.node.id = "slide-" + _key;
			this.node.className = "slide";
			this.node.style.top = "75px";
			
			this.img = new Image();
			this.img.className = "thumb";
			this.img.style.visibility = "hidden";
			this.img.src = "/asset/promo/" + _prop.file + "s.png";
			
			this.shadow = this.createShadow();
			this.node.adopt(this.shadow);
			
			this.node.adopt(this.img);
			
			this.loadingIcon = new Element("div");
			this.loadingIcon.className = "loading";
			
			this.loadThumbImage(_func);
			
			//this.debug = new Element("div", { html:_key, "class":"debug" });
			//this.node.adopt(this.debug)
		},
			
		
		
		loadThumbImage : function(_func) {
			var self = this;
			
			this.showLoading();
			this.loadingState = "start";
			
			this.img.onload = function() {
				if(this.className.match("loaded")) {
					return;
				}
				
				this.className += " loaded";
				
				if(self.loadingState == "complete") {
					callback();
				}
			}
			
			if(this.img.complete) {
				this.img.onload();
			}
			
			this.loadingTimer = setTimeout(function(){
				self.loadingState = "complete";
				if(self.img.className.match("loaded")) {
					callback();
				}
			}, 1000);
			
			
			function callback() {
				self.hideLoading();
				self.img.style.visibility = "visible";
				_func();
			}
		},
		
		
		
		
		loadZoomImage : function(_mode, _prop, _func) {
			var self = this;
			
			if(this.zoomImg && this.zoomImg.parentNode) {
				_func();
				return;
			}
			
			
			var file = _prop.file;
			var src  = "/asset/promo/" + file + ".png";
			
			
			this.btn = new Element("a");
			this.btn.href = _prop.link;
			this.btn.target = _prop.target;
			
			
			this.zoomImg = new Image();
			this.zoomImg.src = src;
			this.zoomImg.className = "zoom";
			
			if(_mode == "direct") {
				callback();
				return;
			}
			
			
			this.showLoading();
			this.loadingState = "start";
			
			this.zoomImg.onload = function() {
				if(this.className.match("loaded")) {
					return;
				}
				
				this.className += " loaded";
				
				if(self.loadingState == "complete") {
					callback();
				}
			}
			
			if(this.zoomImg.complete) {
				this.zoomImg.onload();
			}
			
			this.loadingTimer = setTimeout(function(){
				self.loadingState = "complete";
				if(self.zoomImg.className.match("loaded")) {
					callback();
				}
			}, 250);
			
			
			function callback() {
				self.hideLoading();
				_func();
			}
		},
		
		
		
		swapZoom : function(mode, _func) {
			var self = this;
			
			if(mode == "direct") {
				this.btn.adopt(this.zoomImg);
				this.node.adopt(this.btn);
				callback();
			}
			else {
				$(this.zoomImg).set("opacity", 0);
				this.btn.adopt(this.zoomImg);
				this.node.adopt(this.btn);
				this.fadeFx = new Fx.Morph(this.zoomImg, {duration: 250, transition: Fx.Transitions.linear, onComplete:callback });
				this.fadeFx.start({
					"opacity"  : 1
				});
			}
			
			function callback() {
				self.img.style.visibility = "hidden";
				_func();
			}
		},
		
		
		swapThumb : function() {
			this.img.style.visibility = "visible";
			
			if(this.zoomImg && this.zoomImg.parentNode) {
				this.btn.removeChild(this.zoomImg);
			}
			
			if(this.btn && this.btn.parentNode) {
				this.node.removeChild(this.btn);
			}
		},
		
		
		
		
		showLoading : function() {
			this.node.adopt(this.loadingIcon);
		},
		
		hideLoading : function() {
			try {
				this.node.removeChild(this.loadingIcon);
			}
			catch(e){}
		},
		
		
		
		
		createShadow : function() {
			var lt = new Element("span", { "class":"lt" });
			var lb = new Element("span", { "class":"lb" });
			var rt = new Element("span", { "class":"rt" });
			var rb = new Element("span", { "class":"rb" });
			var l  = new Element("span", { "class":"l" });
			var r  = new Element("span", { "class":"r" });
			var t  = new Element("span", { "class":"t" });
			var b  = new Element("span", { "class":"b" });
			var p  = new Element("span", { "class":"p" });
			
			var shadow = new Element("div", { "class":"shadow" });
			shadow.adopt(lt, lb, rt, rb, l, r, t, b, p);
			
			return shadow;
		}
		
		
		
	})
	
	
	
	
	
	
});

