package com.upc.pbe.upcnews;

import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.VideoView;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.res.Configuration;
import android.net.TrafficStats;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Toast;

//Tercera activitat principal, executa la reproduccio del video sencer
public class VideoActivity extends Activity {
	
	private final static String TAG = "VideoActivity";
	private VideoView video;
	private HLS h = null;
	private String filePath;
	private BandwidthMeasurer bm;
	private ProgressDialog pd;
	ArrayList<String> queue;
	ArrayList<String> playedQueue;
	int currentPos;
	boolean ended;
	boolean buffering;
	DescarregaSegment ds;
	boolean videoNotPlayed;


	@Override
	public void onCreate(Bundle savedInstanceState) {
		
		//Creem el layout
		
		super.onCreate(savedInstanceState);
		//Necesario para las libs
		if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))
		{
			return;
		}
		setContentView(R.layout.activity_video);
		currentPos = 0;
		videoNotPlayed = false;
		queue = new ArrayList<String>();
		playedQueue = new ArrayList<String>();
		buffering = true;
		ended = false;
		filePath = ((UpcApp)getApplication()).getLocalPath();
		video = (VideoView) findViewById(R.id.VideoView1);
		//Creem un listener associat al fi de l'activitat (el fi de cada ts)
		io.vov.vitamio.widget.MediaController mc = new MediaController(this);
		video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
		    public void onCompletion(MediaPlayer mp) {
		    	//Al acabar cada ts, reproduit el seguent
				playNext();
		    } 
		});
		mc.setOnFFLeftListener(new View.OnClickListener() {
			public void onClick(View v) {
				Log.d(TAG, "FFLEFT");
				playPrevious();
			}
		});
		mc.setOnFFRightListener(new View.OnClickListener() {
			public void onClick(View v) {
				Log.d(TAG, "FFRIGHT");
				playNext();
			}
		});
		video.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);
		//Creem un gestor HLS, carreguem el video i iniciem la reproduccio
		h = ((UpcApp)getApplication()).getHLS();
		h.setQuality(((UpcApp)getApplication()).getQuality());
		h.loadVideo();
		video.setMediaController(mc);
		bm = new BandwidthMeasurer();
		downloadSegment(getNext());
	}
	
	public String getNext() 
	{
			return h.next();
	}
	
	public void toggleBuffering(boolean b)
	{
		if(b)
		{
			buffering = true;
			if(pd == null)
			{
				pd = new CustomProgressDialog(VideoActivity.this);
				pd.setCancelable(false);
				pd.setMessage(getString(R.string.buffering_text));
			}
			pd.show();
		}
		else
		{
			buffering = false;
			pd.dismiss();
		}
	}
	
	public void quitPlayer()
	{
		ds.cancel(true);
		video.stopPlayback();
		super.finish();
		return;
	}
	
	public void buffer()
	{
		toggleBuffering(true);
		video.suspend();
	}
	public void play(String path)
	{
		toggleBuffering(false);
		video.setVideoPath(path);
		video.start();
		video.requestFocus();
	}
	
	public void playNext()
	{
		if(++currentPos > 0)
		{
			currentPos = 0;
		}
		if(currentPos == 0)
		{
			if(!videoNotPlayed)
			{
				playedQueue.add(queue.get(0));
				queue.remove(0);
			}
			else
			{
				videoNotPlayed = false;
			}
	    	if(ended && queue.isEmpty())
	    	{
	    		quitPlayer();
	    	}
	    	if(queue.isEmpty())
	    	{
	    		buffer();
	    	}
	    	else
	    	{
	    		play(queue.get(0));
	    	}
		}
		else if(currentPos < 0)
		{
			play(playedQueue.get(playedQueue.size() + currentPos));
		}
	}
	
	public void playPrevious()
	{
		if(currentPos == 0)
		{
			videoNotPlayed = true;
		}
		if(playedQueue.isEmpty())
		{
			play(queue.get(0));
			return;
		}
		else if(playedQueue.size() + (--currentPos) < 0)
    	{
    		currentPos++;
    	}
    	play(playedQueue.get(playedQueue.size() + currentPos));
	}
	
	public void downloadSegment(String url)
	{
		ds = new DescarregaSegment();
		try
		{
			ds.execute(new URL(url));
		}
		catch (MalformedURLException e)
		{
			Toast.makeText(this, "URL malformada", Toast.LENGTH_LONG).show();
		}
	}
	public void showNotFound(String url)
	{
		Toast.makeText(this, "No s'ha trobat el segment " + url, Toast.LENGTH_LONG).show();
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// Determina el funcionament al apretar la tecla de tornar enrere
		if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) 
		{
			quitPlayer();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		if (video != null)
			video.setVideoLayout(VideoView.VIDEO_LAYOUT_SCALE, 0);
		super.onConfigurationChanged(newConfig);
	}
	
	public class DescarregaSegment extends AsyncTask<URL, Void, Void>
	{
		final static String TAG = "DescarregaSegment";
		private long bps;
		boolean failed;
		String url;
		
		public DescarregaSegment()
		{
			bps = 0;
			failed = false;
		}
		
		@Override
		protected void onPreExecute() 
		{
			if(queue.isEmpty() && !ended)
			{
				buffer();
			}
		}
		
		@Override
		protected Void doInBackground(URL... urls)
		{
			Long downloaded = Long.valueOf(0);
			long startTime = System.currentTimeMillis();
			long segmentBytes = TrafficStats.getTotalRxBytes();
			String fileName = urls[0].toString().substring(urls[0].toString().lastIndexOf("/")+1);
			// Iniciem la connexi� i creem els Streams
			try 
			{
				int index = 0;
				String newFileName = fileName.substring(0,fileName.lastIndexOf("."));
				String extension = fileName.substring(fileName.lastIndexOf("."));
				while(new File(filePath + (newFileName + extension)).exists())
				{
					newFileName = fileName.substring(0,fileName.lastIndexOf(".")) + index++;
				}
				fileName = newFileName + extension;
				FileOutputStream out = new FileOutputStream(filePath + fileName);
				BufferedInputStream in = new BufferedInputStream(urls[0].openStream());
				Log.d(TAG, "\nDescarregant: \n");
				Log.d(TAG, ">> URL: " + urls[0]);
				byte data[] = new byte[102400];
	            int count;
	            while ((count = in.read(data)) != -1) 
	            {
	                downloaded += count;
	                out.write(data, 0, count);
	            }
				out.flush();
				out.close();
				in.close();
				bps = (long) bm.Measure(segmentBytes, startTime);
				Log.d(TAG, "Descarrega finalitzada");
				queue.add(filePath + fileName);
			}
			catch(IOException e)
			{
				url = urls[0].toString();
				failed = true;
				this.cancel(true);
				return null;
			}
			return null;
		 }
		 protected void onPostExecute(Void v) 
		 {
			 if(ended)
			 {
					return;
			 }
			 if(failed)
			 {
				 failed = false;
				 showNotFound(url);
			 }
			 else if(!queue.isEmpty() && buffering)
			 {
				 play(queue.get(0));
			 }
			 String newSegment = null;
			 h.updateQuality((long) bps);
			 newSegment = getNext();
			 if(newSegment == null)
			 {
				 ended = true;
			 }
			 else
			 {
				downloadSegment(newSegment); 
			 }
			 return;
	     }
	}
	
}
