//Copyright (C) Ben Parbury - All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited. Written by Ben Parbury <ben@gridlockinteractive.com> 2014
var gSounds = new Sounds();
var gMusic = new Music();

function SoundDefinition(name, sound, instances, loop)
{
	this.name = name;
	this.sound = sound;
	this.loop = loop;
	this.instances = new Array(instances);
	this.nextInstance = 0;
	for(var i = 0; i < instances; i++)
	{
		this.instances[i] = new buzz.sound(sound);
	}
	
	var framesBetweenPlays = 2;
	this.framesBetweenPlays = framesBetweenPlays;
	this.framesSinceLastPlayed = framesBetweenPlays;
	
	this.ShouldPlay = function(instance, fraction, duringRewind)
	{
		if(this.framesSinceLastPlayed >= this.framesBetweenPlays)
		{
			if(!gUndoSystem.IsUndoing() || duringRewind)
			{
				return true;
			}
		}
		return false;
	}
	
	this.Played = function(instance)
	{
		this.framesSinceLastPlayed = 0;
	}
	
	this.Update = function()
	{
		if(this.framesSinceLastPlayed < this.framesBetweenPlays)
		{
			this.framesSinceLastPlayed++;
		}
	}
	
	this.SetVolume = function(volume)
	{
		for(var i = 0; i < this.instances.length; i++)
		{
			this.instances[i].setVolume(volume);
		}
	}
	
	this.GetInstance = function(object)
	{
		var instance = this.instances[this.nextInstance];

		if(instance.object)
		{
			instance.object.Unbind(instance);
		}
		
		object.Bind(instance)
		
		this.nextInstance = (this.nextInstance + 1) % this.instances.length;
		return instance;
	}
	
	this.GetObject = function()
	{
		return new SoundObject(this);
	}
}

function SoundInstance(sound)
{
	this.sound = new buzz.sound(sound);
	this.object = null;
}

function SoundObject(def)
{
	this.def = def;
	this.playing = false;
	this.sound = null;
	
	this.Play = function(fraction, duringRewind)
	{
		if(this.def.ShouldPlay(this, fraction, duringRewind))
		{
			var instance = this.def.GetInstance(this);
			if(instance)
			{
				instance.setVolume(gSounds.volume);
				if(fraction)
				{
					var duration = instance.getDuration();
					instance.setTime(duration * fraction);
					instance.play();
				}
				instance.play();
				if(this.def.loop)
				{
					instance.loop();
				}
				this.playing = true;
				this.def.Played(this);
			}
		}
	}
	
	this.Bind = function(instance)
	{
		instance.bind("playing",
			function(e)
			{
				this.playing = true;
				gConsole.Log(11, "[SND] Started " + this.def.name)
			}.bind(this)
		);
		
		if(!this.def.loop)
		{
			instance.bind("ended abort pause",
				function(e)
				{
					this.playing = false;
					this.sound = null
					gConsole.Log(11, "[SND] Stopped " + this.def.name)
				}.bind(this)
			);
		}
		instance.object = this;
		this.sound = instance;
	}
	
	this.Unbind = function(instance)
	{
		this.Stop();
		
		instance.unbind("playing");
		
		if(!this.def.loop)
		{
			instance.unbind("ended abort pause");
		}
		instance.object = null;
		this.sound = null;
	}
	
	this.IsPlaying = function()
	{
		return this.playing;
	}
	
	this.Stop = function()
	{
		if(this.sound)
		{
			this.sound.stop();
		}
		if(this.def.loop)
		{
			this.playing = false;
			this.sound = null
		}
	}
}

function Sounds()
{
	var volume = 50;
	var prevVolume = gStorage.getItem("options", "sound", "volume");
	if(prevVolume)
	{
		volume = parseInt(prevVolume);
	}
	this.volume = volume;
	this.defs = new Array();
	
	this.AddDefinition = function(def)
	{
		this.defs.push(def);
	}
	
	this.Get = function(name)
	{
		for(var i = 0; i < this.defs.length; i++)
		{
			if(this.defs[i].name == name)
			{
				return this.defs[i].GetObject();
			}
		}
		
		return null;
	}
	
	this.Update = function()
	{
		for(var i = 0; i < this.defs.length; i++)
		{
			this.defs[i].Update();
		}
	}

	this.SetVolume = function(volume)
	{
		gStorage.setItem("options", "sound", "volume", volume);
		this.volume = volume;
		for(var i = 0; i < this.defs.length; i++)
		{
			this.defs[i].SetVolume(volume);
		}
	}
	
	this.ChangeVolume = function(deltaVolume)
	{
		var newVolume = Math.min(Math.max(this.volume + deltaVolume, 0), 100);
		gStorage.setItem("options", "sound", "volume", newVolume);
		this.SetVolume(newVolume);
	}
}

function MusicTrack(filename, title, author)
{
	this.sound = new buzz.sound(filename, { preload: false });
	this.title = title;
	this.author = author;
	
	this.Play = function()
	{
		gConsole.Log(11, "[MSC] Play Music");
		//this.sound.setTime(0); //Stops music from playing in Firefox
		this.sound.setVolume(gMusic.volume);
		this.sound.play();
	}
	
	this.Stop = function()
	{
		gConsole.Log(11, "[MSC] Stop Music");
		this.sound.stop();
	}
	
	this.IsEnded = function()
	{
		return this.sound.isEnded();
	}
	
	this.SetVolume = function(volume)
	{
		this.sound.setVolume(volume);
	}
	
	this.GetTime = function()
	{
	return this.sound.getTime();
	}
	
	this.SetTime = function(time)
	{
	this.sound.setTime(time);
	}
	
}

function Music()
{
	var volume = 50;
	var prevVolume = gStorage.getItem("options", "music", "volume");
	if(prevVolume)
	{
		volume = parseInt(prevVolume);
	}
	this.volume = volume;
	this.playingIndex = null;
	this.tracks = new Array();
	
	this.AddTrack = function(track)
	{
		this.tracks.push(track);
	}
	
	this.PrevTrack = function()
	{
		if(this.playingIndex != null)
		{
			this.tracks[this.playingIndex].Stop();
			var prevTrack = (this.playingIndex - 1);
			if(prevTrack == -1)
			{
				prevTrack = this.tracks.length - 1;
			}
			this.PlayTrack(prevTrack);
		}
		else
		{
			this.PlayTrack(0);
		}
	}

	this.NextTrack = function()
	{
		if(this.playingIndex != null)
		{
			this.tracks[this.playingIndex].Stop();
			this.PlayTrack((this.playingIndex + 1) % this.tracks.length);
		}
		else
		{
			this.PlayTrack(0);
		}
	}
	
	this.PlayTrack = function(index)
	{
		this.playingIndex = index;
		this.tracks[this.playingIndex].Play();
	}
	
	this.GetTrack = function()
	{
		return this.tracks[this.playingIndex];
	}
	
	this.Update = function()
	{
		if(this.playingIndex != null)
		{
			if(this.tracks[this.playingIndex].IsEnded())
			{
				this.NextTrack();
			}
		}
	}
	
	this.SetVolume = function(volume)
	{
		gStorage.setItem("options", "music", "volume", volume);
		this.volume = volume;
		this.tracks[this.playingIndex].SetVolume(volume);
	}

	this.ChangeVolume = function(deltaVolume)
	{
		var newVolume = Math.min(Math.max(this.volume + deltaVolume, 0), 100);
		gStorage.setItem("options", "music", "volume", newVolume);
		this.SetVolume(newVolume);
	}
}

gSounds.AddDefinition(new SoundDefinition("teleport", "data/sounds/teleport", 1));
gSounds.AddDefinition(new SoundDefinition("teleportIn", "data/sounds/teleportIn", 1));
gSounds.AddDefinition(new SoundDefinition("deleting", "data/sounds/blockDeleting", 5));
gSounds.AddDefinition(new SoundDefinition("deleted", "data/sounds/blockDeleted", 3));
gSounds.AddDefinition(new SoundDefinition("slideLoop", "data/sounds/blockSlideLoop", 5, true));
gSounds.AddDefinition(new SoundDefinition("switchSlideLoop", "data/sounds/blockSwitchSlideLoop", 5, true));
gSounds.AddDefinition(new SoundDefinition("slideStart", "data/sounds/blockSlideStart", 1));
gSounds.AddDefinition(new SoundDefinition("slideStop", "data/sounds/blockSlideStop", 1));
gSounds.AddDefinition(new SoundDefinition("transition", "data/sounds/transition", 2));
gSounds.AddDefinition(new SoundDefinition("complete1", "data/sounds/complete1", 1));
gSounds.AddDefinition(new SoundDefinition("complete2", "data/sounds/complete2", 1));
gSounds.AddDefinition(new SoundDefinition("complete3", "data/sounds/complete3", 1));
gSounds.AddDefinition(new SoundDefinition("menuHighlight", "data/sounds/menuHighlight", 5));
gSounds.AddDefinition(new SoundDefinition("menuSelect", "data/sounds/menuSelect", 5));
gSounds.AddDefinition(new SoundDefinition("hint", "data/sounds/hint", 2));
gSounds.AddDefinition(new SoundDefinition("undo", "data/sounds/undo", 1));
gSounds.AddDefinition(new SoundDefinition("starHit1", "data/sounds/starHit1", 1));
gSounds.AddDefinition(new SoundDefinition("starHit2", "data/sounds/starHit2", 1));
gSounds.AddDefinition(new SoundDefinition("starHit3", "data/sounds/starHit3", 1));
gSounds.AddDefinition(new SoundDefinition("pauseClose", "data/sounds/pauseClose", 1));
gSounds.AddDefinition(new SoundDefinition("pauseOpen", "data/sounds/pauseOpen", 1));
gSounds.AddDefinition(new SoundDefinition("playerMoveStart", "data/sounds/playerMoveStart", 1));
gSounds.AddDefinition(new SoundDefinition("playerMoveLoop", "data/sounds/playerMoveLoop", 1, true));
gSounds.AddDefinition(new SoundDefinition("playerMoveStop", "data/sounds/playerMoveStop", 1));


gMusic.AddTrack(new MusicTrack("data/music/poly_music_07", "Orchid", "Graeme Norgate"));
gMusic.AddTrack(new MusicTrack("data/music/poly_music_05", "Morph", "Graeme Norgate"));
if(!gDemo)
{
	gMusic.AddTrack(new MusicTrack("data/music/poly_music_04", "Work", "Graeme Norgate"));
	gMusic.AddTrack(new MusicTrack("data/music/poly_music_01", "Poly", "Ross Tregrenza"));
	gMusic.AddTrack(new MusicTrack("data/music/poly_music_08", "Funkic", "Ross Tregrenza"));
	gMusic.AddTrack(new MusicTrack("data/music/poly_music_02", "Glee", "Graeme Norgate"));
	gMusic.AddTrack(new MusicTrack("data/music/poly_music_03", "Ditty", "Graeme Norgate"));
	gMusic.AddTrack(new MusicTrack("data/music/poly_music_06", "A Different Dream", "Ross Tregrenza"));
}