(function() {
	var Event = YAHOO.util.Event;
	var Dom = YAHOO.util.Dom;
	var Region = YAHOO.util.Region;
	var Point = YAHOO.util.Point;
	var Connect = YAHOO.util.Connect;
	var Scroll = YAHOO.util.Scroll;
	var Anim = YAHOO.util.Anim;
	var History = YAHOO.util.History;

	OnePage = function(menuEl, siteMap, footer, historyField, historyIframe, idList) {
		this.menuEl = Dom.get(menuEl);
		this.siteMap = Dom.get(siteMap);
		this.footerEl = Dom.get(footer);
		this.idList = idList;
		this.imagePreLoad();
		this.initPosition();
		this.registerEvent();
		this.measure();
		this.initHistoryNavigation(historyField, historyIframe);
	}

	YAHOO.extend(OnePage, Object, {
		constructor: OnePage,

		easing: YAHOO.util.Easing.easeOutStrong,
		duration: 1.5,

		imagePreLoad: function() {
			var images = ['img/blue_left.png', 'img/blue_up.png', 'img/blue_right.png', 'img/blue_down.png'];
			this.each(images, function(el) {
				var img = new Image();
				img.src = el;
			});
		},

		initHistoryNavigation: function(historyField, historyIframe) {
			var _this = this;
			var bookmarkedSection = History.getBookmarkedState("page");
			var querySection = History.getQueryStringParameter("section");
			var initSection = bookmarkedSection || querySection || "top";

			History.register("page", initSection, function (state) {
				_this.move(state);
			});
			History.onReady(function() {
				_this.move(initSection);
			});

			try {
				History.initialize(historyField, historyIframe);
			} catch (e) {
				this.move(initSection);
			}
		},

		initPosition: function() {
			this.navigationEls = [];
			for (var y = 0, ylen = this.idList.length; y < ylen; y++) {
				var yList = this.idList[y];
				for (var x = 0, xlen = yList.length; x < xlen; x++) {
					var id = yList[x];
					var onePage = Dom.get(id);
					Dom.setStyle(onePage, 'position', 'absolute');
					Dom.setStyle(onePage, 'left', (x * 2000) + 'px');
					Dom.setStyle(onePage, 'top', (y * 2000) + 'px');
					if (y > 0) {
						var hash = this.idList[y - 1][x];
						if (hash) {
							var top = onePage.appendChild(document.createElement('div'));
							var img = top.appendChild(document.createElement('div'));
							Dom.addClass(top, 'top-nav');
							Event.on(top, 'mouseover', this.onHover, this, true);
							Event.on(top, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'mouseover', this.onHover, this, true);
							Event.on(img, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'click', this.onArrowClick, hash, this);
							this.navigationEls.push(top);
						}
					}
					if (x < xlen - 1) {
						var hash = this.idList[y][x + 1];
						if (hash) {
							var right = onePage.appendChild(document.createElement('div'));
							var img = right.appendChild(document.createElement('div'));
							Dom.addClass(right, 'right-nav');
							Event.on(right, 'mouseover', this.onHover, this, true);
							Event.on(right, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'mouseover', this.onHover, this, true);
							Event.on(img, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'click', this.onArrowClick, hash, this);
							this.navigationEls.push(right);
						}
					}
					if (y < ylen - 1) {
						var hash = this.idList[y + 1][x];
						if (hash) {
							var bottom = onePage.appendChild(document.createElement('div'));
							var img = bottom.appendChild(document.createElement('div'));
							Dom.addClass(bottom, 'bottom-nav');
							Event.on(bottom, 'mouseover', this.onHover, this, true);
							Event.on(bottom, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'mouseover', this.onHover, this, true);
							Event.on(img, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'click', this.onArrowClick, hash, this);
							this.navigationEls.push(bottom);
						}
					}
					if (x > 0) {
						var hash = this.idList[y][x - 1];
						if (hash) {
							var left = onePage.appendChild(document.createElement('div'));
							var img = left.appendChild(document.createElement('div'));
							Dom.addClass(left, 'left-nav');
							Event.on(left, 'mouseover', this.onHover, this, true);
							Event.on(left, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'mouseover', this.onHover, this, true);
							Event.on(img, 'mouseout', this.onUnHover, this, true);
							Event.on(img, 'click', this.onArrowClick, hash, this);
							this.navigationEls.push(left);
						}
					}
				}
			}
			this.moveMenu();
			this.moveFooter();
			Dom.setStyle(document.body, 'overflow', 'hidden');
			Dom.setStyle(document.documentElement, 'overflow', 'hidden');
			Dom.setStyle(this.footerEl, 'position', 'absolute');
		},

		registerEvent: function() {
			var els = document.getElementsByTagName('a');
			var _this = this;
			var url = location.protocol + '//' + location.host + location.pathname;
			this.each(els, function(el) {
				var elUrl = el.href.replace(/#.*/, '');
				if (elUrl != url) return;
				var hash = el.href.substring(url.length + 1);
				Event.on(el, 'click', _this.onClick, hash, _this);
			});

			Event.on(window, 'resize', this.measure, this, true);
			Event.on(window, 'resize', this.moveFooter, this, true);
			Event.on(this.siteMap, 'click', this.closeMenu, this, true);
		},

		getPosition: function(hash) {
			for (var y = 0, ylen = this.idList.length; y < ylen; y++) {
				var yList = this.idList[y];
				for (var x = 0, xlen = yList.length; x < xlen; x++) {
					var id = yList[x];
					if (id == hash) return [x, y];
				}
			}
			return null;
		},

		onArrowClick: function(evType, hash) {
			History.navigate('page', hash);
		},

		onHover: function(event) {
			// アニメーション中はHoverをtrueにしない
			if (this.moving) return;
			var target = Event.getTarget(event);
			if (target.className.indexOf('nav') == -1) target = target.parentNode;
			Dom.addClass(target, 'hover');
		},

		onUnHover: function(event) {
			var target = Event.getTarget(event);
			if (target.className.indexOf('nav') == -1) target = target.parentNode;
			Dom.removeClass(target, 'hover');
		},

		onClick: function(event, argument) {
			Event.stopEvent(event);
			var target = Event.getTarget(event);
			Dom.setStyle(this.siteMap, 'visibility', 'hidden');
			History.navigate('page', argument);
		},

		move: function(hash) {
			var pos = this.getPosition(hash);
			var x = pos[0];
			var y = pos[1];
			var anim;
			if (YAHOO.env.ua.webkit) anim = new Scroll(document.body, {scroll: {to: [x * 2000, y * 2000]}}, this.duration, this.easing);
			else anim = new Scroll(document.documentElement, {scroll: {to: [x * 2000, y * 2000]}}, this.duration, this.easing);
			anim.onComplete.subscribe(this.moveMenu, this, true)
			anim.onComplete.subscribe(this.moveFooter, this, true)
			anim.onComplete.subscribe(function() { this.moving = false; }, this, true)
			this.moving = true;
			anim.animate();
		},

		moveMenu: function() {
			var x = document.documentElement.scrollLeft || document.body.scrollLeft;
			var y = document.documentElement.scrollTop || document.body.scrollTop;
			Dom.setX(this.menuEl, x + 10);
			Dom.setY(this.menuEl, y + 10);
			var targetY = this.menuEl.getElementsByTagName('tr')[parseInt(y / 2000)];
			if (!targetY) return;
			var target = targetY.getElementsByTagName('td')[parseInt(x / 2000)];
			var current = Dom.getElementsByClassName('current');
			if (current.length > 0) Dom.removeClass(current[0], 'current');
			Dom.addClass(target, 'current');
		},

		moveFooter: function() {
			var x = document.documentElement.scrollLeft || document.body.scrollLeft;
			var y = document.documentElement.scrollTop || document.body.scrollTop;
			var viewportWidth = Dom.getViewportWidth();
			var viewportHeight = Dom.getViewportHeight();
			Dom.setX(this.footerEl, x + 20);
			Dom.setY(this.footerEl, y + viewportHeight - 30);
		},

		measure: function() {
			var viewportWidth = Dom.getViewportWidth();
			var viewportHeight = Dom.getViewportHeight();
			var sitemap = this.siteMap;
			Dom.setStyle(sitemap, 'visibility', 'hidden');
			Dom.setStyle(sitemap, 'width', '');
			Dom.setStyle(sitemap, 'height', '');
			Dom.setStyle(sitemap, 'display', '');
			max = recursive(100, 10);
			Dom.setStyle(sitemap, 'display', 'none');
			function recursive(max, min) {
				if (max - min <= 1) return min;
				var middle = parseInt((max + min) / 2);
				Dom.setStyle(sitemap, 'fontSize',  middle + 'px');
				var region = Dom.getRegion(sitemap);
				if (viewportWidth > region.right - region.left && viewportHeight > region.bottom - region.top) return recursive(max, middle);
				else return recursive(middle, min);
			}
		},

		enlarge: function() {
			var sitemap = this.siteMap;
			Dom.setStyle(sitemap, 'display', '');
			Dom.setStyle(sitemap, 'width', '');
			Dom.setStyle(sitemap, 'height', '');
			Dom.setStyle(sitemap, 'fontSize', '0px');
			Dom.setStyle(sitemap, 'visibility', 'visible');
			Dom.setStyle(sitemap, 'opacity', '0.7');
			var viewportHeight = Dom.getViewportHeight();
			var viewportWidth = Dom.getViewportWidth();

			var anim = new Anim(sitemap, { fontSize: { to: max, from: 0, unit: 'px'}, height: {to: viewportHeight, from: 1, unit: 'px'}, width: {to: viewportWidth, from: 1}}, 1, YAHOO.util.Easing.easeOutStrong);
			anim.animate();
		},

		closeMenu: function(event) {
			Dom.setStyle(this.siteMap, 'display', 'none');
		},

		each: function(ar, fn) {
			for (var i = 0, len = ar.length; i < len; i++) {
				fn(ar[i], i);
			}
		},

		contains: function(ar, value) {
			for (var i = 0, len = ar.length; i < len; i++) {
				if (ar[i] == value) return true;
			}
			return false;
		}
	});
})();
