/*
 * ***********************************************************************
 *
 *  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.manager.test;

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import java.util.ArrayList;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.Suppress;

import com.adobe.mediacore.MediaPlayerItemConfig;
import com.adobe.mediacore.MediaResource;
import com.adobe.mediacore.metadata.AdSignalingMode;
import com.adobe.mediacore.metadata.AuditudeSettings;
import com.adobe.mediacore.metadata.Metadata;
import com.adobe.mediacore.metadata.MetadataKeys;
import com.adobe.mediacore.timeline.Timeline;
import com.adobe.mediacore.timeline.advertising.*;
import com.adobe.primetime.reference.config.IAdConfig;
import com.adobe.primetime.reference.manager.AdsManager;
import com.adobe.primetime.reference.manager.AdsManager.AdsManagerEventListener;
import com.adobe.primetime.reference.manager.AdsManagerOn;

/**
 * Unit tests for the AdsManager
 * 
 * @author dshei
 * 
 */

public class AdsManagerTest extends AndroidTestCase {

	private MockMediaPlayer mediaPlayer;
	private AdsManagerOn adsManager;
	private AdsManagerEventListener adsManagerEventListener;
	private IAdConfig adConfig;
	MediaResource playerResource;
	MediaPlayerItemConfig playerItemConfig;

	private boolean adBreakStarted = false;
	private boolean adStarted = false;
	private boolean adBreakCompleted = false;
	private boolean adCompleted = false;
	private double adProgressPercentage = 0;
	private String adClickUrl = "";
	private boolean adSkipped = false;

	@Override
	protected void setUp() throws Exception {
		super.setUp();

		// workaround for Dexmaker bug
		System.setProperty("dexmaker.dexcache", getContext().getCacheDir()
				.getPath());

		String url = "testUrl";
		String zoneId = "61135";
		String domain = "auditude.com";
		String mediaId = "vast_comedy";

		mediaPlayer = new MockMediaPlayer(getContext());
		adConfig = new AdConfig(domain, zoneId, mediaId, AdSignalingMode.DEFAULT);
		adsManager = new AdsManagerOn(adConfig, mediaPlayer);
		adsManagerEventListener = spy(new AdsManagerEventListenerImpl());
		adsManager.addEventListener(adsManagerEventListener);
		playerResource = new MediaResource(url, MediaResource.Type.HLS, adsManager.getAdvertisingMetadata());
		playerItemConfig = new MediaPlayerItemConfig(null, null);
		playerItemConfig.setAdvertisingMetadata(adsManager.getAdvertisingMetadata());
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();

		mediaPlayer = null;
		adsManager = null;
		adBreakStarted = false;
		adBreakCompleted = false;
		adCompleted = false;
		adProgressPercentage = 0;
		adClickUrl = "";
		adSkipped = false;
	}

	/**
	 * Tests public function getAdvertisingMetadata() in AdsManager
	 */
	public void testAdsMetadata() {
		Metadata node = adsManager.getAdvertisingMetadata();
		assertTrue(node.containsKey(MetadataKeys.AUDITUDE_METADATA_KEY.getValue()));
	}

	/**
	 * Tests public function adjustAdSignalingMode() in AdsManager
	 */
	public void testAdJustAdSignalingMode() {
		assertEquals(AdSignalingMode.DEFAULT,
				adConfig.getDefaultAdSignalingMode());

		String url = "testUrl";
		String zoneId = "61135";
		String domain = "auditude.com";
		String mediaId = "vast_comedy";
		adConfig = new AdConfig(domain, zoneId, mediaId,
				AdSignalingMode.MANIFEST_CUES);
		adsManager = new AdsManagerOn(adConfig, mediaPlayer);
		playerResource = new MediaResource(url, MediaResource.Type.HLS, adsManager.getAdvertisingMetadata());
		adsManager.adjustAdSignalingMode(playerItemConfig);

		assertEquals(AdSignalingMode.MANIFEST_CUES, adConfig.getDefaultAdSignalingMode());
	}

	/**
	 * Tests the ad manager handles an ad break correctly For each ad in the ad
	 * break, tests that ad manager responds properly the ad and its incremental
	 * progress
	 */
	public void testAdBreakLifeCycle() {
		ArrayList<Ad> ads = new ArrayList<Ad>();
		MediaResource adMediaResource = new MediaResource("testUrl", MediaResource.Type.HLS, null);
		AdAsset adAsset = new AdAsset("testAsset", 3000, adMediaResource, null, null, null);
		Ad testAd = new Ad("testAd", Ad.Type.LINEAR, null, 30000, adAsset, null);
		ads.add(testAd);

		int[] progress = { 25, 50, 75, 100 };

		mediaPlayer.simulateAdBreakLifeCyle(ads, progress);

		verify(adsManagerEventListener).onAdBreakStarted(null);
		for (Ad ad : ads) {
			verify(adsManagerEventListener).onAdStarted(null, ad);
			for (int eachProgress : progress) {
				verify(adsManagerEventListener).onAdProgress(null, ad,
						eachProgress);
			}
			verify(adsManagerEventListener).onAdCompleted(null, ad);
		}
		verify(adsManagerEventListener).onAdBreakCompleted(null);

		assertTrue(adBreakStarted);
		assertTrue(adStarted);
		assertEquals(adProgressPercentage, 100);
		assertTrue(adCompleted);
		assertTrue(adBreakCompleted);
	}

	/**
	 * Test the ad manager handles AdPlaybackEvent.onAdClick correctly
	 */
	@Suppress
	public void testOnAdClick() {
		MediaResource adMediaResource = new MediaResource("testUrl",
				MediaResource.Type.HLS, null);
		AdClick adClick = new AdClick("ID", "Title", "http://www.adobe.com");
		AdAsset adAsset = new AdAsset("testAsset", 30000, adMediaResource, adClick, null, null);
		Ad ad = new Ad("test", Ad.Type.LINEAR, null, 30000, adAsset, null);

		mediaPlayer.onAdClick(ad);
		// verify(adsManagerEventListener).handleStopAd(null, ad);
		assertEquals(adClickUrl, adClick.getUrl());
	}

	public class AdsManagerEventListenerImpl implements AdsManager.AdsManagerEventListener {
		@Override
		public void onAdBreakStarted(AdBreak adBreak) {
			adBreakStarted = true;
		}

		@Override
		public void onAdBreakCompleted(AdBreak adBreak) {
			adBreakCompleted = true;
		}

		@Override
		public void onAdStarted(AdBreak adBreak, Ad ad) {
			adStarted = true;
		}

		@Override
		public void onAdCompleted(AdBreak adBreak, Ad ad) {
			adCompleted = true;
		}

		@Override
		public void onAdProgress(AdBreak adBreak, Ad ad, double percentage) {
			adProgressPercentage = percentage;
		}

		@Override
		public void onAdClick(String url) {
			adClickUrl = url;
		}

		@Override
		public void onAdBreakSkipped(AdBreak adBreak) {
			adSkipped  = true;
		}

		@Override
		public void onTimelineUpdated(Timeline<?> timeline) {

		}
	};

	/**
	 * Customized Ad config for testing purpose
	 * 
	 */
	private class AdConfig implements IAdConfig {

		AdSignalingMode adSignalMode = null;

		private AuditudeSettings metadata;

		public AdConfig(String domain, String zoneId, String mediaId, AdSignalingMode mode) {
			metadata = new AuditudeSettings();
			metadata.setZoneId(zoneId);
			metadata.setDomain(domain);
			metadata.setMediaId(mediaId);

			adSignalMode = mode;

		}

		@Override
		public String getCustomAdFactoryType() {
			return AdsManager.DEFAULT_CUSTOM_AD_CLIENT_FACTORY;
		}

		@Override
		public boolean isClickableAdsEnabled() {
			return false;
		}

		@Override
		public AdvertisingMetadata getMetadata() {

			return metadata;
		}

		@Override
		public String[] getAdTags() {

			return null;
		}

		@Override
		public boolean isAdvertisingWorkflowEnabled() {

			return false;
		}

		@Override
		public AdSignalingMode getDefaultAdSignalingMode() {

			return adSignalMode;
		}

		@Override
		public boolean useDelayAdLoading() {
			return false;
		}

	}

}
