/*
 * ************************************************************************
 *
 * ADOBE SYSTEMS INCORPORATED
 * Copyright 2013 Adobe Systems Incorporated
 * All Rights Reserved.
 * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the 
 * terms of the Adobe license agreement accompanying it.  If you have received this file from a 
 * source other than Adobe, then your use, modification, or distribution of it requires the prior 
 * written permission of Adobe.
 *
 **************************************************************************
 */

package com.adobe.primetime.reference.feeds;

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.metadata.AdvertisingMetadata;
import com.adobe.primetime.reference.PrimetimeReference;
import com.adobe.primetime.reference.advertising.CustomAdProviderMetadata;
import com.adobe.primetime.reference.entitlement.EntitlementMetadata;
import com.adobe.primetime.reference.feeds.ContentRenditionInfo.ContentType;
import com.adobe.primetime.reference.utils.SerializableNameValuePair;
import com.adobe.primetime.reference.utils.StringUtils;

import java.io.Serializable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

public class ReferencePlayerFeedItemAdapter implements IFeedItemAdapter {
	private final String LOG_TAG = "[Player]::ReferencePlayerFeedItemAdapter";

	// Entry attributes
	protected static final String NAME_ID = "id";
	protected static final String NAME_TITLE = "title";
	protected static final String NAME_DESCRIPTION = "description";
	protected static final String NAME_CATEGORIES = "categories";
	protected static final String NAME_KEYWORDS = "keywords";
	protected static final String NAME_ISLIVE = "isLive";
	protected static final String NAME_CONTENT = "content";
	protected static final String NAME_CONTENT_FORMAT = "format";
	protected static final String NAME_CONTENT_URL = "url";
	protected static final String NAME_CONTENT_LANGUAGE = "language";
	protected static final String NAME_THUMBNAILS = "thumbnails";
	protected static final String NAME_THUMBNAILS_WIDTH = "width";
	protected static final String NAME_THUMBNAILS_URL = "url";
	protected static final String NAME_METADATA = "metadata";
	protected static final String NAME_METADATA_AD = "ad";
    protected static final String NAME_METADATA_ENTITLEMENT = "entitlement";
	protected static final String NODE_NAME_SIGNALING_MODE = "signaling-mode";
	protected static final String NODE_NAME_DISABLE_CONTENT_CACHE = "disable-cache";

	// Entry attribute values
	protected static final String VALUE_TRUE = "true";
	protected static final String VALUE_FALSE = "false";

    // Entitlement Metadata attributes
    protected static final String METADATA_ENTITLEMENT_ID = "id";

	// Time-range Metadata attributes
	protected final String NODE_NAME_METADATA_TIME_RANGES = "time-ranges";
    protected final String METADATA_TIME_RANGE_TYPE = "type";
    protected final String METADATA_TIME_RANGE_LIST = "time-range-list";
    protected final String METADATA_TIME_RANGE_BEGIN = "begin";
    protected final String METADATA_TIME_RANGE_END = "end";
    protected final String METADATA_TIME_RANGE_REPLACEMENT_DURATION = "replacement-duration";
    protected final String VALUE_TIME_RANGE_TYPE_DELETE = "delete";
    protected final String VALUE_TIME_RANGE_TYPE_MARK = "mark";
    protected final String VALUE_TIME_RANGE_TYPE_REPLACE = "replace";
	
	// Ad Metadata attributes
	protected static final String METADATA_AD_TYPE = "type";
	protected static final String METADATA_AD_DETAILS = "details";

	// Ad Metadata - Primetime Ads
	protected static final String VALUE_AD_TYPE_PRIMETIME_ADS = "Primetime Ads";
	protected static final String NODE_NAME_AD_ZONEID = "zoneid";
	protected static final String NODE_NAME_AD_MEDIAID = "mediaid";
    protected static final String NODE_NAME_AD_DEFAULT_MEDIAID = "default-mediaid";
	protected final String NODE_NAME_METADATA_AD_FORCE_HTTPS = "force-https";
	protected final String NODE_NAME_FORCE_HTTPS_ADSERVER_CALLS = "adServer";
	protected static final String NODE_NAME_AD_DOMAIN = "domain";
	protected static final String NODE_NAME_AD_TARGETING = "targeting";
    protected static final String NODE_NAME_AD_CUSTOM_PARAMETERS = "custom-parameters";
	protected static final String NODE_NAME_KEY = "key";
	protected static final String NODE_NAME_VALUE = "value";
    protected static final String NODE_NAME_USER_AGENT = "user-agent";
	protected static final String NODE_CONFIG_LOCATION = "crs-rules";
    protected static final String NODE_NAME_AD_REQUEST_TIMEOUT = "adRequestTimeout";
	protected static final String NODE_NAME_DELAY_AD_LOADING = "delayAdLoading";
	protected static final String NODE_NAME_DELAY_AD_LOADING_TOLERANCE = "delayAdLoadingTolerance";

	// Ad Metadata - Direct Ad Breaks
	protected static final String VALUE_AD_TYPE_DIRECT_AD_BREAKS = "Direct Ad Breaks";
	protected static final String NODE_NAME_ADBREAKS = "ad-breaks";

	// Ad Metadata - Custom Ad Provider
	protected static final String VALUE_AD_TYPE_CUSTOM_AD_PROVIDER = "Custom Ad Provider";
	protected static final String NODE_NAME_CUSTOM_AD_PROVIDER_DOMAIN = "domain";
	protected static final String NODE_NAME_CUSTOM_AD_PROVIDER_AD_PATTERN = "ad-pattern";
	protected static final String NODE_NAME_CUSTOM_AD_PROVIDER_TIME = "time";
	protected static final String NODE_NAME_CUSTOM_AD_PROVIDER_COUNT = "count";
	protected static final String NODE_NAME_CUSTOM_AD_PROVIDER_DURATION = "duration";
	protected static final String NODE_NAME_CUSTOM_AD_PROVIDER_CONTENT_METADATA = "content-metadata";
	protected static final String NODE_NAME_CREATIVE_REPACKAGING_ENABLED = "creative-repackaging";
    protected static final String NODE_NAME_CREATIVE_REPACKAGING_FORMAT = "creative-repackaging-format";
    protected static final String NODE_NAME_CREATIVE_REPACKAGING_DOMAIN = "creative-repackaging-domain";
    protected static final String NODE_NAME_FALLBACK_ON_INVALID_CREATIVE = "fallback-on-invalid-creative";

    // Video Analytics Metadata
    protected static final String NODE_NAME_METADATA_VIDEO_ANALYTICS = "video-analytics";

	protected static final String NODE_NAME_PROTECTIONDATA = "protectionData";

	protected final JSONObject entryObject;
	protected String smallThumbnailURL = null;
	protected String largeThumbnailURL = null;
	protected List<SerializableNameValuePair> properties = null;
    private Map<String, List<ContentRenditionInfo>> contentRenditions = null;
	protected Metadata resourceMetadata = null;
    protected AdvertisingMetadata advertisingMetadata;
    protected AdSignalingMode adSignalingMode;
	protected ProtectionData protectionData = null;
	/**
	 * Class constructor. The ReferencePlayerFeedItemAdapter is used for
	 * retrieving specific data for a given content item
	 * 
	 * @param entryObject
	 *            - one content item in JSON format
	 */
	protected ReferencePlayerFeedItemAdapter(JSONObject entryObject) {
		this.entryObject = entryObject;
        contentRenditions = new HashMap<String, List<ContentRenditionInfo>>();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getId() {
		return getString(entryObject, NAME_ID);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getTitle() {
		return getString(entryObject, NAME_TITLE);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public ContentType getContentType() {
        String isLive = getString(entryObject, NAME_ISLIVE);
		if (isLive != null && isLive.equalsIgnoreCase(VALUE_TRUE)) {
			return ContentType.live;
		} else {
			return ContentType.vod;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Metadata getResourceMetadata() {
		if (resourceMetadata == null) {
			parseMetadata();
		}

		return resourceMetadata;
	}

    /**
     * {@inheritDoc}
     */
    @Override
    public AdvertisingMetadata getAdvertisingMetadata() {
        // after parsing the metadata, advertisingMetadata may still be null
        // so check resourceMetadata as it is initialized during parseMetadata
        if (resourceMetadata == null) {
            parseMetadata();
        }

        return advertisingMetadata;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AdSignalingMode getAdSignalingMode() {
        return adSignalingMode == null ? AdSignalingMode.DEFAULT : adSignalingMode;
    }

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getStreamThumbnailLarge() {
		if (this.largeThumbnailURL == null) {
			parseThumbnailUrls();
		}

		return this.largeThumbnailURL;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getStreamThumbnailSmall() {
		if (this.smallThumbnailURL == null) {
			parseThumbnailUrls();
		}

		return this.smallThumbnailURL;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<SerializableNameValuePair> getProperties() {
		if (this.properties == null) {
			parseProperties();
		}

		return this.properties;
	}

    /**
     * {@inheritDoc}
     */
    @Override
    public List<ContentRenditionInfo> getContentRenditionsByType(String type) {
		if (contentRenditions.isEmpty()) {
			parseContent();
		}

        return contentRenditions.get(type);
    }

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<ContentRenditionInfo> getContentRenditions() {
		if (contentRenditions.isEmpty()) {
			parseContent();
		}

        List<ContentRenditionInfo> result = new ArrayList<ContentRenditionInfo>();
        for (Map.Entry<String, List<ContentRenditionInfo>> me : contentRenditions.entrySet())
        {
            result.addAll(me.getValue());
        }

		return result;
	}

	/**
	 * Gets field value from JSON object given field name
	 * 
	 * @param jsonObject
	 *            - JSON object to search in
	 * @param fieldName
	 *            - field name to be searched for
	 * @return String - field value or null if field name does not exist or
	 *         field value is empty
	 */
    protected String getString(JSONObject jsonObject, String fieldName) {
        return getString(jsonObject, fieldName, null);
    }

	protected String getString(JSONObject jsonObject, String fieldName, String defaultValue) {
		try {
			if (jsonObject.has(fieldName) && !jsonObject.isNull(fieldName)) {
				return jsonObject.getString(fieldName);
			}
		} catch (JSONException e) {
			PrimetimeReference.logger.w(LOG_TAG + "::getString", "Error getting field '" + fieldName + "' from JSON: " + e.getMessage());
		}

		return defaultValue;
	}

    protected boolean getBoolean(JSONObject jsonObject, String fieldName, boolean defaultValue) {
        String result = getString(jsonObject, fieldName);
        if ("true".equalsIgnoreCase(result)) {
            return true;
        }
        else if ("false".equalsIgnoreCase(result)) {
            return false;
        }
        else {
            return defaultValue;
        }
    }

	/**
	 * Sets the small and large thumb URLs
	 */
	protected void parseThumbnailUrls() {
		if (getString(entryObject, NAME_THUMBNAILS) == null) {
			return;
		}

		JSONObject smallThumbnailObject = null;
		JSONObject largeThumbnailObject = null;
		try {
			JSONArray content = entryObject.getJSONArray(NAME_THUMBNAILS);
			for (int i = 0; i < content.length(); i++) {
				JSONObject contentObject = content.getJSONObject(i);
				String url = getString(contentObject, NAME_THUMBNAILS_URL);
				if (url != null && !url.isEmpty()) {
					if (smallThumbnailObject == null) {
						smallThumbnailObject = largeThumbnailObject = contentObject;
					} else {
						if (contentObject.getInt(NAME_THUMBNAILS_WIDTH) < smallThumbnailObject
								.getInt(NAME_THUMBNAILS_WIDTH)) {
							smallThumbnailObject = contentObject;
						} else if (contentObject.getInt(NAME_THUMBNAILS_WIDTH) > largeThumbnailObject
								.getInt(NAME_THUMBNAILS_WIDTH)) {
							largeThumbnailObject = contentObject;
						}
					}
				}
			}

			if (smallThumbnailObject != null) {
				this.smallThumbnailURL = smallThumbnailObject
						.getString(NAME_THUMBNAILS_URL);
			}

			if (largeThumbnailObject != null) {
				this.largeThumbnailURL = largeThumbnailObject
						.getString(NAME_THUMBNAILS_URL);
			}
		} catch (JSONException e) {
			PrimetimeReference.logger.e(LOG_TAG + "::parseThumbnailUrls",
					"Error parsing thumbnail list: " + e.getMessage());
		}
	}

	/**
	 * Sets the category, which is the list of categories tagged for the
	 * content, can be used by application to enhance user experience Sets the
	 * key words, a list of comma separated keywords also used to enhance user
	 * experience
	 */
	protected void parseProperties() {
		this.properties = new Vector<SerializableNameValuePair>();
		String categoriesStr = getString(entryObject, NAME_CATEGORIES);

		if (categoriesStr != null) {
			properties.add(new SerializableNameValuePair(NAME_CATEGORIES,
					categoriesStr));
		}

		String keywords = getString(entryObject, NAME_KEYWORDS);
		if (keywords != null && !keywords.isEmpty()) {
			properties.add(new SerializableNameValuePair(NAME_KEYWORDS,
                    keywords));
		}
	}

	/**
	 * Populates the list of ContentRenditionInfo objects for this content,
	 * content renditions currently can either be in the HDS or HLS format
	 */
	protected void parseContent() {
		if (getString(entryObject, NAME_CONTENT) == null) {
			return;
		}

		try {
			JSONArray content = entryObject.getJSONArray(NAME_CONTENT);
			for (int i = 0; i < content.length(); i++) {
				JSONObject contentObject = content.getJSONObject(i);

				String formatStr = getString(contentObject, NAME_CONTENT_FORMAT);
                MediaResource.Type resourceType = null;
                // Try to find content type based on MediaResource Type name
                try {
                    resourceType = MediaResource.Type.valueOf(formatStr.toUpperCase());
                }
                catch (IllegalArgumentException e)
                {
                    // content format did not match any MediaResource.Type name
                }

                // Did not find content type by name, so try finding by identifier
                if (resourceType == null) {
                    for (MediaResource.Type type : MediaResource.Type.values())
                    {
                        if (type.getValue().equalsIgnoreCase(formatStr)) {
                            resourceType = type;
                            break;
                        }
                    }
                }

				String url = getString(contentObject, NAME_CONTENT_URL);
				String language = getString(contentObject, NAME_CONTENT_LANGUAGE);
				List<SerializableNameValuePair> renditionProperties = new ArrayList<SerializableNameValuePair>();
				renditionProperties.add(new SerializableNameValuePair(NAME_CONTENT_LANGUAGE, language));
				ContentRenditionInfo info = new ContentRenditionInfo(resourceType.name(), url, renditionProperties);

                if (!contentRenditions.containsKey(resourceType.name()))
                {
                    contentRenditions.put(resourceType.name(), new ArrayList<ContentRenditionInfo>());
                }

                contentRenditions.get(resourceType.name()).add(info);
			}

		} catch (JSONException e) {
			PrimetimeReference.logger.e(LOG_TAG + "::parseContent",
					"Error parsing content list: " + e.getMessage());
		}
	}

	/**
	 * Parses the metadata of the content and populates the Metadat object,
	 * which contains the key/value pair pointing to a specific Metadata
	 * type like AuditudeSettings, direct ad breaks in a JSON metadata string,
	 * custom ad markers metadata, or any custom Metadata subclass with a
	 * custom AdProivder implementation.
	 */
	protected void parseMetadata() {
		if (getString(entryObject, NAME_METADATA) == null) {
			return;
		}

		try {
			resourceMetadata = new Metadata();

			JSONObject metadataObject = entryObject.getJSONObject(NAME_METADATA);

            try
            {
                // parse AdvertisingMetadata from metadata.ad object
                if (metadataObject.has(NAME_METADATA_AD))
                {
                    JSONObject metadataAdObject = metadataObject.getJSONObject(NAME_METADATA_AD);

                    String adType = metadataAdObject.getString(METADATA_AD_TYPE);
                    JSONObject adDetailsObject = metadataAdObject.getJSONObject(METADATA_AD_DETAILS);

                    if (adType.equals(VALUE_AD_TYPE_PRIMETIME_ADS))
                    {
                        advertisingMetadata = createAuditudeMetadata(adDetailsObject);
                    }
                    else if (adType.equals(VALUE_AD_TYPE_DIRECT_AD_BREAKS))
                    {
                        advertisingMetadata = createBasicMetadataFrom(adDetailsObject);
                    }
                    else if (adType.equals(VALUE_AD_TYPE_CUSTOM_AD_PROVIDER))
                    {
                        advertisingMetadata = createCustomAdProvider(adDetailsObject);
                    }

                }

                // parse AdSignalingMode from metadata object
                if (metadataObject.has(NODE_NAME_SIGNALING_MODE)) {
					adSignalingMode = AdSignalingMode.createFrom(metadataObject.getString(NODE_NAME_SIGNALING_MODE));
                }

            }
            catch (JSONException e)
            {
                PrimetimeReference.logger.w(LOG_TAG + "::parseMetadata",
                        "Error parsing ad metadata list: " + e.getMessage());
            }

            try
            {
                // add entitlement metadata if present
                JSONObject entitlementObject = metadataObject.getJSONObject(NAME_METADATA_ENTITLEMENT);
                if (entitlementObject != null)
                {
                    String resourceId = entitlementObject.getString(METADATA_ENTITLEMENT_ID);
                    if (resourceId != null)
                    {
                        EntitlementMetadata entitlementMetadata = new EntitlementMetadata();
                        entitlementMetadata.setValue(EntitlementMetadata.RESOURCE_ID_KEY, resourceId);

                        resourceMetadata.setMetadata(EntitlementMetadata.ENTITLEMENT_METADATA, entitlementMetadata);
                    }
                }
            }
            catch (JSONException e)
            {
                PrimetimeReference.logger.w(LOG_TAG + "::parseMetadata",
                        "Error parsing entitlement metadata list: " + e.getMessage());
            }

            /*try
            {
                if (metadataObject.has(NODE_NAME_METADATA_VIDEO_ANALYTICS))
                {
                    resourceMetadata.setValue(VideoAnalyticsMetadata.VIDEO_ANALYTICS_METADATA_KEY, metadataObject.getJSONObject(NODE_NAME_METADATA_VIDEO_ANALYTICS).toString());
                }
            }
            catch (JSONException e)
            {
                PrimetimeReference.logger.w(LOG_TAG + "::parseMetadata",
                        "Error parsing video analytics metadata list: " + e.getMessage());
            }*/


		}
        catch (JSONException e)
        {
			PrimetimeReference.logger.e(LOG_TAG + "::parseMetadata",
					"Error parsing metadata list: " + e.getMessage());
		}
	}

    /**
	 * Creates Custom Ad Provider Metadata from JSON object This is only an
	 * example of how a customer can have custom ad data in their feeds and
	 * implement their own AdProvider to resolve the ad data to ad content urls
	 * and Placement info
	 * 
	 * @param jsonObject
	 *            - to be parsed
	 * @return CustomAdProviderMetadata -
	 */
	protected CustomAdProviderMetadata createCustomAdProvider(
			JSONObject jsonObject) {
		CustomAdProviderMetadata result = new CustomAdProviderMetadata();

		try {
			String domain = jsonObject
					.getString(NODE_NAME_CUSTOM_AD_PROVIDER_DOMAIN);
			result.setDomain(domain);

			JSONArray jsonArray = jsonObject
					.getJSONArray(NODE_NAME_CUSTOM_AD_PROVIDER_AD_PATTERN);

			ArrayList<CustomAdProviderMetadata.AdPattern> adPatternList = new ArrayList<CustomAdProviderMetadata.AdPattern>();
			for (int i = 0; i < jsonArray.length(); i++) {
				JSONObject aJsonObject = jsonArray.getJSONObject(i);
				Long time = Long.parseLong(aJsonObject
						.getString(NODE_NAME_CUSTOM_AD_PROVIDER_TIME));
				Long count = Long.parseLong(aJsonObject
						.getString(NODE_NAME_CUSTOM_AD_PROVIDER_COUNT));
				Long duration = Long.parseLong(aJsonObject
						.getString(NODE_NAME_CUSTOM_AD_PROVIDER_DURATION));

				CustomAdProviderMetadata.AdPattern adPattern = new CustomAdProviderMetadata.AdPattern(
						time, count, duration);
				adPatternList.add(adPattern);
			}
			result.setAdPatternList(adPatternList);

			Metadata contentMetadata = getMetadataFromJson(jsonObject,
                    NODE_NAME_CUSTOM_AD_PROVIDER_CONTENT_METADATA);
			result.setContentMetadata(contentMetadata);
		} catch (JSONException e) {
			PrimetimeReference.logger.e(LOG_TAG + "::createCustomAdProvider",
					"Error parsing custom ad provider: " + e.getMessage());
		}

		return result;
	}

	/**
	 * Creates and returns an AuditudeSettings object
	 * 
	 * @param jsonObject
	 *            - to be parsed
	 * @return AuditudeSettings - set with the Auditude domain, media id, zone
	 *         id, targeting parameters, and creative packaging option.
	 */
	protected AdvertisingMetadata createAuditudeMetadata(JSONObject jsonObject) {
		AuditudeSettings result = new AuditudeSettings();

		try {
            String value;
            if ((value = getString(jsonObject, NODE_NAME_AD_ZONEID)) != null) {
                result.setZoneId(value);
            }
            if ((value = getString(jsonObject, NODE_NAME_AD_MEDIAID)) != null) {
                result.setMediaId(value);
            }
            if ((value = getString(jsonObject, NODE_NAME_AD_DOMAIN)) != null) {
                result.setDomain(value);
            }
            if ((value = getString(jsonObject, NODE_NAME_AD_DEFAULT_MEDIAID)) != null) {
                result.setDefaultMediaId(value);
            }
            if ((value = getString(jsonObject, NODE_NAME_USER_AGENT)) != null) {
                result.setUserAgent(value);
            }
			if ((value = getString(jsonObject, NODE_CONFIG_LOCATION)) != null) {
				result.setCRSRulesJsonURL(value);
			} 
			
            if (jsonObject.has(NODE_NAME_AD_REQUEST_TIMEOUT)) {
                result.setAdResolutionTimeout(jsonObject.getInt(NODE_NAME_AD_REQUEST_TIMEOUT));
            }
			if (jsonObject.has(NODE_NAME_DELAY_AD_LOADING)) {
				result.setDelayAdLoading(jsonObject.getBoolean(NODE_NAME_DELAY_AD_LOADING));
			}
            if (jsonObject.has(NODE_NAME_DELAY_AD_LOADING_TOLERANCE)) {
				result.setDelayAdLoadingTolerance(jsonObject.getDouble(NODE_NAME_DELAY_AD_LOADING_TOLERANCE));
			}

			if (jsonObject.has(NODE_NAME_METADATA_AD_FORCE_HTTPS)) {
				JSONObject forceHttpsAdCalls =  jsonObject.getJSONObject(NODE_NAME_METADATA_AD_FORCE_HTTPS);
				if (forceHttpsAdCalls.has(NODE_NAME_FORCE_HTTPS_ADSERVER_CALLS)) {
					result.getForceHttpsConfiguration().setAdServerCalls(forceHttpsAdCalls.getBoolean(NODE_NAME_FORCE_HTTPS_ADSERVER_CALLS));
				}
			}

            Metadata targetingParameters = getMetadataFromJson(jsonObject, NODE_NAME_AD_TARGETING);
            result.setTargetingInfo(targetingParameters);

            Metadata customParameters = getMetadataFromJson(jsonObject, NODE_NAME_AD_CUSTOM_PARAMETERS);
            result.setCustomParameters(customParameters);

            result.setCreativeRepackagingEnabled(getBoolean(jsonObject, NODE_NAME_CREATIVE_REPACKAGING_ENABLED, false));
            result.setCreativeRepackagingFormat(getString(jsonObject, NODE_NAME_CREATIVE_REPACKAGING_FORMAT, "application/x-mpegURL"));
            result.setCreativeRepackagingDomain(getString(jsonObject, NODE_NAME_CREATIVE_REPACKAGING_DOMAIN, ""));
            result.setFallbackOnInvalidCreative(getBoolean(jsonObject, NODE_NAME_FALLBACK_ON_INVALID_CREATIVE, false));

		} catch (JSONException e) {
			PrimetimeReference.logger.e(LOG_TAG + "::createAuditudeMetadata",
					"Error parsing auditude metadata: " + e.getMessage());
		} catch (NumberFormatException e) {
			PrimetimeReference.logger.e(LOG_TAG + "::createAuditudeMetadata",
					"Error parsing auditude metadata: " + e.getMessage());
		}

		return result;
	}
	

	/**
	 * Creates and returns the direct ad break metadata from JSON object. The
	 * JSON Metadata String for direct ad breaks expects data in a certain
	 * format, see the Reference JSON structure for the format
	 * 
	 * @param jsonObject
	 *            - to be parsed
	 * @return AdvertisingMetadata - set with a string containing direct ad
	 *         break data
	 * @throws JSONException
	 *             if there is an error parsing the JSON object
	 */
	protected AdvertisingMetadata createBasicMetadataFrom(JSONObject jsonObject)
			throws JSONException {
		AdvertisingMetadata result = new AdvertisingMetadata();

		String serializedJSONAdBreaks = jsonObject.getString(NODE_NAME_ADBREAKS);
		result.setValue(MetadataKeys.JSON_METADATA_KEY.getValue(), serializedJSONAdBreaks);

		return result;
	}

	/**
	 * Creates Metadata from targeting parameters in the Auditude metadata,
	 * helper function of createAuditudeMetadata
	 * 
	 * @param jsonObject
	 *            - to be parsed
	 * @param nodeName
	 *            - to be searched for
	 * @return Metadata - metadata containing the key/value pairs
	 * @throws JSONException
	 *             if there is an error parsing the JSON object
	 */
	protected Metadata getMetadataFromJson(JSONObject jsonObject,
			String nodeName) throws JSONException {
		Metadata metadata = new Metadata();
		if (jsonObject.has(nodeName)) {
			JSONArray jsonArray = new JSONArray(jsonObject.getString(nodeName));
			for (int i = 0; i < jsonArray.length(); i++) {
				JSONObject jsonChild = jsonArray.getJSONObject(i);

				String key = null;
				if (jsonChild.has(NODE_NAME_KEY)) {
					key = jsonChild.getString(NODE_NAME_KEY).trim();
				}

				String value = null;
				if (jsonChild.has(NODE_NAME_VALUE)) {
					value = jsonChild.getString(NODE_NAME_VALUE).trim();
				}

				if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(value)) {
					metadata.setValue(key, value);
				}
			}
		}
		return metadata;
	}


	 ProtectionData getProtectionData() throws Exception 
	 {
		if(protectionData != null)
			return protectionData;

		if (getString(entryObject, NODE_NAME_PROTECTIONDATA) == null) {
			return null;
		}

		try {
	
				JSONObject protectionDataObject = entryObject.getJSONObject(NODE_NAME_PROTECTIONDATA);
                if(protectionDataObject != null)
					protectionData  = new ProtectionData(protectionDataObject);

				return protectionData;

		} catch (Exception e) {
			PrimetimeReference.logger.e(LOG_TAG + "::parseContent",
					"Error parsing content list: " + e.getMessage());
		}	
		
		return null;	
	}

	@Override
     public String getLicenseServerUrl() 
	 {
	 try {
		String url = getProtectionData().getLicenseServerUrl();
		return url;
		}
		catch (Exception e) {
		}

		return "";
	 }

	 @Override
     public String getDrmType() 
	 {
		try {	

			String type = getProtectionData().getDrmType();
			return type;
		}
			catch (Exception e) {
		}
		return "";
	 }


	    public class ProtectionData implements Serializable {
        private final String drmType;
        private final String licenseServerUrl;
        
        public ProtectionData(JSONObject jsonObject) throws Exception {
            try {
                
                if (jsonObject.has("com.widevine.alpha"))
                {
                    drmType = "com.widevine.alpha";
                    licenseServerUrl = jsonObject.getString("com.widevine.alpha");
                    
                } else if (jsonObject.has("com.microsoft.playready"))
                {
                    drmType = "com.microsoft.playready";
                    licenseServerUrl = jsonObject.getString("com.microsoft.playready");
                } else {
                    drmType = "";
                    licenseServerUrl = "";                    
                }
				PrimetimeReference.logger.i(LOG_TAG + "pavan: ::ProtectionData#ProtectionData" , " timepass");
				PrimetimeReference.logger.i(LOG_TAG + "pavan: drmtype", drmType);
				PrimetimeReference.logger.i(LOG_TAG + "pavan: licence  ", licenseServerUrl);
				 
            } catch (Exception e) {							
                PrimetimeReference.logger.e(LOG_TAG + "::ProtectionData#ProtectionData", e.getMessage());
                throw e;
            }
        }
        
        public String getDrmType() { return drmType; }
        public String getLicenseServerUrl() { return licenseServerUrl; }
    }

}
