package com.gamepatriot.framework2d.implementation;

import android.media.MediaPlayer;
import android.util.Log;

import com.gamepatriot.androidframework.framework.AndroidMusicHandler;
import com.gamepatriot.framework2d.R;

/**
 * The MusicHandler class provides the functionality for playing, resuming, and starting music-audio files. The class contains resource references to music with its subclass {@link Music} and
 * uses a single {@link MediaPlayer} to control and manipulate musical playback for the application.
 * 
 * @see AndroidMusicHandler
 * @author Pete Schmitz, May 9, 2013
 *
 */
public class MusicHandler implements AndroidMusicHandler {
	
	/** Automatic volume level once class is instantiated. **/
	public static float DEFAULT_MUSIC_VOLUME = 1.0f;
	
	/**
	 * Music enum contains flags for each Music resource and their associated resource index (musicIndex).
	 * 
	 * @author Pete Schmitz, May 9, 2013
	 *
	 */
	public static enum Music{
		HIP_HOP_PIANO(R.raw.hiphoppiano);
		
		/** Index of the resource supplied in the constructor. **/
		private int musicIndex = -1;
		
		private Music(int $musicIndex){
			musicIndex = $musicIndex;
		}
		
		/** 
		 * Return the music resource index that is associated with this enum.
		 */
		public int getMusicIndex(){
			return musicIndex;
		}
	}
	
	//References
	
	private final Main main;
	
	
	//Container
	
	/** The {@link MediaPlayer} used to playback music. **/
	private MediaPlayer mediaPlayer;
	
	
	//Flags
	
	/** Whether music should play when {@link #resumeMusic()} or {@link #playMusic(Music, boolean)} are called. **/
	public boolean musicEnabled = true;
	
	/** Whether a recreation of the Media Player needs to established. The media player will be destroyed and recreated based on whether the application is the active window or not. **/
	private boolean recreation = false;
	
	/** Flag for the volume setting {@link #mediaPlayer} is currently set to. Change the volume using {@link #musicVolume(float)}. **/
	private float volume = DEFAULT_MUSIC_VOLUME;
	
	/** The current {@link Music} that is being played in {@link #mediaPlayer}. **/
	private Music musicID = null;
	
	/** Whether or not the current music playing will continuously loop when it ends. **/
	private boolean looping = false;
	
	/** Stores the position index of the current music when {@link #disableMusic()} is called.  **/
	private int musicSeek = -1;
	
	
	/**
	 * Constructor
	 * @param $main				Reference to this application's {@link Main} class.
	 * @param $musicEnabled		Whether or not this class should start non-muted.
	 */
	public MusicHandler(Main $main, boolean $musicEnabled){
		musicVolume(DEFAULT_MUSIC_VOLUME);
		main = $main;
		
		if ($musicEnabled) enableMusic();
		else disableMusic();
	}
	
	@Override
	public void disableMusic() {
		musicEnabled = false;
		recreation = true;
		
		if (mediaPlayer == null || musicID == null) return;
		
		musicSeek = mediaPlayer.getCurrentPosition();
		mediaPlayer.release();
		mediaPlayer = null;
	}
	
	@Override
	public void enableMusic() {
		musicEnabled = true;
		if (musicID != null && musicSeek >= 0){
			playMusic(musicID, looping);
			mediaPlayer.seekTo(musicSeek);
		}
		resumeMusic();
	}
	
	@Override
	public void musicVolume(float $amount) {
		volume = $amount;
		
		if (mediaPlayer == null) return;
		
		mediaPlayer.setVolume($amount, $amount);
	}
	
	@Override
	public void pauseMusic() {
		if (mediaPlayer == null) return;
		
		mediaPlayer.pause();
	}
	
	@Override
	public void resumeMusic() {
		if (mediaPlayer == null) return;
		
		if (musicEnabled) mediaPlayer.start();
	}
	
	/**
	 * Convenient call to play music based on a {@link Music} ID.
	 * @param $music	The Music ID that references the music resource.
	 * @param $loop		Whether this music should continuously loop or not.
	 */
	public void playMusic(Music $music, boolean $loop) {
		int $musicIndex = -1;
		looping = $loop;
		
		$musicIndex = $music.getMusicIndex();
		Log.d("logd", "Music index: " + Integer.toString($musicIndex));
		if ($musicIndex >= 0){
			if (mediaPlayer != null) mediaPlayer.release();
			try {
				musicID = $music;
				mediaPlayer = MediaPlayer.create(main, $musicIndex);
				
				//Check if creation was successful
				if (mediaPlayer == null){
					Log.d("logd", "media player creation failed");
					return;
				}
				
				mediaPlayer.setVolume(volume, volume);
				mediaPlayer.setLooping($loop);
				if (musicEnabled){
					if (!recreation) mediaPlayer.start();
					recreation = false;
				}
					
			} catch (Exception e){
				
				throw new RuntimeException("Media Player couldn't load music.");
			}
		}
	}
	
}
