package com.kangacult.octogone;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Audio {

	/**
	 * Static Variables
	 */
	
//	public static final int MAX_LOOP_SOUNDS = 10;
	
	//public static final float MAX_PLAYER_HEARING = 
	
	/**
	 * Private variables
	 */

	private Random random = new Random();
	private Vector3 playerPosition = new Vector3();
	private Vector3 soundPosition = new Vector3();
	private List<Sound> soundList = new ArrayList<Sound>();
	
//	private long[] soundIds = new long[MAX_LOOP_SOUNDS];
//	private Vector3[] soundPositions = new Vector3[MAX_LOOP_SOUNDS];
//	private Sound[] soundRef = new Sound[MAX_LOOP_SOUNDS];

	
	/**
	 * Public variables
	 */

	public enum SoundType {
		PLAYER_WATERTHROW, PLAYER_JUMPIMPACT, PLAYER_GRUNT, PLAYER_DEATH, PLAYER_WATERREFILL, PLAYER_FOOTSTEP, ENEMY_FIREBALL, ENEMY_DEATH, ENEMY_GROWL, OPENING_LINE, WAVE_START
	}

	public Sound[] playerWaterThrows;
	public Sound[] playerJumpImpacts;
	public Sound[] playerGrunts;
	public Sound[] playerDeaths;
	public Sound[] playerWaterRefills;
	public Sound[] playerFootsteps;
	public Sound[] enemyFireballs;
	public Sound[] enemyDeaths;
	public Sound[] enemyGrowls;
	public Sound[] openingLine;
	public Sound[] waveStarts;

	
//	public enum LoopType {FOUNTAIN_LOOP,FIRE_LOOP}
//	
//	public Sound[] fountainLoops;
//	public Sound[] fireLoops;
	
	public Music[] musics;
	public Music currentMusic;
	
	public float unpauseTime = 0f;
	
	public float playerMaxHearing = 50f;
	
	public void init(){
		
		playerWaterThrows = new Sound[1];
		//playerWaterThrows[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Water_Throw_1.ogg")); //old
		playerWaterThrows[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Water_Throw_2_Short.ogg")); //made by jhart and andrew
		//playerWaterThrows[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Water_Throw_2_Medium.ogg")); //made by jhart and andrew
		//playerWaterThrows[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Water_Throw_2_Long.ogg")); //made by jhart and andrew

		
		playerJumpImpacts = new Sound[0];
		
		playerGrunts = new Sound[15];
		playerGrunts[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-01.ogg"));
		playerGrunts[1] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-02.ogg"));
		playerGrunts[2] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-03.ogg"));
		playerGrunts[3] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-04.ogg"));
		playerGrunts[4] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-05.ogg"));
		playerGrunts[5] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-06.ogg"));
		playerGrunts[6] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-07.ogg"));
		playerGrunts[7] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-08.ogg"));
		playerGrunts[8] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-12.ogg"));
		playerGrunts[9] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-13.ogg"));
		playerGrunts[10] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-14.ogg"));
		playerGrunts[11] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-15.ogg"));
		playerGrunts[12] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-16.ogg"));
		playerGrunts[13] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-17.ogg"));
		playerGrunts[14] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Battlecry_Grunt-18.ogg"));

		playerDeaths = new Sound[5];
		playerDeaths[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Death_1.ogg"));
		playerDeaths[1] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Death_2.ogg"));
		playerDeaths[2] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Death_3.ogg"));
		playerDeaths[3] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Death_4.ogg"));
		playerDeaths[4] = Gdx.audio.newSound(Gdx.files.internal("audio/Female_Death_5.ogg"));

		playerWaterRefills = new Sound[1];
		//playerWaterRefills[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Water_Refill_1.ogg"));
		playerWaterRefills[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Water_Refill_2.ogg"));

		playerFootsteps = new Sound[1];
		//playerFootsteps[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Footstep_1.ogg"));
		//playerFootsteps[1] = Gdx.audio.newSound(Gdx.files.internal("audio/Footstep_2.ogg"));
		//playerFootsteps[2] = Gdx.audio.newSound(Gdx.files.internal("audio/Footstep_3.ogg"));
		playerFootsteps[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Footstep_4.ogg"));
		
//		fountainLoops = new Sound[1];		
//		fountainLoops[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Fountain_Loop_1.ogg"));
//		
//		fireLoops = new Sound[1];		
//		fireLoops[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Fire_Burning_Loop_1.ogg"));
		
		enemyFireballs = new Sound[4];
		enemyFireballs[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Fireball_1_Quieter.ogg"));
		enemyFireballs[1] = Gdx.audio.newSound(Gdx.files.internal("audio/Fireball_2_Quieter.ogg"));
		enemyFireballs[2] = Gdx.audio.newSound(Gdx.files.internal("audio/Fireball_3_Quieter.ogg"));
		enemyFireballs[3] = Gdx.audio.newSound(Gdx.files.internal("audio/Fireball_4_Quieter.ogg"));

		
		enemyDeaths = new Sound[1]; //I am not sure if both of these sounds belong together...
		enemyDeaths[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Put_Out_Fire_1.ogg"));


		
		enemyGrowls = new Sound[1]; //one type of enemy should only have one growl as to not confuse the player
		//enemyGrowls[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Growl_1.ogg"));
		//enemyGrowls[1] = Gdx.audio.newSound(Gdx.files.internal("audio/Growl_2.ogg"));
		enemyGrowls[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Growl_3.ogg"));
		//enemyGrowls[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Growl_4.ogg"));
		
		openingLine = new Sound[6];
		openingLine[0] = Gdx.audio.newSound(Gdx.files.internal("audio/WhereAmI_1.ogg"));
		openingLine[1] = Gdx.audio.newSound(Gdx.files.internal("audio/WhereAmI_2.ogg"));
		openingLine[2] = Gdx.audio.newSound(Gdx.files.internal("audio/WhereAmI_3.ogg"));
		openingLine[3] = Gdx.audio.newSound(Gdx.files.internal("audio/WhereAmI_4.ogg"));
		openingLine[4] = Gdx.audio.newSound(Gdx.files.internal("audio/WhereAmI_5.ogg"));
		openingLine[5] = Gdx.audio.newSound(Gdx.files.internal("audio/WhereAmI_6.ogg"));

		waveStarts = new Sound[15]; 
		//waveStarts[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Growl_4.ogg"));
		waveStarts[0] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-03.ogg"));
		waveStarts[1] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-04.ogg"));
		waveStarts[2] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-07.ogg"));
		waveStarts[3] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-14.ogg"));
		waveStarts[4] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-15.ogg"));
		waveStarts[5] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-18.ogg"));
		waveStarts[6] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-19.ogg"));
		waveStarts[7] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-2-1.ogg"));
		waveStarts[8] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-2-2.ogg"));
		waveStarts[9] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-22.ogg"));
		waveStarts[10] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-23.ogg"));
		waveStarts[11] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-24.ogg"));
		waveStarts[12] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-25.ogg"));
		waveStarts[13] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-27.ogg"));
		waveStarts[14] = Gdx.audio.newSound(Gdx.files.internal("audio/Wave_Start-30.ogg"));

		
		for (Sound s: playerWaterThrows){
			soundList.add(s);
		}
		for (Sound s: playerJumpImpacts){
			soundList.add(s);
		}
		for (Sound s: playerGrunts){
			soundList.add(s);
		}
		for (Sound s: playerDeaths){
			soundList.add(s);
		}
		for (Sound s: playerWaterRefills){
			soundList.add(s);
		}
		for (Sound s: playerFootsteps){
			soundList.add(s);
		}
		for (Sound s: enemyFireballs){
			soundList.add(s);
		}
		for (Sound s: enemyDeaths){
			soundList.add(s);
		}
		for (Sound s: enemyGrowls){
			soundList.add(s);
		}
		for (Sound s: openingLine){
			soundList.add(s);
		}
		for (Sound s: waveStarts){
			soundList.add(s);
		}
		
		musics = new Music[1];
		musics[0] = Gdx.audio.newMusic(Gdx.files.internal("audio/Music_1_Shamanistic.ogg"));
		currentMusic = musics[0];

		/**
		 * Play Music...
		 */
		currentMusic.setVolume(1.0f);
		currentMusic.setLooping(true);
		currentMusic.play();
		

	}
	
	public void update(float elapsedTime){
		
		if (unpauseTime > 0f) {
			unpauseTime -= elapsedTime;
			if (currentMusic.isPlaying()) currentMusic.stop();
		}
		else if (!currentMusic.isPlaying()) currentMusic.play();
	}
	
	public void pauseMusicAndStopSound(float pauseTime){
		unpauseTime = pauseTime;
		for (Sound s : soundList){
			s.stop();
		}
	}
	

	public void playSound(SoundType type, Vector3 playerPosition, Vector3 playerDirection, Vector3 soundPosition){
		playSound(type, playerPosition, playerDirection, soundPosition, 1.0f, false);
	}
	
	public void playSound(SoundType type, Vector3 playerPosition, Vector3 playerDirection, Vector3 soundPosition, boolean ignoreSoundPause){
		playSound(type, playerPosition, playerDirection, soundPosition, 1.0f, ignoreSoundPause);
	}
	
	public void playSound(SoundType type, Vector3 playerPosition, Vector3 playerDirection, Vector3 soundPosition, float pitch, boolean ignoreSoundPause){
		if (unpauseTime > 0f && !ignoreSoundPause) {
			return;
		}
		
		long soundId = -1;
		Sound soundRef = null;
		switch(type){
		case PLAYER_WATERTHROW:
			soundRef = playerWaterThrows[random.nextInt(playerWaterThrows.length)];
			break;
		case PLAYER_JUMPIMPACT:
			soundRef = playerJumpImpacts[random.nextInt(playerJumpImpacts.length)];
			break;
		case PLAYER_GRUNT:
			soundRef = playerGrunts[random.nextInt(playerGrunts.length)];
			break;
		case PLAYER_DEATH:
			soundRef = playerDeaths[random.nextInt(playerDeaths.length)];
			break;
		case PLAYER_WATERREFILL:
			soundRef = playerWaterRefills[random.nextInt(playerWaterRefills.length)];
			break;
		case PLAYER_FOOTSTEP:
			soundRef = playerFootsteps[random.nextInt(playerFootsteps.length)];
			break;
		case ENEMY_FIREBALL:
			soundRef = enemyFireballs[random.nextInt(enemyFireballs.length)];
			break;
		case ENEMY_DEATH:
			soundRef = enemyDeaths[random.nextInt(enemyDeaths.length)];
			break;
		case ENEMY_GROWL:
			soundRef = enemyGrowls[random.nextInt(enemyGrowls.length)];
			break;
		case OPENING_LINE:
			soundRef = openingLine[random.nextInt(openingLine.length)];
			break;
		case WAVE_START:
			soundRef = waveStarts[random.nextInt(waveStarts.length)];
			break;
		default:
			break;
		
		}
		
		if (soundRef == null) return;
		
		soundId = soundRef.play();
		
		if (soundId < 0) return;

		soundRef.setPitch(soundId, pitch);
		setVolumeAndPan(soundRef, soundId, playerPosition, playerDirection, soundPosition);
	}
	
	private void setVolumeAndPan(Sound soundRef, long soundId, Vector3 playerPosition, Vector3 playerDirection, Vector3 soundPosition){
		if (soundRef==null) return;
		if (soundId<0) return;
		
		float distance = playerPosition.dst(soundPosition);
		float normalizedVolume = (playerMaxHearing - distance) / playerMaxHearing;
		normalizedVolume = (float) Math.pow(normalizedVolume, 1.6f);
		
		//soundRef.setVolume(soundId, normalizedVolume);
		//playerPosition.sub(soundPosition);
		//Vector3 soundHeading = playerPosition.sub(soundPosition);
		this.playerPosition.x = playerPosition.x;
		this.playerPosition.y = playerPosition.y;
		this.playerPosition.z = playerPosition.z;
		
		this.soundPosition.x = soundPosition.x;
		this.soundPosition.y = soundPosition.y;
		this.soundPosition.z = soundPosition.z;
		
		Vector3 soundHeading = this.soundPosition.sub(this.playerPosition);
		//Vector3 soundHeading = this.playerPosition.sub(this.soundPosition);
		
		float soundDirection = ((MathUtils.atan2(soundHeading.x, soundHeading.y) * MathUtils.radiansToDegrees) + 360) % 360;
		float forwardDirection = ((MathUtils.atan2(playerDirection.x, playerDirection.y) * MathUtils.radiansToDegrees) + 360) % 360;
		
		//System.out.println("SoundDirection = " +  soundDirection);
		//System.out.println("ForwardDirection = " + forwardDirection);
//		
		float angleDelta = soundDirection - forwardDirection;
		
		//System.out.println("Angle Delta" + angleDelta);

		
		if(angleDelta<-180) angleDelta+=360f;
		if(angleDelta>=180) angleDelta-=360f;
		
		//System.out.println("Angle Delta " + angleDelta);

		
		float normalizedDelta = angleDelta/180f;

		normalizedVolume = MathUtils.clamp(normalizedVolume, 0.0f, 0.80f);

		soundRef.setPan(soundId, normalizedDelta/3f, normalizedVolume);
		
		//System.out.println("Pan = " + normalizedDelta + " Volume = " + normalizedVolume);
		
		//soundHeading.sub
//		float soundAngle = (float) Math.atan2(soundHeading.y, soundHeading.x);

		
	}
	
//	private int getUnusedLoopSoundIndex(){
//		for (int i=0; i<MAX_LOOP_SOUNDS;i++){
//			if (soundIds[i]==-1){
//				return i;
//			}
//			
//		}
//		return -1;
//	}
	
//	public void startLoop(LoopType type, Vector3 soundPosition){
//		int index = getUnusedLoopSoundIndex();
//		if (index == -1) return;
//		
//		long soundId = -1;
//		stopLoop(type);
//		switch(type){
//			case FOUNTAIN_LOOP:
//				soundId = fountainLoops[random.nextInt(fountainLoops.length)].loop();
//				break;
//			case FIRE_LOOP:
//				soundId = fireLoops[random.nextInt(fireLoops.length)].loop();
//				break;
//			default:
//				break;
//		}
//		
//		if (soundId>-1) {
//			soundIds[index] = soundId;
//		}
//
//	}
//	
//
//	
//	public void stopLoop(LoopType type){
//		switch(type){
//		case FOUNTAIN_LOOP:
//			for (Sound s: fountainLoops){
//				s.stop();
//			}
//			break;
//		case FIRE_LOOP:
//			for (Sound s: fireLoops){
//				s.stop();
//			}
//			break;
//		default:
//			break;
//		}
//	}
	
	public void dispose(){
		
		for (Sound s: soundList){
			s.dispose();
		}
//		for (Sound s: fountainLoops){
//			s.dispose();
//		}
//		for (Sound s: fireLoops){
//			s.dispose();
//		}
		
		for (Music m: musics){
			m.dispose();
		}
	
	}
	
	
	
}
