package com.androidhive.musicplayer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import org.arkiwi.app.R;
import org.arkiwi.app.activity.Viewer;
import org.arkiwi.app.feed.FeedQuery;
import org.arkiwi.app.rss.RssReader;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class MusicPlayerActivity extends Activity implements OnCompletionListener, SeekBar.OnSeekBarChangeListener {
	private final static String LOG_TAG = "MPA";
	private ImageButton btnPlay;
	private ImageButton btnForward;
	private ImageButton btnBackward;
	private ImageButton btnNext;
	private ImageButton btnPrevious;
	private ImageButton btnPlaylist;
	private ImageButton btnRepeat;
	private ImageButton btnShuffle;
	private SeekBar songProgressBar;
	private TextView songTitleLabel;
	private TextView songCurrentDurationLabel;
	private TextView songTotalDurationLabel;
	// Media Player
	private  MediaPlayer mp;
	// Handler to update UI timer, progress bar etc,.
	private WindowManager.LayoutParams layout;
	
	private Handler mHandler = new Handler();
	private SongsManager songManager;
	private Utilities utils;
	private int seekForwardTime = 5000; // 5000 milliseconds
	private int seekBackwardTime = 5000; // 5000 milliseconds
	private int currentSongIndex = 0; 
	private boolean isShuffle = false;
	private boolean isRepeat = false;
	private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.pl_player);
		
		layout = getWindow().getAttributes();
		
		Log.d(LOG_TAG, "onCreate()");
		// All player buttons
		btnPlay = (ImageButton) findViewById(R.id.btnPlay);
		btnForward = (ImageButton) findViewById(R.id.btnForward);
		btnBackward = (ImageButton) findViewById(R.id.btnBackward);
		btnNext = (ImageButton) findViewById(R.id.btnNext);
		btnPrevious = (ImageButton) findViewById(R.id.btnPrevious);
		btnPlaylist = (ImageButton) findViewById(R.id.btnPlaylist);
		btnRepeat = (ImageButton) findViewById(R.id.btnRepeat);
		btnShuffle = (ImageButton) findViewById(R.id.btnShuffle);
		songProgressBar = (SeekBar) findViewById(R.id.songProgressBar);
		songTitleLabel = (TextView) findViewById(R.id.songTitle);
		songCurrentDurationLabel = (TextView) findViewById(R.id.songCurrentDurationLabel);
		songTotalDurationLabel = (TextView) findViewById(R.id.songTotalDurationLabel);

		Bundle extras = getIntent().getExtras();
		if(extras != null) {
			//tpe = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
			//mUpdateTimeTaskHandler = tpe.submit(mUpdateTimeTask);
			
			RssReader rssReader = RssReader.getInstance();
			FeedQuery fq = rssReader.getFeedQuery();
			//Mediaplayer
			mp = new MediaPlayer();
			songManager = SongsManager.getInstance();
			if(songManager.getSongsList().size()>0)
				songManager.getSongsList().clear();
			
			utils = new Utilities();
			// Listeners
			songProgressBar.setOnSeekBarChangeListener(this); // Important
			mp.setOnCompletionListener(this); // Important
			
			if(extras.getInt("type") == Viewer.MENU_XSPF_ID ) {
				//TODO: verificare se ho almeno 1 feeditem, è meglio
				//verificare prima di mandare l'intent... da vedere se
				//è fattibile.
				songsList = songManager.getPlayListFromWeb(
						fq.getFeedItems(getString(R.string.rss_type_audio)));
			} else if(extras.getInt("type") == Viewer.INTENT_SONG_ID){
				String key = extras.getString("feed");
				songsList = songManager.getPlayListFromWeb(
						fq.getFeedItem(fq.getFeedItem(key)));
			} 

			if(songManager.getSongsList().size()>0)
				playSong(0);
			
		}
		/**
		 * Play button click event
		 * plays a song and changes button to pause image
		 * pauses a song and changes button to play image
		 * */
		btnPlay.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				if(resumeSong()){
					mp.pause();
					// Changing button image to play button
					btnPlay.setImageResource(R.drawable.pl_play);
				}
			}
		});
		
		/**
		 * Forward button click event
		 * Forwards song specified seconds
		 * */
		btnForward.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// get current song position				
				int currentPosition = mp.getCurrentPosition();
				// check if seekForward time is lesser than song duration
				if(currentPosition + seekForwardTime <= mp.getDuration()){
					// forward song
					mp.seekTo(currentPosition + seekForwardTime);
				}else{
					// forward to end position
					mp.seekTo(mp.getDuration());
				}
			}
		});
		
		/**
		 * Backward button click event
		 * Backward song to specified seconds
		 * */
		btnBackward.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// get current song position				
				int currentPosition = mp.getCurrentPosition();
				// check if seekBackward time is greater than 0 sec
				if(currentPosition - seekBackwardTime >= 0){
					// forward song
					mp.seekTo(currentPosition - seekBackwardTime);
				}else{
					// backward to starting position
					mp.seekTo(0);
				}
				
			}
		});
		
		/**
		 * Next button click event
		 * Plays next song by taking currentSongIndex + 1
		 * */
		btnNext.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				Log.d(LOG_TAG, "btnNext() "+currentSongIndex);
				// check if next song is there or not
				if(currentSongIndex < (songsList.size() - 1)){
					playSong(currentSongIndex + 1);
					currentSongIndex = currentSongIndex + 1;
				}else{
					// play first song
					playSong(0);
					currentSongIndex = 0;
					
					Toast.makeText(getApplicationContext(), R.string.toast_pl_no_next, Toast.LENGTH_SHORT).show();
				}
			}
		});
		
		/**
		 * Back button click event
		 * Plays previous song by currentSongIndex - 1
		 * */
		btnPrevious.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				Log.d(LOG_TAG, "btnPrevious() "+currentSongIndex);
				if(currentSongIndex > 0){
					playSong(currentSongIndex - 1);
					currentSongIndex = currentSongIndex - 1;
				}else{
					// play last song
					playSong(songsList.size() - 1);
					currentSongIndex = songsList.size() - 1;
					Toast.makeText(getApplicationContext(), R.string.toast_pl_no_prev, Toast.LENGTH_SHORT).show();
				}
				
			}
		});
		
		/**
		 * Button Click event for Repeat button
		 * Enables repeat flag to true
		 * */
		btnRepeat.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				if(isRepeat){
					isRepeat = false;
					Toast.makeText(getApplicationContext(), R.string.toast_pl_r_off, Toast.LENGTH_SHORT).show();
					btnRepeat.setImageResource(R.drawable.pl_repeat);
				}else{
					// make repeat to true
					isRepeat = true;
					Toast.makeText(getApplicationContext(), R.string.toast_pl_r_on, Toast.LENGTH_SHORT).show();
					// make shuffle to false
					isShuffle = false;
					btnRepeat.setImageResource(R.drawable.pl_repeat_focused);
					btnShuffle.setImageResource(R.drawable.pl_shuffle);
				}	
			}
		});
		
		/**
		 * Button Click event for Shuffle button
		 * Enables shuffle flag to true
		 * */
		btnShuffle.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				if(isShuffle){
					isShuffle = false;
					Toast.makeText(getApplicationContext(), R.string.toast_pl_s_off, Toast.LENGTH_SHORT).show();
					btnShuffle.setImageResource(R.drawable.pl_shuffle);
				}else{
					// make repeat to true
					isShuffle= true;
					Toast.makeText(getApplicationContext(), R.string.toast_pl_s_on, Toast.LENGTH_SHORT).show();
					// make shuffle to false
					isRepeat = false;
					btnShuffle.setImageResource(R.drawable.pl_shuffle_focused);
					btnRepeat.setImageResource(R.drawable.pl_repeat);
				}	
			}
		});
	
		
		/**
		 * Button Click event for Play list click event
		 * Launches list activity which displays list of songs
		 * */
		btnPlaylist.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				layout.screenBrightness = -1;
				getWindow().setAttributes(layout);
				
				Intent i = new Intent(getApplicationContext(), PlayListActivity.class);
				startActivityForResult(i, 100);			
			}
		});
		
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		
	    resumeSong();
	}
	
	/**
	 * Se il brano è interrotto viene rimesso in play aggiornando il bottone
	 */
	private boolean resumeSong(){
		boolean playng=false;
	    if(mp != null) {
	    	if(! mp.isPlaying()){
	    		// Resume song
	    		mp.start();
	    		// Changing button image to pause button
	    		btnPlay.setImageResource(R.drawable.pl_pause);
	    	} else {
	    		playng=true;
	    	}
	    	
     		layout.screenBrightness = 0.1f;
    		getWindow().setAttributes(layout);
	    } 
	    
	    return playng;
	}
	
	/**
	 * Receiving song index from playlist view
	 * and play the song
	 * */
	@Override
    protected void onActivityResult(int requestCode,
                                     int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == 100){
         	currentSongIndex = data.getExtras().getInt("songIndex");
         	Log.d(LOG_TAG, "onActivityResult(), dalla playlist "+currentSongIndex);
         	// play selected song
            playSong(currentSongIndex);
        }
 
    }
	
	/**
	 * Function to play a song
	 * @param songIndex - index of song
	 * */
	public void  playSong(int songIndex){
		// Play song
		try {
			Log.d(LOG_TAG, "playSong() "+songIndex);
			
     		layout.screenBrightness = 0.1f;
    		getWindow().setAttributes(layout);
			
        	mp.reset();
			mp.setDataSource(songsList.get(songIndex).get("songPath"));
			mp.prepare();
			mp.start();
			// Displaying Song title
			String songTitle = songsList.get(songIndex).get("songTitle");
        	songTitleLabel.setText(songTitle);
			
        	// Changing Button Image to pause image
			btnPlay.setImageResource(R.drawable.pl_pause);
			
			// set Progress bar values
			songProgressBar.setProgress(0);
			songProgressBar.setMax(100);
			
			// Updating progress bar
			updateProgressBar();			
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//TODO: gestirlo con un servizio così da non fermare la musica girando per l'app 
	/**
	 * Background Runnable thread
	 * */
	private Runnable mUpdateTimeTask = new Runnable() {
		   public void run() {
			   long totalDuration = mp.getDuration();
			   long currentDuration = mp.getCurrentPosition();
			  
			   // Displaying Total Duration time
			   songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
			   // Displaying time completed playing
			   songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
			   
			   // Updating progress bar
			   int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
			   //Log.d("Progress", ""+progress);
			   songProgressBar.setProgress(progress);
			   
			   // Running this thread after 100 milliseconds
			   mHandler.postDelayed(this, 100);
		   }
		};

	/**
	 * 
	 * */
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {}
	/**
	 * Update timer on seekbar
	 * */
	public void updateProgressBar() {
        mHandler.postDelayed(mUpdateTimeTask, 100);        
    }	
	/**
	 * When user starts moving the progress handler
	 * */
	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {
		// remove message Handler from updating progress bar
		mHandler.removeCallbacks(mUpdateTimeTask);
    }
	
	/**
	 * When user stops moving the progress hanlder
	 * */
	@Override
    public void onStopTrackingTouch(SeekBar seekBar) {
		mHandler.removeCallbacks(mUpdateTimeTask);
		int totalDuration = mp.getDuration();
		int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
		
		// forward or backward to certain seconds
		mp.seekTo(currentPosition);
		
		// update timer progress again
		updateProgressBar();
    }

	/**
	 * On Song Playing completed
	 * if repeat is ON play same song again
	 * if shuffle is ON play random song
	 * */
	@Override
	public void onCompletion(MediaPlayer arg0) {
		
		// check for repeat is ON or OFF
		if(isRepeat){
			// repeat is on play same song again
			playSong(currentSongIndex);
		} else if(isShuffle){
			// shuffle is on - play a random song
			Random rand = new Random();
			currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
			playSong(currentSongIndex);
		} else{
			//TODO:se ci sono solo poche tracce continua a ciclare, 
			//essendo che le tracce le prende da internet, forse è meglio
			//fermarlo?
			
			// no repeat or shuffle ON - play next song
			if(currentSongIndex < (songsList.size() - 1)){
				playSong(currentSongIndex + 1);
				currentSongIndex = currentSongIndex + 1;
			}else{
				// play first song
				playSong(0);
				currentSongIndex = 0;
			}
		} 
	}
	
	@Override
	protected void onPause() {
	    super.onPause();
	    if(mp != null) {
	    	if(mp.isPlaying()){
	    		mp.pause();
	    		
	    		layout.screenBrightness = -1;
	    		getWindow().setAttributes(layout);
	    	}
	    }
	}
	
	@Override
	 public void onDestroy(){
		Log.d(LOG_TAG, "onDestroy()");
		super.onDestroy();
		layout.screenBrightness = -1;
		getWindow().setAttributes(layout);
		if(mp != null) {
			mHandler.removeCallbacks(mUpdateTimeTask);
			mp.release();
		}
	 }
	
	
}