/*
 * ***********************************************************************
 *
 *  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.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.adobe.mediacore.ABRControlParameters.ABRPolicy;
import com.adobe.mediacore.MediaPlayer.PlayerStatus;
import com.adobe.primetime.reference.manager.PlaybackManager;

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

	private final String PLAYBACK_START = "Player state changed to ["
			+ PlayerStatus.PLAYING + "].";
	private final String BIT_RATE_CHANGE = "Detected bit rate change [%1$s at time [";

	// These are the bit rates from low to high in the test stream
	private final String[] BITRATES = { "70400", "440000", "660000", "990000",
			"1408000", "2310000" };

	private boolean isAbrControlEnabled;
	private String init, min, max, abrPolicy;

	public PlaybackABREndToEndTest() throws Exception {
		contentUrl = "http://d398890tia84ty.cloudfront.net/e2e-vod/cloudfront_vod_hls_tos_30fps.m3u8";
	}

	@Override
	protected void tearDown() throws Exception {

		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(getInstrumentation()
						.getTargetContext());
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
						isAbrControlEnabled).commit();

		super.tearDown();
	}

	/**
	 * Test ABR switching based on default ABR params
	 */
	public void testDefaultABR() throws InterruptedException {

		Context context = getInstrumentation().getTargetContext();

		// set the control bar to disable ABR control
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(context);
		isAbrControlEnabled = prefs.getBoolean(
				PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
				PlaybackManager.DEFAULT_ABR_CTRL_ENABLED);
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED, false)
				.commit();

		solo.waitForLogMessage(PLAYBACK_START);
		Assert.assertTrue(solo.waitForLogMessage(String.format(BIT_RATE_CHANGE,
				BITRATES[3])));

		// restore original ABR control flag
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
						isAbrControlEnabled).commit();

	}

	/**
	 * Test ABR switching based on customize ABR params
	 */
	public void testCustomABRParams() throws InterruptedException {

		Context context = getInstrumentation().getTargetContext();

		// set the control bar to enable ABR control
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(context);
		isAbrControlEnabled = prefs.getBoolean(
				PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
				PlaybackManager.DEFAULT_ABR_CTRL_ENABLED);
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED, true)
				.commit();

		// set init = second lowest bit rate, min = lowest, max = highest
		init = prefs.getString(PlaybackManager.SETTINGS_ABR_INITIAL_BITRATE,
				String.valueOf(PlaybackManager.DEFAULT_INIT_BIT_RATE));
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_INITIAL_BITRATE,
						BITRATES[1]).commit();
		min = prefs.getString(PlaybackManager.SETTINGS_ABR_MIN_BITRATE,
				String.valueOf(PlaybackManager.DEFAULT_MIN_BIT_RATE));
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_MIN_BITRATE,
						BITRATES[0]).commit();
		max = prefs.getString(PlaybackManager.SETTINGS_ABR_MAX_BITRATE,
				String.valueOf(PlaybackManager.DEFAULT_MAX_BIT_RATE));
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_MAX_BITRATE,
						BITRATES[2]).commit();

		// playback starts at initial bit rate
		solo.waitForLogMessage(PLAYBACK_START);
		Assert.assertTrue(solo.waitForLogMessage(String.format(BIT_RATE_CHANGE,
				BITRATES[1])));

		// playback steps up within 20 seconds
		Assert.assertTrue(solo.waitForLogMessage(String.format(BIT_RATE_CHANGE,
				BITRATES[2])));

		// restore original ABR params
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
						isAbrControlEnabled).commit();
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_INITIAL_BITRATE, init)
				.commit();
		prefs.edit().putString(PlaybackManager.SETTINGS_ABR_MIN_BITRATE, min)
				.commit();
		prefs.edit().putString(PlaybackManager.SETTINGS_ABR_MAX_BITRATE, max)
				.commit();
	}

	/**
	 * Test ABR switching based on customize ABR policy
	 */
	public void testCustomABRPolicy() throws InterruptedException {

		Context context = getInstrumentation().getTargetContext();

		// set the control bar to enable ABR control
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(context);
		isAbrControlEnabled = prefs.getBoolean(
				PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
				PlaybackManager.DEFAULT_ABR_CTRL_ENABLED);
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED, true)
				.commit();

		// set all bit rate to 0 and ABR policy to aggressive
		init = prefs.getString(PlaybackManager.SETTINGS_ABR_INITIAL_BITRATE,
				String.valueOf(PlaybackManager.DEFAULT_INIT_BIT_RATE));
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_INITIAL_BITRATE, "0")
				.commit();
		min = prefs.getString(PlaybackManager.SETTINGS_ABR_MIN_BITRATE,
				String.valueOf(PlaybackManager.DEFAULT_MIN_BIT_RATE));
		prefs.edit().putString(PlaybackManager.SETTINGS_ABR_MIN_BITRATE, "0")
				.commit();
		max = prefs.getString(PlaybackManager.SETTINGS_ABR_MAX_BITRATE,
				String.valueOf(PlaybackManager.DEFAULT_MAX_BIT_RATE));
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_MAX_BITRATE,
						BITRATES[5]).commit();
		abrPolicy = prefs.getString(PlaybackManager.SETTINGS_ABR_POLICY,
				String.valueOf(ABRPolicy.ABR_MODERATE.getValue()));
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_POLICY,
						String.valueOf(ABRPolicy.ABR_AGGRESSIVE.getValue()))
				.commit();

		// playback starts at initial bit rate
		solo.waitForLogMessage(PLAYBACK_START);
		Assert.assertTrue(solo.waitForLogMessage(String.format(BIT_RATE_CHANGE,
				BITRATES[5])));

		// restore original ABR params
		prefs.edit()
				.putBoolean(PlaybackManager.SETTINGS_ABR_CTRL_ENABLED,
						isAbrControlEnabled).commit();
		prefs.edit()
				.putString(PlaybackManager.SETTINGS_ABR_INITIAL_BITRATE, init)
				.commit();
		prefs.edit().putString(PlaybackManager.SETTINGS_ABR_MIN_BITRATE, min)
				.commit();
		prefs.edit().putString(PlaybackManager.SETTINGS_ABR_MAX_BITRATE, max)
				.commit();
		prefs.edit().putString(PlaybackManager.SETTINGS_ABR_POLICY, abrPolicy)
				.commit();
	}

}
