var SOURCES_DIR = "sources/";

var CANVAS_SIZE = 1000;
var MAX_BUFFER = 500;
var LOAD_INTERVAL = 1000*15;
var AUDIO_LENGTH = 10;
var BGM_VOLUME = 0.8;
var TOMOSHIBI_VOLUME = 0.1;
var TOMOSHIBI_SPEED = 1000/10;
//知床岬：東経145度19分48秒, 北緯44度20分42秒 > 145.33, 44.345
//糸満： 東経127度40分8秒, 北緯26度4分41秒 > 127.669, 26.078
var ZOOM = 20;
var MICRO_ZOOM_Y_RATE = 0.3;
var MICRO_ZOOM_Y = ZOOM*MICRO_ZOOM_Y_RATE;
var MAXS = 60;
var MINS = 5;
var MACRO_MINS = 15;
var MINUS = 10;
var MINX = 172;
var MAXX = 828;
var MINX = 191;
var MAXX = 845;
var MINY = 156;
var MAXY = 832;
var ALPHA = 30;
var ALPHA_MICRO = 50;
var TO_RADIAN = Math.PI / 180;
var R_45 = TO_RADIAN * 45;
var SIN_45 = Math.sin(R_45);
var COS_45 = Math.cos(R_45);

var XRATE = (MAXX-MINX) / (145.33-127.669);
var YRATE = (MAXY-MINY) / (26.078-44.345);

var SAMPLE_RATE = 44100;
var SOUND_LENGTH = 100;
var MILLI_LENGTH = SAMPLE_RATE*SOUND_LENGTH/1000;
var BASIC_BGM_SECOND = 4;

var Main = {
	getCanvasX: function(lon) {
		return MINX + (lon - 127.669) * XRATE;
	},
	
	getCanvasY: function(lat) {
		return MINY + (lat - 44.345) * YRATE;
	},
	
	start: function() {
		//prepares counters
		Main.labels = ["HOKKAIDO","AOMORI","IWATE","MIYAGI","AKITA","YAMAGATA","FUKUSHIMA","IBARAKI","TOCHIGI","GUNMA","SAITAMA","CHIBA","TOKYO","KANAGAWA","NIIGATA","TOYAMA","ISHIKAWA","FUKUI","YAMANASHI","NAGANO","GIFU","SHIZUOKA","AICHI","MIE","SHIGA","KYOTO","OSAKA","HYOGO","NARA","WAKAYAMA","TOTTORI","SHIMANE","OKAYAMA","HIROSHIMA","YAMAGUCHI","TOKUSHIMA","KAGAWA","EHIME","KOCHI","FUKUOKA","SAGA","NAGASAKI","KUMAMOTO","OITA","MIYAZAKI","KAGOSHIMA","OKINAWA"];

		Main.information_pane = $("#information-pane");
		Main.information_pane_name = $("#information-pane-name");
		Main.information_pane_count = $("#information-pane-count");

		Main.counterjapanui = $("#JAPAN .counter");
		Main.counteruis = {};
		Main.counts = {};
		for (var i = 0; i < Main.labels.length; i++) {
			var name = Main.labels[i];
			Main.counteruis[name] = $("#"+name+" .counter");
			Main.counts[name] = 0;
		}
		
		$("#navigation-pane-sound").click(SoundController.onClick);
		
		Main.main_container = $("#main-container");
		Main.tomoshibi_canvas = $("#tomoshibi-canvas");
		Main.japan_canvas = $("#japan-canvas");

		Main.lastclicktime = 0;
		var svgdocument = Main.japan_canvas[0].getSVGDocument();
		var jsvgdocument = $(svgdocument);
		jsvgdocument.bind("mousedown", Main.onMouseDown);
		jsvgdocument.bind("mouseup", Main.onMouseUp);
		jsvgdocument.bind("mousemove", Main.onMouseMove);
		var japan = $("#JAPAN", svgdocument);
		japan.bind("mouseover", Main.onMouseOverJapan);
		japan.bind("mouseout", Main.onMouseOutJapan);
		Main.svgdocument = svgdocument;

		new Processing(Main.tomoshibi_canvas[0], Main.init);
			
		//AUROLA 2011.08.11
		Main.japan_canvas[0].addEventListener("mousedown", function(event) {
			Main.onMouseDown(event);
			Main.onMouseUp(event);
		}, false);

   	},
	
	setupCounterDock: function() {
		//dock-like side counter		
		var paneid = "counter";
		var pane = $("#"+paneid);
		var menus = $(".line");
		var MAX_RANGE = 35;
		var MAX_SIZE = 32;
		var TO_CALC = (Math.PI / 180)/MAX_RANGE*90;
		var fontsizes = [];
		var topmenu = $(menus[0]);
		Main.current_ydif = 0;
		pane.mousemove(function(e) {
			var menuheight = Main.base_menuheight;
			var halfheight = Main.base_menuheight_half;
			var y = (e.pageY-this.offsetTop) + Main.current_ydif;
			var focusindex = 0;
			var focusoffset = 0;
			for (var i = 0, n = menus.length; i < n; i++) {
				var menu = $(menus[i]);
				var yy = menuheight*i;
				var dd = y-(yy+halfheight);
				var dy = Math.abs(dd);
				fontsizes[i] = Main.base_fontsize;
				if (MAX_RANGE > dy) {
					var cos = Math.cos(TO_CALC*dy);
					var size = MAX_SIZE*cos;
					fontsizes[i] += size;
					if (yy <= y && y <= yy+menuheight) {
						focusindex = i;
						focusoffset = yy-y;
						//break;
					}
				}
			}
			for (var i = 0, n = menus.length; i < n; i++) {
				var menu = $(menus[i]);
				menu.css("font-size", fontsizes[i]+"px");
			}
			
			var menu = $(menus[focusindex]);
			var ydif = y-menu.position().top + focusoffset/menuheight*menu.height();
			if (ydif > 0) {
				return;
			}
			pane.css("margin-top", ydif+"px");
			Main.current_ydif = ydif;
		});
		pane.mouseout(function(e) {
			var id = !e.relatedTarget ? "main-container" : e.relatedTarget.getAttribute("id");
			if (id == "japan-canvas" || id == "main-container") {
				Main.current_ydif = 0;
				pane.css("margin-top", "0px");
				menus.css("font-size", Main.base_fontsize+"px");
			}
		});
	},
	
	onResize: function() {
		var win = $(window);
		var w = win.width();
		var h = win.height();
		var size = Math.min(w, h);
		var x = (w-size)/2;
		var y = (h-size)/2;
		Main.japan_canvas_x = x;
		Main.japan_canvas_y = y;
		Main.japan_canvas_w = size;
		Main.japan_canvas_h = size;

		//svg size for webkit
		Main.svgdocument.documentElement.setAttribute("width", size);
		Main.svgdocument.documentElement.setAttribute("height", size);

		Main.japan_canvas.css({"top":y+"px", "left":x+"px", "width":size+"px", "height":size+"px", "opacity":1});
		
		Main.setupTomoshibiCanvasBounds();

		//font size
		$("#information-pane-name").css("font-size", (h/6)+"px");
		$("#information-pane-count").css("font-size", (h/6)+"px");
		//counter
		var counter = $("#counter");
		var counterHeight = h - (50*2);
		var japanline = $("#JAPAN");
		var fontsize = 14;
		for (;;) {
			japanline.css("font-size", fontsize+"px");
			var height = japanline.height();
			if (height*Main.labels.length < counterHeight || fontsize < 2) {
				break;
			}
			fontsize -= 1;
		}
		for (var i = 0; i < Main.labels.length; i++) {
			$("#"+Main.labels[i]).css("font-size", fontsize+"px");
		}

		var hh = counter.height();
		var yy = (h-hh)/2;
		counter.css("top", yy+"px");
		
		Main.base_menuheight = japanline.height();
		Main.base_menuheight_half = Main.base_menuheight/2;
		Main.base_fontsize = fontsize;

		Main.setupCounterDock();
	},
	
	init: function(processing) {
		Main.star_image = processing.loadImage("svg/tomoshibi.svg");

		Main.prefindex = 0;
		Main.current_counts = {};

		Main.tomoshibis = [];
		Main.b4x = new Uint16Array(MAX_BUFFER);
		Main.b4y = new Uint16Array(MAX_BUFFER);
		Main.b4s = new Uint8Array(MAX_BUFFER);
		Main.b4c = new Int32Array(MAX_BUFFER);
		Main.b4l = new Uint16Array(MAX_BUFFER);
		Main.b4n = {};

		Main.processing = processing;
		Main.processing.size(CANVAS_SIZE, CANVAS_SIZE);
        Main.processing.background(0, 0);
		Main.processing.frameRate(30);
		Main.processing.draw = Main.draw4macro;

		Main.onResize();
		$(window).resize(Main.onResize);

		Main.loadStatistics(function() {
			$("#counter").animate({"opacity":0.99}, 1000, function() {
				setTimeout(function() {
					$("#counter").css("opacity", 1);
				}, 1000);
			});
			Main.loadTomoshibi();
		});
	},
	
	draw4macro: function() {
		//update
		Main.update4macro();
		var processing = Main.processing;
        processing.background(0, 0);
        processing.noStroke();
		for (var j = 0; j < MAX_BUFFER; j++) {
			if (Main.b4s[j] != 0) {
				var x = Main.b4x[j];
				var y = Main.b4y[j];
				var size = Main.b4s[j]/2;

				processing.pushMatrix();
				processing.translate(x, y);
		        processing.fill(Main.b4c[j], ALPHA);
		        
				processing.rotate(Math.random());
				if (size < MINS) {
					size = size/3+Math.random()*size/2;
			        processing.fill("#ffffff");
			        processing.ellipse(0, 0, size, size);  
				} else {
					var halfsize = size/2;
					processing.image(Main.star_image, -halfsize, -halfsize, size, size);
			        processing.ellipse(0, 0, size*1.5, size*1.5);
				}
				processing.popMatrix();
			}
		}
    },
	
	draw4micro: function() {
		//update
		Main.update4micro();
		var processing = Main.processing;
        processing.background(0, 0);
        processing.noStroke();
		
		processing.translate(Main.current_marginx4canvas, Main.current_marginy4canvas);		
		processing.translate(Main.japan_canvas_x/Main.tomoshibi_canvas.width()*CANVAS_SIZE, Main.japan_canvas_y/Main.tomoshibi_canvas.height()*CANVAS_SIZE);
		var scalex = Main.japan_canvas_w/Main.tomoshibi_canvas.width();
		var scaley = Main.japan_canvas_h/Main.tomoshibi_canvas.height();
		processing.scale(scalex, scaley);
		processing.translate(Main.center_x, Main.center_y);
		processing.scale(1, MICRO_ZOOM_Y_RATE);
		processing.rotate(R_45);
		processing.translate(-Main.center_x, -Main.center_y);
		
    	//zooming
		var sx = Main.view_x;
		var sy = Main.view_y;
		var wv = Main.view_w;
		var hv = Main.view_h;

		for (var j = 0; j < MAX_BUFFER; j++) {
			if (Main.b4s[j] != 0) {
				Main.draw4tomoshibi(processing, sx, sy, wv, hv, j);
			}
		}
	},

	draw4tomoshibi: function(processing, sx, sy, wv, hv, j) {
		var x = Main.b4x[j];
		var y = Main.b4y[j];
		//全体にマップ
		x = (x-sx)/wv*CANVAS_SIZE;
		y = (y-sy)/hv*CANVAS_SIZE;

		processing.pushMatrix();
		processing.translate(x, y);

		var size = Main.b4s[j];
		var alpha = ALPHA_MICRO;
		if (size == MINS) {
			if (size < MACRO_MINS) {
				size = MACRO_MINS*2+MACRO_MINS*Math.random()*0.5;
			}
		} else {
			var rate = size/MAXS;
			var circlesize = (MAXS - size)/2;
			var aOfCircle = rate*128;
	        processing.fill(0xffffff, aOfCircle);
        	processing.ellipse(0, 0, circlesize, circlesize);  
			size *= 1.6;
		}

		var lsize = size*5;
		processing.rotate(-R_45);
        processing.noStroke();
        processing.fill(Main.b4c[j], alpha);
        processing.beginShape();
        var offset = lsize/size;
        var half = offset/2;
		processing.bezier(-half, 0, -half, -lsize, half, -lsize, half, 0);
		
        processing.endShape();

        processing.fill(0xffffff, alpha/2);
        processing.beginShape();
		processing.bezier(-half, 0, -half, -lsize/3, half, -lsize/3, half, 0);
        processing.endShape();
				
		processing.popMatrix();
	},
	
	updateLiveTomoshibis: function(diff) {
		var minus = MINUS*diff/TOMOSHIBI_SPEED;
		for (var j = 0; j < MAX_BUFFER; j++) {
			var size = Main.b4s[j];
			if (size != 0) {
				Main.b4l[j] += 1;
				size = size-(Math.random()*minus);
				if (size < MINS) {
					size = MINS;
				}
				Main.b4s[j] = size;
			}
		}
	},
	
	update4macro: function() {
		//new tomoshibi
		var diff = Main.getDiff();
		Main.updateLiveTomoshibis(diff[1]);
		var difcount = diff[0];
		var enablecount = 0;
		for (var i = 0; i < difcount; i++) {
			var tomoshibi = Main.tomoshibis.shift();
			if (!tomoshibi) {
				break;
			}
			Main.updatePrefectureCount(tomoshibi);
			Main.newTomoshibi(tomoshibi);
			enablecount += 1;
		}
		//sound
		enablecount = enablecount > AUDIO_LENGTH ? AUDIO_LENGTH : enablecount;
		for (var i = 0; i < enablecount; i++) {
			SoundController.playTomoshibiMACRO(i);
		}
		
		Main.updateCount();
		Main.updateInformationPane(Main.counterjapanui.text());
	},
	
	update4micro: function() {
		var diff = Main.getDiff();
		Main.updateLiveTomoshibis(diff[1]);
		var difcount = diff[0];
		var offset = 100;
		var sx = Main.view_x-offset;
		var ex = Main.view_x+Main.view_w+offset*2;
		var sy = Main.view_y-offset;
		var ey = Main.view_y+Main.view_h+offset*2;

		var enablecount = 0;		
		for (var i = 0; i < difcount; i++) {
			var tomoshibi = Main.tomoshibis.shift();
			if (!tomoshibi) {
				break;
			}
			Main.updatePrefectureCount(tomoshibi);
			Main.newTomoshibi(tomoshibi);
			enablecount += 1;
		}
		if (enablecount > 0) {
			Main.updateInformationPane(Math.round(Main.counts[Main.selected_prefecture]));
		}
		enablecount = enablecount > AUDIO_LENGTH ? AUDIO_LENGTH : enablecount;
		for (var i = 0; i < enablecount; i++) {
			SoundController.playTomoshibiMICRO(i);
		}
		Main.updateCount();
	},

	update4prefecture: function() {
		var diff = Main.getDiff();
		Main.updateLiveTomoshibis(diff[1]);
		var difcount = diff[0];
		var enablecount = 0;
		for (var i = 0; i < difcount; i++) {
			var tomoshibi = Main.tomoshibis.shift();
			if (!tomoshibi) {
				break;
			}
			Main.updatePrefectureCount(tomoshibi);
			var name = tomoshibi[2];
			if (name != Main.selected_prefecture) {
				continue;
			}
			Main.updateInformationPane(Main.counts[name]);
			
			Main.newTomoshibi(tomoshibi);
			enablecount += 1;
		}
		if (enablecount > 0) {
			enablecount = 1;
		}
		for (var i = 0; i < enablecount; i++) {
			SoundController.playTomoshibiMICRO(i);
		}
		Main.updateCount();
	},
	
	updatePrefectureCount: function(tomoshibi) {
		var name = tomoshibi[2];
		var percount = tomoshibi[3];
//		Main.counts[name] = Math.round(percount+Main.counts[name]);
		Main.counts[name] = percount+Main.counts[name];
	},
	
	getDiff: function() {
		var currenttime = (new Date()).getTime();
		var timedif = currenttime - Main.last_loaded;
		var rate = timedif/LOAD_INTERVAL;
		var count = Math.round(rate * Main.tomoshibi_count);
		var time2 = currenttime - Main.last_updated;
		Main.last_updated = currenttime; 
		return [Main.tomoshibis.length - (Main.tomoshibi_count - count), time2];
	},
	
	newTomoshibi: function(tomoshibi) {
		var index = Main.findNextBox();
		if (index < 0) {
			return;
		}
		var x = tomoshibi[0];
		var y = tomoshibi[1];
		Main.b4s[index] = MAXS;
		Main.b4x[index] = x;
		Main.b4y[index] = y;
		
		var color = tomoshibi[4];
		Main.b4c[index] = color;

		Main.b4n[index] = tomoshibi[2];
		Main.b4l[index] = 0;
	},
	
	updateCount: function() {
		var total = 0;
		for (var i = 0; i < Main.labels.length; i++) {
			var name = Main.labels[i];
			var count = Math.round(Main.counts[name]);
			Main.counteruis[name].text(count);
			total += count;
		}
		Main.counterjapanui.text(total);
	},
	
	setupTomoshibiCanvasBounds: function() {
		if (Main.processing.draw == Main.draw4macro) {
			Main.tomoshibi_canvas.css({"top":Main.japan_canvas_y+"px", "left":Main.japan_canvas_x+"px", "width":Main.japan_canvas_w+"px", "height":Main.japan_canvas_h+"px"});
		} else {
			Main.tomoshibi_canvas.css({"top":"0px", "left":"0px", "width":"100%", "height":"100%"});
		}
	},
	
	next_index : 0,
	findNextBox: function() {
		var returned = Main.next_index;
		Main.next_index += 1;
		if (MAX_BUFFER == Main.next_index) {
			Main.next_index = 0;
		}
		var size = Main.b4s[returned];
		if (size > MINS) {
			return -1;
		}
		return returned;
	},
	
	loadStatistics: function(callback) {
		var url = SOURCES_DIR+"statistics6.txt?"+(new Date().getTime());
		$.get(url, function(data){
			var lines = data.split("\n");
			var total = 0;
			for (var i = 0, n = lines.length; i < n; i++) {
				var line = lines[i];
				var elements = line.split(",");
				if (elements.length != 2) {
					continue;
				}
				var name = elements[0];
				var count = parseInt(elements[1]);
				Main.counts[name] = count;
				Main.counteruis[name].text(count);
				total += count;
			}
			Main.counterjapanui.text(total);
			callback();
		});
	},
	
	loadTomoshibi: function() {
		var url = SOURCES_DIR+"tomoshibi6.txt?"+(new Date().getTime());
		$.get(url, function(data){
			var tomoshibis = [];
			var lines = data.split("\n");
			
			for (var i = 0; i < Main.labels.length; i++) {
				Main.current_counts[Main.labels[i]] = 0;
			}

			var prefectures = {};
			var prefcount = 0;
			for (var i = 0, n = lines.length; i < n; i++) {
				var line = lines[i];
				var elements = line.split(",");
				if (elements.length != 5) {
					continue;
				}
				var name = elements[3];
				if (name == "null") {
					continue;
				}
				var lon = parseFloat(elements[0]);
				var lat = parseFloat(elements[1]);
				var x = Math.round(Main.getCanvasX(lon));
				var y = Math.round(Main.getCanvasY(lat));
				var colorstring = elements[4];
				var color = parseInt("0xff"+colorstring, 16);
				var total = parseInt(elements[2]);
				var count = total;
				if (count > 5) {
					count += Math.ceil(Math.log(count-5));
				}
				var percount = total / count;
				for (var j = 0; j < count; j++) {
					tomoshibis.push([x,y,name, percount, color]);
				}
				Main.current_counts[name] += count;
				if (!prefectures[name]) {
					prefectures[name] = true;
					prefcount += 1;
				}
			}
			
			Main.cover_all_prefecture = prefcount == Main.labels.length;
			
			//shuffle
			var o = tomoshibis;
			for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);

			//find max
			var maxcount = 0;
			for (var i = 0; i < Main.labels.length; i++) {
				maxcount = Math.max(maxcount, Main.current_counts[Main.labels[i]]);
			}
			Main.maxcount = maxcount;
			if (maxcount > AUDIO_LENGTH) {
				for (var i = 0; i < Main.labels.length; i++) {
					var count = Main.current_counts[Main.labels[i]];
					count = Math.ceil(count/maxcount * AUDIO_LENGTH);
					Main.current_counts[Main.labels[i]] = count;
				}
			}

			Main.tomoshibis = Main.tomoshibis.concat(tomoshibis);
			Main.tomoshibi_count = Main.tomoshibis.length;
			Main.last_loaded = (new Date()).getTime();
			Main.last_updated = Main.last_loaded;
			setTimeout(Main.loadTomoshibi, LOAD_INTERVAL);
		});
	},
	//user interaction -----------------------------------------------------
	onClick: function(e) {
		Main.lastmouse = e;
		var currenttime = (new Date()).getTime();
		var dif = currenttime - Main.lastclicktime;
		Main.lastclicktime = currenttime;
		if (dif < 500) {
			//500ms以内の連続クリックはダブルクリックとして無視する。
			return;
		}
		Main.tomoshibi_canvas.hide();
		//Main.japan.css("filter", "");
		if (Main.processing.draw == Main.draw4macro) {
			var width = Main.japan_canvas.width();
			var height = Main.japan_canvas.height();
			var ww = width/ZOOM;
			var hh = height/ZOOM;
			var clickXOnCanvas = e.clientX;
			var clickYOnCanvas = e.clientY;
			var xx = clickXOnCanvas - clickXOnCanvas/width*ww;
			var yy = clickYOnCanvas - clickYOnCanvas/height*hh;
			var xrate = CANVAS_SIZE/width;
			var yrate = CANVAS_SIZE/height;
			Main.clickx = clickXOnCanvas;
			Main.clicky = clickYOnCanvas;
			Main.xrate = xrate;
			Main.yrate = yrate;
			Main.center_x = clickXOnCanvas*xrate;
			Main.center_y = clickYOnCanvas*yrate;
			Main.view_x = xx*xrate;
			Main.view_y = yy*yrate;
			Main.view_w = ww*xrate;
			Main.view_h = hh*yrate;

			StyleController.duration(Main.japan_canvas, "1s");
			StyleController.origin(Main.japan_canvas, (e.clientX)+"px "+(e.clientY)+"px");
			StyleController.transform(Main.japan_canvas, "scale("+ZOOM+","+MICRO_ZOOM_Y+") rotate(45deg)");

			Main.current_marginx = 0;
			Main.current_marginy = 0;
			Main.current_marginx4canvas = 0;
			Main.current_marginy4canvas = 0;

			Main.processing.draw = Main.draw4micro;
			Main.unFocus();
		} else {
			StyleController.transform(Main.tomoshibi_canvas, "");
			StyleController.duration(Main.japan_canvas, "1s");
			StyleController.transform(Main.japan_canvas, "");
			Main.processing.draw = Main.draw4macro;
			Main.unFocus();
		}
		Main.setupTomoshibiCanvasBounds();
		Main.isTransitioning = true;
		setTimeout(function() {
			Main.isTransitioning = false;
			Main.tomoshibi_canvas.show();
			if (Main.processing.draw == Main.draw4micro) {
				Main.onMouseOver(Main.lastmouse);
			}
		}, 1100);
	},
	
	onMouseDown: function(e) {
		Main.dragged = false;
		if (Main.processing.draw == Main.draw4macro) {
		} else {
			Main.movable = true;
			Main.current_mousex = e.screenX;
			Main.current_mousey = e.screenY;
			StyleController.duration(Main.japan_canvas, "");
		}
	},
	
	onMouseMove: function(e) {
		if (Main.movable != true) {
			return;
		}
		Main.dragged = true;
		var x = e.screenX;
		var y = e.screenY;
		var dx = (Main.current_mousex-x);
		var dy = (Main.current_mousey-y);
		Main.current_mousex = x;
		Main.current_mousey = y;
		xvector = dx;
		yvector = dy;
		Main.current_marginx -= xvector;
		Main.current_marginy -= yvector;
		Main.current_marginx4canvas = Main.current_marginx/Main.main_container.width()*CANVAS_SIZE;
		Main.current_marginy4canvas = Main.current_marginy/Main.main_container.height()*CANVAS_SIZE;
		StyleController.transform(Main.japan_canvas, "translate("+Main.current_marginx+"px,"+Main.current_marginy+"px) scale("+ZOOM+","+MICRO_ZOOM_Y+") rotate(45deg)");
		Main.tomoshibi_canvas.hide();
	},

	onMouseUp: function(e) {
		if (Main.dragged == false) {
			Main.onClick(e);
		} else {
			var processing = Main.processing;
	        processing.externals.context.clearRect(0, 0, processing.width, processing.height);
			Main.tomoshibi_canvas.show();
		}
		Main.movable = false;
		Main.dragged = false;
	},

	//over > out > over
	unFocus: function() {
		if (Main.selected_prefecture != null) {
			var element = $("#"+Main.selected_prefecture, Main.svgdocument);
			element.animate({"stroke-width":0.1}, 500, function() {
				element.css("stroke", "#333");
			});
		}
		Main.information_pane.hide();
		Main.selected_prefecture = null;
	},
	
	onMouseOver: function(e) {
 		if (Main.dragged == true) {
 			return;
 		}
		Main.lastmouse = e;
		if (Main.isTransitioning == true || !Main.lastmouse) {
			return;
		}
		var element = $(e.target);
		var name = element.attr("id");
		if (!name) {
			Main.selected_prefecture = null;
			return;
		}
		element.css({"stroke-width":0.5, "stroke":"#fff"});
		var count = Math.round(Main.counts[name]);
		Main.showInformationPane(name, count);
		Main.selected_prefecture = name;
	},
	
	onMouseOut: function(e) {
 		if (Main.dragged == true) {
 			return;
 		}
 		Main.lastmouse = null;
		Main.unFocus();
	},

	onMouseOverJapan: function(e) {
		if (Main.processing.draw != Main.draw4macro) {
			Main.onMouseOver(e);
		} else {
			Main.showInformationPane("JAPAN", Main.counterjapanui.text());
		}
	},
	
	onMouseOutJapan: function(e) {
		if (Main.processing.draw != Main.draw4macro) {
			Main.onMouseOut(e);
		} else {
			Main.unFocus();
		}
	},
	
	getCommaString: function(str) {
		for (str = new String(str); str != (str = str.replace(/^(-?\d+)(\d{3})/, "$1,$2")); );
		return str;
	},
	
	updateInformationPane: function(count) {
		Main.information_pane_count.text(Main.getCommaString(count));
	},
	
	showInformationPane: function(name, count) {
		Main.information_pane_name.text(name);
		Main.information_pane_count.text(Main.getCommaString(count));
		Main.information_pane.show();
	}
}

var StyleController = {
	transform: function(target, value) {
		StyleController.apply(target, "transform", value);
	},
	duration: function(target, value) {
		StyleController.apply(target, "transition-duration", value);
	},
	origin: function(target, value) {
		StyleController.apply(target, "transform-origin", value);
	},
	apply: function(target, property, value) {
		target.css("-moz-"+property, value);
		target.css("-webkit-"+property, value);
		target.css("-o-"+property, value);
		target.css("-ms-"+property, value);
	}
}

var SoundController = {
	onClick: function() {
		if (!SoundController.initialized) {
			if (!Audio || !(new Audio()).mozSetup) {
				var result = confirm("この機能は Firefox で先行導入された Audio Data API によって実装されています。Firefox をダウンロードしますか？");
				if (result == true) {
					window.open("http://mozilla.jp/firefox/", "_blank");
				}
				return;
			}
			SoundController.init();
			SoundController.initialized = true;
		}
		if (SoundController.on == true) {
			var button = $("#navigation-pane-sound");
			button.text("SOUND OFF");
			button.removeClass("on");
			SoundController.on = false;
			SoundController.playTomoshibi = function() {};
			SoundController.playTomoshibiMACRO = function() {};
			SoundController.playTomoshibiMICRO = function() {};
			for (var i = 0; i < SoundController.audios.length; i++) {
				SoundController.audios[i].volume = 0;
			}
		} else {
			var button = $("#navigation-pane-sound");
			button.text("SOUND ON");
			button.addClass("on");
			SoundController.on = true;
			SoundController.playTomoshibiMACRO = SoundController.playTomoshibiMACRO_REAL;
			SoundController.playTomoshibiMICRO = SoundController.playTomoshibiMICRO_REAL;
			SoundController.fadeIn(0);
		}
	},
	
	fadeIn: function(volume) {
		volume += 0.05;
		if (volume >= 1) {
			volume = 1;
		}
		for (var i = 0; i < SoundController.audios.length; i++) {
			SoundController.audios[i].volume = volume;
		}
		if (volume < 1) {
			setTimeout(SoundController.fadeIn, 100, volume);
		}
	},
	
	init: function() {
	    SoundController.current_audio_index = 0;
		SoundController.audios = [];
		for (var i = 0; i < AUDIO_LENGTH; i++) {
			SoundController.audios[i] = new Audio();
			SoundController.audios[i].volume = 0;
			SoundController.audios[i].mozSetup(2, SAMPLE_RATE);
		}
		
		//ソ、ラ、シ、レ
//		SoundController.freqtable = [391/2, 440/2, 493/2, 587/2, 391, 440, 493, 587, 391*2, 440*2, 493*2, 587*2, 391*4, 440*4, 493*4, 587*4];
		SoundController.freqtable = [391/4, 440/4, 493/4, 587/4, 391/2, 440/2, 493/2, 587/2, 391, 440, 493, 587];
		//ミソドミ
		SoundController.freqtable_micro = [329/4, 391/4, 523/4, 659/4, 329/2, 391/2, 523/2, 659/2, 329, 391, 523, 659];
//		SoundController.freqtable_micro = [329/2, 391/2, 523/2, 659/2, 329, 391, 523, 659, 329*2, 391*2, 523*2, 659*2, 329*4, 391*4, 523*4, 659*4];
//		SoundController.freqtable_micro = [329/4, 391/4, 523/4, 659/4, 329/2, 391/2, 523/2, 659/2, 329, 391, 523, 659, 329*2, 391*2, 523*2, 659*2, 329*4, 391*4, 523*4, 659*4];
		SoundController.bgmindex = 0;
		//アップとアウトで、ピッチのクラスタを変えた
		//デュレーションを変えた、エンベロープのかけかたを変えた
		//音高(ピッチ)、音長(デュレーション)、音色(時間エンベロープ)
	},
	
	playTomoshibiMACRO: function() {
	},
	playTomoshibiMICRO: function() {
	},
	
	playTomoshibiREAL: function(index, range, table) {
		//checks this audio is working or not
		var soundlength = MILLI_LENGTH*range;
	    var freq = table[Math.floor(Math.random()*SoundController.freqtable.length)];
    	var data = new Float32Array(soundlength);
	    var k = 2* Math.PI * freq / SAMPLE_RATE;
	    var time = index*soundlength/30;
	    for(var j=time, n = data.length; j<n;j++){
	        data[j] = Math.sin(k * j) * TOMOSHIBI_VOLUME;
	    }
	    
//	    if (range > 8) {
	    	var pattern = Math.floor(Math.random()*3);
		    var envelope = data.length*(pattern == 0 ? 0.1 : pattern== 1? 0.4 : 0.5);
		    for(var j=0; j<envelope;j++){
		        data[j] *= j/envelope; 
		    }
		    for(var j=envelope, n = data.length; j<n;j++){
		        data[j] *= (1-j/n); 
		    }
//	    }

	    SoundController.write2device(SoundController.audios[SoundController.current_audio_index], data);
	    SoundController.current_audio_index += 1;
	    if (SoundController.current_audio_index == SoundController.audios.length) {
		    SoundController.current_audio_index = 0;
	    }
	},
	
	playTomoshibiMICRO_REAL: function(index) {
		var range = 10+Math.ceil(Math.random()*40);
		SoundController.playTomoshibiREAL(index, range, SoundController.freqtable_micro);
	},
	
	playTomoshibiMACRO_REAL: function(index) {
		var range = 10+Math.ceil(Math.random()*10);
		SoundController.playTomoshibiREAL(index, range, SoundController.freqtable);
	},
	
	write2device: function(audio, buffer) {
	    audio.mozWriteAudio(buffer);
	}
}

$(window).load(function(){
	Main.start();
});
