/*
 * ***********************************************************************
 *
 *  ADOBE CONFIDENTIAL
 *  ___________________
 *
 *  Copyright 2013 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 *  NOTICE:  All information contained herein is, and remains
 *  the property of Adobe Systems Incorporated and its suppliers,
 *  if any.  The intellectual and technical concepts contained
 *  herein are proprietary to Adobe Systems Incorporated and its
 *  suppliers and are protected by trade secret or copyright law.
 *  Dissemination of this information or reproduction of this material
 *  is strictly forbidden unless prior written permission is obtained
 *  from Adobe Systems Incorporated.
 *
 * ***********************************************************************
 */

package com.adobe.primetime.reference.feature.playback;

import junit.framework.Assert;
import android.annotation.TargetApi;
import android.graphics.Point;
import android.os.Build;
import android.view.Display;
import android.widget.ImageButton;
import android.widget.TextView;

import com.adobe.mediacore.MediaPlayer.PlayerStatus;
import com.adobe.primetime.reference.R;
import com.adobe.primetime.reference.ui.player.MarkableSeekBar;

/**
 * Play a HLS stream with play and pause operation.
 */
public class PlaybackPlayPauseEndToEndTest extends PlaybackEndToEndTestBase {

	private final String BUFFER_COMPLETE = "Buffering complete";
	private final String PLAYBACK_START = "Player state changed to ["
			+ PlayerStatus.PLAYING + "].";
	private final String PLAYBACK_COMPLETE = "Player state changed to [COMPLETE]";
	private final String SEEK_COMPLETE_0 = "Seek complete at position: 0";

	public PlaybackPlayPauseEndToEndTest() throws Exception {
		contentUrl = "http://de9b7h88wgj5l.cloudfront.net/static/hls-ref/30fps/tos-abr400k.m3u8";
	}

	/**
	 * Test player activity loads and play the video item correctly
	 */
	public void testLoadAndPlayVideo() throws InterruptedException {

		// Verify buffering on prepare stage
		Assert.assertTrue(solo.waitForView(R.id.pbBufferingSpinner));
		Assert.assertTrue(solo.waitForLogMessage(BUFFER_COMPLETE));

		// Verify duration matches
		Assert.assertEquals("12:14", ((TextView) solo
				.getView(R.id.txtCurrentTime)).getText().subSequence(6, 11));
	}

	/**
	 * Test pause and resume operation
	 * 
	 * @throws InterruptedException
	 */
	@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
	public void testPauseAndResumeVideo() throws InterruptedException {

		Assert.assertTrue(solo.waitForLogMessage(BUFFER_COMPLETE));

		// Play video for 10 seconds
		solo.sleep(10000);

		// Pause by tapping the middle screen
		Display display = solo.getCurrentActivity().getWindowManager()
				.getDefaultDisplay();
		Point size = getDisplaySize(display);
		int width = size.x;
		int height = size.y;
		solo.clickOnScreen(width / 2, height / 2);

		// Save current time and check it's been played for at least 5 seconds
		String currentTime = ((TextView) solo.getView(R.id.txtCurrentTime))
				.getText().toString().substring(0, 5);
		int sec = timeToSec(currentTime);
		Assert.assertTrue(sec > 5);
		Assert.assertEquals(((ImageButton) solo
				.getView(R.id.btnPlayerControlPlayPause))
				.getContentDescription(), "play");

		// Wait another 3 seconds and recheck the current time does not change.
		solo.sleep(3000);
		String newCurrentTime = ((TextView) solo.getView(R.id.txtCurrentTime))
				.getText().toString().substring(0, 5);
		Assert.assertEquals(newCurrentTime, currentTime);

		// Resume playing and play another 5 seconds then verify playback has
		// advanced
		solo.clickOnView(solo.getView(R.id.btnPlayerControlPlayPause));
		solo.sleep(5000);
		newCurrentTime = ((TextView) solo.getView(R.id.txtCurrentTime))
				.getText().toString().substring(0, 5);
		int newSec = timeToSec(newCurrentTime);
		Assert.assertTrue(newSec > sec);
		Assert.assertEquals(((ImageButton) solo
				.getView(R.id.btnPlayerControlPlayPause))
				.getContentDescription(), "pause");

	}

	/**
	 * Test seek and replay operation
	 * 
	 * @throws InterruptedException
	 */
	public void testSeekAndReplayVideo() throws InterruptedException {

		// Wait until video starts playing
		Assert.assertTrue(solo.waitForLogMessage(PLAYBACK_START));
		solo.clickOnView(solo.getView(R.id.btnPlayerControlPlayPause));

		// Seek to the end of the video
		MarkableSeekBar seekBar = (MarkableSeekBar) solo
				.getView(R.id.sbPlayerControlSeekBar);
		int[] location = { 0, 0 };
		seekBar.getLocationOnScreen(location);
		solo.clickOnScreen(
				(int) Math.floor(location[0] + (seekBar.getWidth() * .985)),
				location[1]);
		solo.clearLog();
		Assert.assertTrue(solo.waitForLogMessage(BUFFER_COMPLETE));

		// Verify current time is greater than 12 minutes
		String currentTime = ((TextView) solo.getView(R.id.txtCurrentTime))
				.getText().toString().substring(0, 5);
		assertTrue(timeToSec(currentTime) > 12 * 60);

		// Playback should end in 6 seconds, but the time varies depending on the screen size.  
		// We wait for 15 seconds just in case.
		solo.clickOnView(solo.getView(R.id.btnPlayerControlPlayPause));
		Assert.assertTrue(solo.waitForLogMessage(PLAYBACK_COMPLETE, 15000));
		currentTime = ((TextView) solo.getView(R.id.txtCurrentTime)).getText()
				.toString().substring(0, 5);
		assertEquals(currentTime, "12:14");

		// Replay the video
		solo.clearLog();

		// Wait a while before replay
		solo.sleep(3000);
		solo.clickOnView(solo.getView(R.id.btnPlayerControlPlayPause));
		Assert.assertTrue(solo.waitForLogMessage(SEEK_COMPLETE_0));
	}

	/**
	 * Convert string representation of time MM:SS to number of seconds
	 * 
	 * @param time
	 * @return
	 */
	private int timeToSec(String time) {
		int min = Integer.parseInt(time.substring(0, time.indexOf(":")));
		int sec = Integer.parseInt(time.substring(time.indexOf(":") + 1));
		return min * 60 + sec;
	}

}
