soundManager.defaultOptions.debugMode = false; // disable debug output

var MW = new Object();

MW = {
	display_log: true,				// enable log display
	path_sounds: 'sounds/',		// directory with mp3s
	
	init: function(soundmanager) {
		this.sm = soundmanager;
		
		MW.input.init();
		
		MW.loader.add('welcome2.mp3', 'welcome');
		MW.loader.add('play.mp3', 'play');
		MW.loader.add('rules.mp3', 'rules');
		MW.loader.add('start.mp3', 'menu_music');
		MW.loader.add('quit.mp3', 'quit');
		MW.loader.add('bonk.mp3', 'bip');
		MW.loader.add('AMB_BD_1.mp3', 'pok');
		MW.loader.add('footstep1.mp3', 'step1');
		MW.loader.add('footstep2.mp3', 'step2');
		MW.loader.add('thunder.mp3', 'thunder');
		MW.loader.add('fullrules.mp3', 'fullrules');
		MW.loader.add('fullrules2.mp3', 'fullrules2');
		MW.loader.add('gameover.mp3', 'gameover');
		MW.loader.add('ambiant.mp3', 'game_music');
		MW.loader.add('levelup.mp3', 'levelup');
		MW.loader.add('attack.mp3', 'attack');
		MW.loader.add('wins.mp3', 'wins');
		MW.loader.add('left.mp3', 'left');
		MW.loader.add('right.mp3', 'right');
		
		MW.loader.start('MW.menu.init();');
	},
	
	log: function(msg) {
		if(this.display_log) {
			//soundManager._writeDebug(msg);
			//console.log(msg);
		}
	}
};

MW.loader = {
	files: [],
	status: {'current':0, 'total':0},
	callback: function() { },
	
	add: function(filename, alias) {
		this.files[this.files.length] = {'filename':filename, 'alias':alias};
		this.status.total++;
		return true;
	},
	
	start: function(callback) {
		this.callback = callback;
		
		if(this.status.total > 0) {
			MW.sm.createSound({id:this.files[0].alias,url:MW.path_sounds + this.files[0].filename, autoLoad: true, onload: MW.loader.next});
			return true;
		}
		else {
			MW.log('Loader: no file in queue!');
			return false;
		}
	},
	
	next: function() {
		if(MW.loader.status.current + 1 < MW.loader.status.total) {
			MW.loader.status.current++;
			MW.sm.createSound({id:MW.loader.files[MW.loader.status.current].alias,url:MW.path_sounds + MW.loader.files[MW.loader.status.current].filename, autoLoad: true, onload: MW.loader.next});
		}
		else {
			MW.log('Loader: all files loaded.');
			window.setTimeout(MW.loader.callback, 1);
		}
	},
	
	getStatus: function() {
		return this.status;
	}
};

MW.sound = {
	play: function(alias) {
		MW.sm.play(alias, {volume: 100});
	},
	
	stop: function(alias) {
		MW.sm.stop(alias);
	},
	
	startLoop: function(alias, volume) {
		MW.sm.play(alias, {volume: volume, onfinish: function() { MW.sound.startLoop(alias, volume); }});
	},
	
	stopLoop: function(alias) {
		MW.sm.stop(alias);
	}
};

MW.menu = {
	items: [],
	status: {'current':-1, 'total': 0},
	
	init: function() {
		MW.menu.status.current = -1;
		MW.menu.status.total = 0;
		
		MW.game.level = 0;
		
		MW.input.clear();
		MW.input.setlock();
		MW.input.add({'code':Event.KEY_UP, 'action': 'MW.menu.next(-1);'});
		MW.input.add({'code':Event.KEY_DOWN, 'action': 'MW.menu.next(1);'});
		MW.input.add({'code':Event.KEY_RIGHT, 'action': 'MW.menu.run();'});
		
		MW.menu.add({'title':'Welcome', 'sound': 'welcome', 'type':'label'});
		MW.menu.add({'title':'Play', 'sound': 'play', 'type':'action', 'action':'MW.sound.stopLoop(\'menu_music\');MW.game.init();'});
		MW.menu.add({'title':'Rules', 'sound': 'rules', 'type':'action', 'action':'MW.menu.rules();'});
		MW.menu.add({'title':'Quit', 'sound': 'quit', 'type':'action', 'action':'MW.sound.stopLoop(\'menu_music\');MW.input.clear();'});
		
		MW.menu.start();
		
		/*
		
			You are a robot in an arena. Your mission is to found your enemi before he attack you. Use arrows keys on your keyword to move. TOP and BOTTOM will move forward and backward, LEFT and RIGHT will change your orientation.
			Use your radar to locate your ennemi, it's a periodic sound in stereo. Tips: if you go to the right direction footstep sound is louder.
			Warning, you ennemi attack you ! He will play some sounds, at the end, use LEFT and RIGHT keys to reproduce the same melody and defend yourself. 
		
		*/
	},
	
	start: function() {
		MW.sound.startLoop('menu_music', 60);
		MW.menu.next(1);
	},
	
	next: function(inc) {
		if(-1 == MW.menu.status.current) {
			MW.menu.status.current = 0;
			MW.sm.play(MW.menu.items[MW.menu.status.current].sound, {volume: 100, onfinish: function() { MW.menu.next(1); }});
		}
		else {
			if((MW.menu.status.current + inc) % MW.menu.status.total >= 0) {
				MW.menu.status.current = (MW.menu.status.current + inc) % MW.menu.status.total;
			}
			else {
				MW.menu.status.current = MW.menu.status.total - 1;
			}
			
			if('action' == MW.menu.items[MW.menu.status.current].type) {
				MW.sm.play(MW.menu.items[MW.menu.status.current].sound, {volume: 100, onfinish: function() { MW.input.unlock(); }});
			}
			else {
				MW.menu.next(inc);
			}
		}
	},
	
	run: function() {
		MW.sm.play(MW.menu.items[MW.menu.status.current].sound, {volume: 100, onfinish: function() { window.setTimeout(MW.menu.items[MW.menu.status.current].action, 0); }});
	},
	
	add: function(item) {
		this.status.total++;
		this.items[this.items.length] = item;
	},
	
	rules: function() {
		MW.sm.play('fullrules', {volume: 100, onfinish: function() { MW.sm.play('fullrules2', {volume: 100, onfinish: function() { MW.menu.init(); }}); }});
	}
};

MW.game = {
	status: {'online': true},
	frequency: 1500,
	level: 0,
	list: [],
	list_current: 0,
	
	init: function() {
		MW.input.clear();
		MW.input.setlock();
		MW.input.add({'code':Event.KEY_UP, 'action': 'MW.player.tryMove(1);'});
		MW.input.add({'code':Event.KEY_DOWN, 'action': 'MW.player.tryMove(-1);'});
		MW.input.add({'code':Event.KEY_LEFT, 'action': 'MW.player.turn(-90);'});
		MW.input.add({'code':Event.KEY_RIGHT, 'action': 'MW.player.turn(90);'});
		
		MW.menu.add({'title':'Welcome', 'sound': 'welcome', 'type':'label'});
		MW.menu.add({'title':'Play', 'sound': 'play', 'type':'action', 'action':'MW.game.init();'});
		MW.menu.add({'title':'Rules', 'sound': 'rules', 'type':'action'});
		MW.menu.add({'title':'Quit', 'sound': 'quit', 'type':'action'});
		
		MW.sound.startLoop('game_music', 60);
		MW.game.level = 0;
		MW.game.start();
	},
	
	start: function() {
		MW.map.init();
		MW.player.init();
		MW.ia.init();
		
		MW.game.level++;
		this.status.online = true;
		MW.input.unlock();
		
		if(10 <= MW.game.level) {
			MW.game.stop();
			MW.sm.play('wins', {volume: 100, onfinish: function() { MW.menu.init(); }});
		}
		else {
			// prepare attack
			window.setTimeout('MW.game.attack(\''+MW.game.level+'\');', 10000 + ((10 - MW.game.level) * 2000));
			MW.game.loop();
		}
	},
	
	restart: function() {
		this.status.online = true;
		MW.input.clear();
		MW.input.add({'code':Event.KEY_UP, 'action': 'MW.player.tryMove(1);'});
		MW.input.add({'code':Event.KEY_DOWN, 'action': 'MW.player.tryMove(-1);'});
		MW.input.add({'code':Event.KEY_LEFT, 'action': 'MW.player.turn(-90);'});
		MW.input.add({'code':Event.KEY_RIGHT, 'action': 'MW.player.turn(90);'});
		MW.input.unlock();
		window.setTimeout('MW.game.attack(\''+MW.game.level+'\');', 10000 + ((10 - MW.game.level) * 2000));
		MW.sound.startLoop('game_music', 60);
		MW.game.loop();
	},
	
	attack: function(level) {
		if(level == MW.game.level) {
			MW.game.stop();
			MW.input.setlock();
			MW.sm.play('attack', {volume: 100, onfinish: function() { MW.game.attack_gen(); }});
		}
	},
	
	attack_gen: function() {
		MW.game.list = [];
		MW.game.list_current = 0;
		for(var i=0 ; i<MW.game.level + 1 ; i++) {
			MW.game.list[MW.game.list.length] = Math.round(Math.random() * 1);
		}
		MW.game.attack_play();
	},
	
	attack_play: function() {
		if(MW.game.list_current >= MW.game.list.length) {
			MW.game.attack_listen();
		}
		else {
			var value = MW.game.list[MW.game.list_current];
			if(0 == value) {
				MW.sm.play('left', {volume: 100, pan: -100, onfinish: function() { MW.game.attack_play(); }});
			}
			else {
				MW.sm.play('right', {volume: 100, pan: 100, onfinish: function() { MW.game.attack_play(); }});
			}
			MW.game.list_current++;
		}
	},
	
	attack_listen: function() {
		MW.game.list_current = 0;
		MW.input.clear();
		MW.input.add({'code':Event.KEY_LEFT, 'action': 'MW.game.attack_reply(0);'});
		MW.input.add({'code':Event.KEY_RIGHT, 'action': 'MW.game.attack_reply(1);'});
		MW.input.unlock();
	},
	
	attack_reply: function(value) {
		if(0 == value) {
			MW.sm.play('left', {volume: 100, pan: -100, onfinish: function() { MW.game.attack_reply2(0); }});
		}
		else {
			MW.sm.play('right', {volume: 100, pan: 100, onfinish: function() { MW.game.attack_reply2(1); }});
		}
	},
	
	attack_reply2: function(value) {
		if(value == MW.game.list[MW.game.list_current]) {
			if(MW.game.list_current + 1 >= MW.game.list.length) {
				// player defend himself :)
				MW.game.restart();
			}
			else {
				MW.game.list_current++;
				MW.input.unlock();
			}
		}
		else {
			// gameover
			MW.sm.play('gameover', {volume: 100, onfinish: function() { MW.menu.init(); }});
		}
	},
	
	loop: function() {
		var distance = MW.player.distance(MW.ia.position.x, MW.ia.position.y);
		var volume = 100 - distance;
		var orientation = MW.player.orientation(MW.ia.position.x, MW.ia.position.y);
		var pan = 0;
		
		MW.game.frequency = (((distance) * 1000) / 100) + 500;
		
		if(0 == MW.player.position.angle) {
			pan = orientation.x * 100;
		}
		else if(90 == MW.player.position.angle) {
			pan = orientation.y * 100;
		}
		else if(180 == MW.player.position.angle) {
			pan = orientation.x * (-100);
		}
		else {
			pan = orientation.y * (-100);
		}
		
		MW.sm.play('bip', {volume: volume, pan:pan});
		
		MW.log(MW.player.distance(MW.ia.position.x, MW.ia.position.y));
		
		MW.map.display();
		
		if(true == this.status.online) {
			window.setTimeout('MW.game.loop();', MW.game.frequency);
		}
	},
	
	stop: function() {
		MW.sound.stopLoop('game_music');
		this.status.online = false;
	}
};

MW.player = {
	position: {'x':0, 'y':0, angle:'0'},
	
	init: function() {
		this.position.angle = 0;
		this.position.x = Math.floor(Math.random() * (MW.map.width));
		this.position.y = Math.floor(Math.random() * (MW.map.height));
	}, 
	
	compare: function(x, y) {
		if(x == this.position.x && y == this.position.y) {
			return true;
		}
		return false;
	},
	
	distance: function(x, y) {
		var distance = Math.sqrt(Math.pow((x - this.position.x), 2)
			         + Math.pow((y - this.position.y), 2));
		return (100 * distance) / MW.map.max;
	},
	
	orientation: function(x, y) {
		var result = {'x':'', 'y':''};
		
		//result.x = (x - this.position.x) / MW.map.max * 100; 
		//result.y = (this.position.y - y) / MW.map.max * 100; 
		
		if(x < this.position.x) {
			result.x = -1;
		}
		else if (x > this.position.x) {
			result.x = 1;
		}
		else {
			result.x = 0;
		}
		
		if(y < this.position.y) {
			result.y = 1;
		}
		else if(y > this.position.y) {
			result.y = -1;
		}
		else {
			result.y = 0;
		}
		
		return result;
	},
	
	tryMove: function(direction) {
		var x, y;
		var distance1, distance2;
		
		if(0 == MW.player.position.angle) {
			x = MW.player.position.x;
			y = MW.player.position.y - direction;
		}
		else if(90 == MW.player.position.angle) {
			x = MW.player.position.x + direction;
			y = MW.player.position.y;
		}
		else if(180 == MW.player.position.angle) {
			x = MW.player.position.x;
			y = MW.player.position.y + direction;
		}
		else {
			x = MW.player.position.x - direction;
			y = MW.player.position.y;
		}
		
		if(MW.player.move(x, y)) {
			MW.map.setPlayer(MW.player.position.x, MW.player.position.y, x, y);
			distance1 = MW.player.distance(MW.ia.position.x, MW.ia.position.y);
			MW.player.position.x = x;
			MW.player.position.y = y;
			distance2 = MW.player.distance(MW.ia.position.x, MW.ia.position.y);
			
			if(distance1 > distance2) {
				MW.sound.play('step1');
			}
			else {
				MW.sound.play('step2');
			}
			
			if(MW.player.compare(MW.ia.position.x, MW.ia.position.y)) {
				MW.sm.play('thunder', {volume: 100, onfinish: function() { MW.sound.play('levelup'); MW.game.start(); }});
				MW.game.stop();
			}
		}
		else {
			MW.sound.play('pok');
		}
		MW.input.unlock();
	},
	
	move: function(x, y) {
		var result = true;
		if(x < 0 || x >= MW.map.width) {
			result = false;
		}
		else if(y < 0 || y >= MW.map.height) {
			result = false;
		}
		return result;
	},
	
	turn: function(angle) {
		if((MW.player.position.angle + angle) % 360 < 0) {
			MW.player.position.angle = 270;
		}
		else {
			MW.player.position.angle = (MW.player.position.angle + angle) % 360;
		}
		
		if(90 == angle) {
			MW.sm.play('step1', {volume: 100, pan:100});
		}
		else {
			MW.sm.play('step1', {volume: 100, pan:-100});
		}
		//window.setTimeout('MW.sm.play(\'step1\');', 500);
		MW.input.unlock();
	}
};

MW.ia = {
	position: {'x':0, 'y':0},
	
	init: function() {
		this.position.x = Math.floor(Math.random() * (MW.map.width));
		this.position.y = Math.floor(Math.random() * (MW.map.height));
		
		// position user must be != position ia
		while(MW.player.compare(this.position.x, this.position.y)) {
			this.position.x = Math.floor(Math.random() * (MW.map.width));
			this.position.y = Math.floor(Math.random() * (MW.map.height));
		}
		
		MW.map.setIa(this.position.x, this.position.y);
	}, 
	
	compare: function(x, y) {
		if(x == this.position.x && y == this.position.y) {
			return true;
		}
		return false;
	},
	
	distance: function(x, y) {
		var distance = Math.sqrt(Math.pow((x - this.position.x), 2)
			         + Math.pow((y - this.position.y), 2));
		return (100 * distance) / MW.map.max;
	}
};

MW.map = {
	width: 20,
	height: 20,
	matrix: [],
	max: 0,
	
	init: function() {
		var matrix = [];
		for(var i=0;i<this.width;i++) {
			matrix[i] = [];
			for(var j=0;j<this.width;j++) {
				matrix[i][j] = 0;
			}
		}
		this.max = Math.sqrt(Math.pow(this.width, 2) + Math.pow(this.height, 2));
		this.matrix = matrix;
	},
	
	setPlayer: function(old_x, old_y, new_x, new_y) {
		this.matrix[old_y][old_x] = '0';
		this.matrix[new_y][new_x] = 'P';
	},
	
	setIa: function(x, y) {
		this.matrix[y][x] = 'X';
	},
	
	display: function() {
		var buffer = '<table><tr>';
		for(var i=0;i<this.width;i++) {
			for(var j=0;j<this.width;j++) {
				if(0 == this.matrix[i][j]) {
					var item = '&nbsp;';
				}
				else {
					var item = this.matrix[i][j];
				}
				buffer += '<td>' + item + '</td>';
			}
			buffer += "</tr>";
		}
		buffer += '</table>';
		$('ts_map').update(buffer);
	}
};

MW.input = {
	keys: [],
	lock: false,
	
	init: function() {
		Event.observe(document, 'keypress', MW.input.catchkey);
	},
	
	add: function(key) {
		this.keys[this.keys.length] = key;
	},
	
	clear: function() {
		this.keys = [];
	},
	
	catchkey: function(e) {
		var found = false;
		
		if(false == MW.input.lock) {
			MW.input.lock = true;
			
			// unicode
			var unicode;
			if (!e) var e = window.event;
			if (e.keyCode) unicode = e.keyCode;
			else if (e.which) unicode = e.which;
			
			MW.input.keys.each(function(key) {
				if(unicode == key.code) {
					found = true;
					MW.log(key.action);
					window.setTimeout(key.action, 1);
				}
			});
			
			if(false == found) {
				MW.input.unlock();
			}
		}
	},
		
	setlock: function () {
		MW.input.lock = true;
	},
		
	unlock: function () {
		MW.input.lock = false;
	}
};
	
// SoundManager2 & MW loader
soundManager.onload = function() {
  MW.init(soundManager);
}
