/**
 * $URL$
 * DAAND
 * Copyright (C) 2004 - 2013, INSIDE Secure BV.  All rights reserved.
 */
package com.insidesecure.drm.android.reference.activities;

import android.app.Activity;
import android.app.Dialog;
import android.content.*;
import android.os.*;
import android.util.Log;
import android.view.*;
import android.widget.*;
import com.insidesecure.drm.android.reference.*;
import com.insidesecure.drm.android.reference.ContentHandler;
import com.insidesecure.drm.android.reference.Loader;
import com.insidesecure.drm.android.reference.xoplayer.R;
import com.insidesecure.drm.android.reference.views.utils.SwipeDetector;
import com.insidesecure.drm.android.reference.views.utils.SwipeDetectorListener;
import com.insidesecure.drmagent.*;
import com.npaw.youbora.lib6.utils.youboraconfigutils.YouboraConfigManager;

import java.io.*;
import java.net.*;
import java.util.*;

@SuppressWarnings("unchecked")
public class HomeActivity extends AbstractDRMActivity implements Loader.Callback
{
    private static final String TAG = "HomeActivity";

    private static DRMContentInfo sSelectedDrmContentInfo;

    private ListView mContentListHLS;
    private ListView mContentListDASH;
    private ListView mContentListPIFF;
    private ListView mContentListSS;
    private ListView mContentListMiscellaneous;

    private TextView mContentLabelHLS;
    private TextView mContentLabelDASH;
    private TextView mContentLabelPIFF;
    private TextView mContentLabelSS;
    private TextView mContentLabelMiscellaneous;

    private ContentListAdapter mContentListAdapterHLS;
    private ContentListAdapter mContentListAdapterDASH;
    private ContentListAdapter mContentListAdapterPIFF;
    private ContentListAdapter mContentListAdapterSS;
    private ContentListAdapter mContentListAdapterMiscellaneous;

    private List<String> mFailedDescriptors = new ArrayList<String>();
    protected DRMCacheInfo mDrmCacheInfo;

    private boolean mIsContentListRefreshing = false;
    private String mNewContentFileName = null;

    private static final int ABOUT_DIALOG = 1;
    private static final int CONTENT_INFO_DIALOG = 2;
    private static final int CONTENT_REFRESH_IN_PROGRESS = 3;
    private static final int UNTRUSTED_TIME = 4;
    private static final int DESCRIPTOR_LOADING_FAILED = 5;

    private static final int RETRIEVING_WEB_INITIATOR = 6;
    private static final int WEB_INITIATOR_RETRIEVED = 7;
    private static final int ERROR_RETRIEVING_WEB_INITIATOR = 8;
    private static final int INFO_WEB_INITIATOR_NOT_SUPPORTED = 10;
    private static final int OFFLINE_MODE = 11;
    private static final int INITIATE_PLAYBACK_FAILED = 12;

    private Loader mLoader;
    private Handler mHandler;

    private String getCustomData(final DRMContentInfo drmContentInfo)
    {
        return ContentHandler.getCustomData(drmContentInfo);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        Log.d(TAG, "onCreate");
        super.onCreate(savedInstanceState);

        mHandler = new Handler();
        mLoader = new Loader("HomeActivityLoader");

        setContentView(R.layout.home);

        initViews();

        startSavingLogsIfNeeded();

        Intent intent = getIntent();
        String fileName = intent.getStringExtra(LauncherActivity.EXTRA_NEW_CDESC);
        if(fileName != null)
        {
            mNewContentFileName = fileName;
        }

    }

    private void startSavingLogsIfNeeded() {
        if (getSharedPreferences(Constants.PREFERENCES_FILENAME, Context.MODE_PRIVATE)
                .getBoolean(Constants.PREFERENCES_SAVE_LOGS, false)) {
            Tools.saveLogs(this);
        }
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy");
        Tools.stopLogSavingProcess();
        super.onDestroy();
    }

    @Override
    protected void onStart()
    {
        super.onStart();

    }

    @Override
    protected void onResume() {
        refreshContentList();
        super.onResume();
    }

    protected void onPause()
    {
        // Always release the agent once we are done in this activity
        releaseDRMContentsInAdapters();

        sSelectedDrmContentInfo = null;

        super.onPause();
    }

    private  void releaseDRMContentsInAdapters() {
        for (DRMContentInfo drmContentInfo : mContentListAdapterHLS.mContentInfoList) {
            drmContentInfo.releaseDRMContent();
        }
        for (DRMContentInfo drmContentInfo : mContentListAdapterDASH.mContentInfoList) {
            drmContentInfo.releaseDRMContent();
        }
        for (DRMContentInfo drmContentInfo : mContentListAdapterPIFF.mContentInfoList) {
            drmContentInfo.releaseDRMContent();
        }
        for (DRMContentInfo drmContentInfo : mContentListAdapterSS.mContentInfoList) {
            drmContentInfo.releaseDRMContent();
        }
        for (DRMContentInfo drmContentInfo : mContentListAdapterMiscellaneous.mContentInfoList) {
            drmContentInfo.releaseDRMContent();
        }
    }

    private void initViews() {
        mContentListHLS = (ListView) findViewById(R.id.content_list_hls);
        mContentListHLS.setItemsCanFocus(true);
        mContentListDASH = (ListView) findViewById(R.id.content_list_dash);
        mContentListDASH.setItemsCanFocus(true);
        mContentListPIFF = (ListView) findViewById(R.id.content_list_piff);
        mContentListPIFF.setItemsCanFocus(true);
        mContentListSS = (ListView) findViewById(R.id.content_list_ss);
        mContentListSS.setItemsCanFocus(true);
        mContentListMiscellaneous = (ListView) findViewById(R.id.content_list_miscellaneous);
        mContentListMiscellaneous.setItemsCanFocus(true);

        mContentLabelHLS = (TextView) findViewById(R.id.content_list_label_hls);
        mContentLabelDASH = (TextView) findViewById(R.id.content_list_label_dash);
        mContentLabelPIFF = (TextView) findViewById(R.id.content_list_label_piff);
        mContentLabelSS = (TextView) findViewById(R.id.content_list_label_ss);
        mContentLabelMiscellaneous = (TextView) findViewById(R.id.content_list_label_miscellaneous);

        mContentListAdapterHLS = new ContentListAdapter();
        mContentListAdapterDASH = new ContentListAdapter();
        mContentListAdapterPIFF = new ContentListAdapter();
        mContentListAdapterSS = new ContentListAdapter();
        mContentListAdapterMiscellaneous = new ContentListAdapter();

        mContentListHLS.setAdapter(mContentListAdapterHLS);
        mContentListDASH.setAdapter(mContentListAdapterDASH);
        mContentListPIFF.setAdapter(mContentListAdapterPIFF);
        mContentListSS.setAdapter(mContentListAdapterSS);
        mContentListMiscellaneous.setAdapter(mContentListAdapterMiscellaneous);
    }

    private void clearContentListInAdapters() {
        mContentListAdapterHLS.mContentInfoList.clear();
        mContentListAdapterHLS.notifyDataSetChanged();

        mContentListAdapterDASH.mContentInfoList.clear();
        mContentListAdapterDASH.notifyDataSetChanged();

        mContentListAdapterPIFF.mContentInfoList.clear();
        mContentListAdapterPIFF.notifyDataSetChanged();

        mContentListAdapterSS.mContentInfoList.clear();
        mContentListAdapterSS.notifyDataSetChanged();

        mContentListAdapterMiscellaneous.mContentInfoList.clear();
        mContentListAdapterMiscellaneous.notifyDataSetChanged();
    }

    protected void displayDialog(int id)
    {
        showDialog(id);
    }

    private void refreshContentList()
    {
        if(mIsContentListRefreshing)
        {
            return;
        }

        mIsContentListRefreshing = true;

        clearContentListInAdapters();

        showDialog(HomeActivity.CONTENT_REFRESH_IN_PROGRESS);
        mFailedDescriptors.clear();

        setListFocus();

        // Initialize the agent instance - this does nothing if already initialized
        // This is a work around for certain 2.x device where this seemed required
        // DRMAgentDelegate.initialize(HomeActivity.this);

        ContentHandler.retrieveDRMContentInfos(HomeActivity.this, true, true, new ContentHandler.ContentRetrieverListener()
        {
            @Override
            public void checkProtection(final DRMContentInfo drmContentInfo)
            {
                drmContentInfo.mIsClearText = isClearText(drmContentInfo);
            }

            @Override
            public void drmContentRetrievalFinished(final List<DRMContentInfo> drmContentInfos)
            {
                showOrHideEmptyListViews();

                removeDialog(HomeActivity.CONTENT_REFRESH_IN_PROGRESS);

                // Check the secure time now
                if (!DRMAgentDelegate.DRMAGENT.isTimeTrusted())
                {
                    // Bad time
                    displayDialog(HomeActivity.UNTRUSTED_TIME);
                }

                if (!mFailedDescriptors.isEmpty())
                {
                    Log.i(TAG, "Processing of the following descriptors failed: " + mFailedDescriptors);
                    removeDialog(HomeActivity.DESCRIPTOR_LOADING_FAILED);
                    showDialog(HomeActivity.DESCRIPTOR_LOADING_FAILED);
                }

                mIsContentListRefreshing = false;
            }

            @Override
            public void drmContentInfoRetrieved(final DRMContentInfo drmContentInfo)
            {
                addContentToNeededList(drmContentInfo);
            }

            @Override
            public void drmContentInfoRetrievalFailed(final File name, final URL url)
            {
                mFailedDescriptors.add(name.getAbsolutePath());
            }
        });

    }

    private void addContentToNeededList(final DRMContentInfo drmContentInfo) {
        switch (drmContentInfo.mDRMContentFormat) {
            case HTTP_LIVE_STREAMING:
                mContentListAdapterHLS.addContentInfo(drmContentInfo);
                Collections.sort(mContentListAdapterHLS.mContentInfoList);
                mContentListAdapterHLS.notifyDataSetChanged();
                break;
            case MPEG_DASH:
                mContentListAdapterDASH.addContentInfo(drmContentInfo);
                Collections.sort(mContentListAdapterDASH.mContentInfoList);
                mContentListAdapterDASH.notifyDataSetChanged();
                break;
            case PIFF:
                mContentListAdapterPIFF.addContentInfo(drmContentInfo);
                Collections.sort(mContentListAdapterPIFF.mContentInfoList);
                mContentListAdapterPIFF.notifyDataSetChanged();
                break;
            case SMOOTH_STREAMING:
                mContentListAdapterSS.addContentInfo(drmContentInfo);
                Collections.sort(mContentListAdapterSS.mContentInfoList);
                mContentListAdapterSS.notifyDataSetChanged();
                break;
            default:
                mContentListAdapterMiscellaneous.addContentInfo(drmContentInfo);
                Collections.sort(mContentListAdapterMiscellaneous.mContentInfoList);
                mContentListAdapterMiscellaneous.notifyDataSetChanged();
                break;
        }
    }

    private void notifyDataSetChanged(final DRMContentFormat drmContentFormat) {
        switch (drmContentFormat) {
            case HTTP_LIVE_STREAMING:
                mContentListAdapterHLS.notifyDataSetChanged();
                break;
            case MPEG_DASH:
                mContentListAdapterDASH.notifyDataSetChanged();
                break;
            case PIFF:
                mContentListAdapterPIFF.notifyDataSetChanged();
                break;
            case SMOOTH_STREAMING:
                mContentListAdapterSS.notifyDataSetChanged();
                break;
            default:
                mContentListAdapterMiscellaneous.notifyDataSetChanged();
                break;
        }
    }

    private void showOrHideEmptyListViews() {

        mContentListHLS.setVisibility(mContentListAdapterHLS.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);
        mContentLabelHLS.setVisibility(mContentListAdapterHLS.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);

        mContentListDASH.setVisibility(mContentListAdapterDASH.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);
        mContentLabelDASH.setVisibility(mContentListAdapterDASH.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);

        mContentListPIFF.setVisibility(mContentListAdapterPIFF.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);
        mContentLabelPIFF.setVisibility(mContentListAdapterPIFF.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);

        mContentListSS.setVisibility(mContentListAdapterSS.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);
        mContentLabelSS.setVisibility(mContentListAdapterSS.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);

        mContentListMiscellaneous.setVisibility(mContentListAdapterMiscellaneous.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);
        mContentLabelMiscellaneous.setVisibility(mContentListAdapterMiscellaneous.mContentInfoList.size() == 0 ? View.GONE : View.VISIBLE);

        setListFocus();
    }

    private void setListFocus()
    {
        if(mContentListHLS.getVisibility()==View.VISIBLE)
            mContentListHLS.requestFocus();
        else if(mContentListDASH.getVisibility()==View.VISIBLE)
            mContentListDASH.requestFocus();
        else if(mContentListPIFF.getVisibility()==View.VISIBLE)
            mContentListPIFF.requestFocus();
        else if(mContentListSS.getVisibility()==View.VISIBLE)
            mContentListSS.requestFocus();
        else if(mContentListMiscellaneous.getVisibility()==View.VISIBLE)
            mContentListMiscellaneous.requestFocus();
    }

    private void deleteFailedDescriptors()
    {
        for (String cdescFilename : mFailedDescriptors)
        {
            File file = new File(cdescFilename);
            if (!file.delete())
                file.deleteOnExit();
        }
        refreshContentList();
    }

    @Override
    protected Dialog onCreateDialog(final int id)
    {
        Dialog dialog = null;

        switch (id)
        {
            case HomeActivity.ABOUT_DIALOG:
                dialog = createAboutDialog();
                break;
            case HomeActivity.CONTENT_INFO_DIALOG:
                dialog = createContentInfoDialog();
                break;
            case HomeActivity.CONTENT_REFRESH_IN_PROGRESS:
                dialog = Tools.createSimpleProgressDialog(this, getText(R.string.dialog_title), getText(R.string.dialog_text_refresh_content));
                break;
            case HomeActivity.UNTRUSTED_TIME:
                dialog = createAlertDialog(HomeActivity.UNTRUSTED_TIME, getText(R.string.dialog_text_untrusted_time));
                break;
            case HomeActivity.DESCRIPTOR_LOADING_FAILED:
                dialog = createDescriptorLoadingFailedDialog();
                break;
            case RETRIEVING_WEB_INITIATOR:
                dialog = Tools.createSimpleProgressDialog(this, getText(R.string.dialog_title), getText(R.string.dialog_text_retrieving_web_initiator));
                break;
            case WEB_INITIATOR_RETRIEVED:
                dialog = createAlertDialog(HomeActivity.WEB_INITIATOR_RETRIEVED, getText(R.string.dialog_text_web_initiator_retrieved));
                break;
            case ERROR_RETRIEVING_WEB_INITIATOR:
                dialog = createAlertDialog(HomeActivity.ERROR_RETRIEVING_WEB_INITIATOR, getText(R.string.dialog_text_web_initiator_retrieval_error));
                break;
            case INFO_WEB_INITIATOR_NOT_SUPPORTED:
                dialog = createAlertDialog(HomeActivity.INFO_WEB_INITIATOR_NOT_SUPPORTED, getText(R.string.dialog_text_web_initiator_not_supported));
                break;
            case OFFLINE_MODE:
                dialog = createAlertDialog(HomeActivity.OFFLINE_MODE, getText(R.string.dialog_text_offline_mode));
                break;
            case INITIATE_PLAYBACK_FAILED:
                dialog = createAlertDialog(HomeActivity.INITIATE_PLAYBACK_FAILED, getText(R.string.dialog_text_initiate_playback_failed));
                break;
            default:
        }
        return dialog;
    }

    private Dialog createAlertDialog(final int dialogID, final CharSequence text)
    {
        final DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int id)
            {
                removeDialog(dialogID);
            }
        };
        return Tools.createAlertDialog(this, getText(R.string.dialog_title), text, false, "Ok", positiveListener, null, null);
    }

    private Dialog createAboutDialog()
    {
        final Dialog dialog = new Dialog(this);
        dialog.setContentView(R.layout.about_dialog);
        dialog.setTitle(getText(R.string.about_title));

        final TextView textCopyright = (TextView) dialog.findViewById(R.id.text_copyright);
        textCopyright.setText(getText(R.string.about_copyright));

        final TextView text = (TextView) dialog.findViewById(R.id.text);
        text.setText(getString(R.string.not_available));

        dialog.setOwnerActivity(HomeActivity.this);

        try
        {
            String s = DRMAgentDelegate.getDRMInformation(this);
            if (s != null)
            {
                text.setText(s);
            }
        }
        catch (Exception ex)
        {
            Log.d(TAG, "Unable to retrieve version information: " + ex.getMessage(), ex);
        }

        dialog.setCanceledOnTouchOutside(true);
        dialog.setCancelable(true);

        return dialog;

    }

    protected Dialog createDescriptorLoadingFailedDialog()
    {
        final DialogInterface.OnClickListener negativeListener = new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                dialog.dismiss();
            }
        };

        final DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int id)
            {
                dialog.dismiss();
                deleteFailedDescriptors();
            }
        };
        return mFailedDescriptors.size() == 0 ? null : Tools.createAlertDialog(this, getText(R.string.dialog_title),
                Integer.toString(mFailedDescriptors.size()) + " " + getText(R.string.dialog_text_descriptor_loading_error) + "\n\n" + listFailingDescriptors(mFailedDescriptors),
                false, getText(R.string.dialog_button_ok), positiveListener, getText(R.string.dialog_button_cancel), negativeListener);
    }

    private String listFailingDescriptors(final List<String> mFailedDescriptors)
    {
        if (mFailedDescriptors == null || mFailedDescriptors.isEmpty())
        {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (Iterator<String> iterator = mFailedDescriptors.iterator(); iterator.hasNext(); )
        {
            String s = iterator.next();
            sb.append(s);
            if (iterator.hasNext())
            {
                sb.append('\n');
            }
        }
        return sb.toString();
    }

    private void updateAboutDialog(Dialog dialog, SecureDeviceResult secureDeviceResult)
    {

        if (secureDeviceResult != null)
        {
            final TextView text = (TextView) dialog.findViewById(R.id.text);
            text.setText(text.getText().toString().replace(getString(R.string.drm_security_state_retrieving),
                                                           secureDeviceResult.isSecureDevice() ? getString(R.string.drm_security_state_secure)
                                                                                               : getString(R.string.drm_security_state_compromised)));
        }
    }

    @Override
    protected void onPrepareDialog(final int id, final Dialog dialog)
    {
        super.onPrepareDialog(id, dialog);

        switch (id)
        {
            case HomeActivity.ABOUT_DIALOG:
                updateAboutDialog(dialog, DRMAgentDelegate.getSecureDeviceResult());
                break;
            case HomeActivity.CONTENT_INFO_DIALOG:
                updateContentInfoDialog(dialog, sSelectedDrmContentInfo);
                break;
            case HomeActivity.CONTENT_REFRESH_IN_PROGRESS:
                break;
            default:
        }

    }

    private Dialog createContentInfoDialog()
    {
        if (sSelectedDrmContentInfo != null)
        {
            final Dialog dialog = new Dialog(this);
            updateContentInfoDialog(dialog, sSelectedDrmContentInfo);
            return dialog;
        }
        return null;

    }

    private void updateContentInfoDialog(final Dialog dialog, final DRMContentInfo drmContentInfo)
    {
        dialog.setContentView(R.layout.content_info_dialog);
        dialog.setTitle(getText(R.string.content_info_dialog_title));
        dialog.setCancelable(true);
        dialog.setCanceledOnTouchOutside(true);

        setTextInTextView(dialog, R.id.content_info_uri, R.string.content_info_dialog_uri, drmContentInfo.mContentLocation.toString());
        setTextInTextView(dialog, R.id.content_info_title, R.string.content_info_dialog_content_title, drmContentInfo.mTitle);

        final TextView drmContentFormatTextView = (TextView) dialog.findViewById(R.id.content_format);
        switch (drmContentInfo.getDRMContent(HomeActivity.this).getDRMContentFormat())
        {
            case HTTP_LIVE_STREAMING:
                drmContentFormatTextView.setText(getString(R.string.content_info_dialog_content_format, "HTTP Live Streaming"));
                break;
            case MPEG_DASH:
                drmContentFormatTextView.setText(getString(R.string.content_info_dialog_content_format, "MPEG-DASH"));
                break;
            case SMOOTH_STREAMING:
                drmContentFormatTextView.setText(getString(R.string.content_info_dialog_content_format, "Smooth Streaming"));
                break;
            case PIFF:
                drmContentFormatTextView.setText(getString(R.string.content_info_dialog_content_format, "PIFF"));
                break;
        }

        final TextView hasCachedDataTextView = (TextView) dialog.findViewById(R.id.content_info_has_cached_data);
        hasCachedDataTextView.setVisibility(View.GONE);

        final TextView cachedBitrateTextView = (TextView) dialog.findViewById(R.id.content_info_cached_data_bitrate);
        cachedBitrateTextView.setVisibility(View.GONE);

        final TextView cachedAudioTrackNameTextView = (TextView) dialog.findViewById(R.id.content_info_cached_data_audio_track_name);
        cachedAudioTrackNameTextView.setVisibility(View.GONE);

        final TextView totalCachedDurationTextView = (TextView) dialog.findViewById(R.id.content_total_cached_duration);
        totalCachedDurationTextView.setVisibility(View.GONE);

        final TextView totalCachedSizeTextView = (TextView) dialog.findViewById(R.id.content_total_cached_size);
        totalCachedSizeTextView.setVisibility(View.GONE);

        // Handle whether or not to display cache information as well ..
        switch (drmContentInfo.getDRMContent(HomeActivity.this).getDRMContentFormat())
        {
            case SMOOTH_STREAMING:
            case HTTP_LIVE_STREAMING:
            case PIFF:
            case MPEG_DASH:
                mDrmCacheInfo = null;
                final DRMCacheState drmCacheState = getDRMCacheState(drmContentInfo);

                hasCachedDataTextView.setText(String.format(getString(R.string.content_info_dialog_has_cached_data_format), drmCacheState));
                hasCachedDataTextView.setVisibility(View.VISIBLE);

                if (drmCacheState != DRMCacheState.NONE)
                {
                    cachedBitrateTextView.setText(getString(R.string.content_info_dialog_cached_bitrate,getDRMCachedBitrate(drmContentInfo)));
                    cachedBitrateTextView.setVisibility(View.VISIBLE);

                    cachedAudioTrackNameTextView.setText(getString(R.string.content_info_dialog_cached_audio_track_name, getDRMCachedAudioTrackName(drmContentInfo)));
                    cachedAudioTrackNameTextView.setVisibility(View.VISIBLE);

                    totalCachedDurationTextView.setText(getString(R.string.content_info_dialog_total_cached_duration_format, getCachedDuration(drmContentInfo), getTotalDuration(drmContentInfo)));
                    totalCachedDurationTextView.setVisibility(View.VISIBLE);

                    totalCachedSizeTextView.setText(getString(R.string.content_info_dialog_total_cached_bytes_format, getCachedSize(drmContentInfo)));
                    totalCachedSizeTextView.setVisibility(View.VISIBLE);
                }
                break;
            default:
        }

        final DRMScheme drmScheme = retrieveDRMScheme(drmContentInfo);
        setTextInTextView(dialog, R.id.content_info_drm_scheme, R.string.content_info_dialog_drm_scheme, drmScheme.name());

        final TextView keyIDTextView = (TextView) dialog.findViewById(R.id.content_info_key_identifier);
        keyIDTextView.setVisibility(View.GONE);

        final TextView validFromTextView = (TextView) dialog.findViewById(R.id.content_info_license_valid_from);
        validFromTextView.setVisibility(View.GONE);

        final TextView validToTextView = (TextView) dialog.findViewById(R.id.content_info_license_valid_to);
        validToTextView.setVisibility(View.GONE);

        // Only display the following information if the content is DRM protected
        if (retrieveDRMScheme(drmContentInfo) != DRMScheme.CLEARTEXT)
        {
            final String contentID = drmContentInfo.getDRMContent(HomeActivity.this).getMetaData(DRMMetaData.CONTENT_ID);
            if (contentID != null)
            {
                keyIDTextView.setText(String.format(getString(R.string.content_info_dialog_key_identifier), contentID));
                keyIDTextView.setVisibility(View.VISIBLE);
            }

            DRMRights rights = drmContentInfo.getDRMContent(HomeActivity.this).getCachedDRMRights();
            if (rights.getStartDate() != null)
            {
                validFromTextView.setText(String.format(getString(R.string.content_info_dialog_valid_from), formatDate(rights.getStartDate())));
                validFromTextView.setVisibility(View.VISIBLE);
            }

            if (rights.getEndDate() != null)
            {
                validToTextView.setText(String.format(getString(R.string.content_info_dialog_valid_to), formatDate(rights.getEndDate())));
                validToTextView.setVisibility(View.VISIBLE);
            }
        }

        final TextView infoAudio = (TextView) dialog.findViewById(R.id.content_info_audio);
        infoAudio.setVisibility(View.GONE);

        final TextView infoVideo = (TextView) dialog.findViewById(R.id.content_info_video);
        infoVideo.setVisibility(View.GONE);

        StringBuilder stringBuilder = new StringBuilder();

        List<DRMContent.AudioTrack> audioTracks = drmContentInfo.getDRMContent(HomeActivity.this).getAudioTracks();
        for (Iterator<DRMContent.AudioTrack> iterator = audioTracks.iterator(); iterator.hasNext(); )
        {
            final DRMContent.AudioTrack next = iterator.next();
            stringBuilder.append(next.mName);

            stringBuilder.append("[");
            stringBuilder.append(next.mAudioCodec);
            stringBuilder.append("]");

            if (next.mLanguage != null)
            {
                stringBuilder.append("(");
                stringBuilder.append(next.mLanguage);
                stringBuilder.append(")");
            }

            if (iterator.hasNext())
            {
                stringBuilder.append(", ");
            }
        }


        if (stringBuilder.toString().length() > 0)
        {
            setTextInTextView(dialog, R.id.content_info_audio, R.string.content_info_dialog_content_audio, stringBuilder.toString());
            infoAudio.setVisibility(View.VISIBLE);
        }
        setTextInTextView(dialog, R.id.content_info_islive, R.string.content_info_dialog_islive, drmContentInfo.getDRMContent(HomeActivity.this).isLive() ? getString(R.string.yes) : getString(R.string.no));

        final String numberVideoStreams;
        final List<DRMContent.VideoQualityLevel> videoQualityLevels = drmContentInfo.getDRMContent(HomeActivity.this).getVideoQualityLevels();
        int numVideoQualityLevels = videoQualityLevels.size();
        if (numVideoQualityLevels > 1)
        {
            numberVideoStreams = "" + numVideoQualityLevels;
        }
        else if (numVideoQualityLevels == 1 && videoQualityLevels.get(0) != DRMContent.AUDIO_ONLY_VIDEO_QUALITY_LEVEL)
        {
            numberVideoStreams = "Single video stream";
        }
        else
        {
            numberVideoStreams = "N/A - Audio only";
        }
        setTextInTextView(dialog, R.id.content_info_video, R.string.content_info_dialog_num_video_streams, numberVideoStreams);
        infoVideo.setVisibility(View.VISIBLE);

        setTextInTextView(dialog, R.id.content_info_content_playable, R.string.content_info_dialog_playable, hasRights(drmContentInfo) ? getString(R.string.yes) : getString(R.string.no));

        dialog.setOwnerActivity(HomeActivity.this);

    }

    private String getTotalDuration(final DRMContentInfo drmContentInfo)
    {
        if (mDrmCacheInfo == null)
            mDrmCacheInfo = drmContentInfo.getDRMContent(HomeActivity.this).getDRMCacheInfo();
        return mDrmCacheInfo == null ? "0" : Long.toString(mDrmCacheInfo.getDuration());
    }

    protected String getCachedDuration(final DRMContentInfo drmContentInfo)
    {
        if (mDrmCacheInfo == null)
        {
            mDrmCacheInfo = drmContentInfo.getDRMContent(HomeActivity.this).getDRMCacheInfo();
        }
        return mDrmCacheInfo == null ? "0" : Long.toString(mDrmCacheInfo.getDurationCached());
    }

    protected DRMCacheState getDRMCacheState(final DRMContentInfo drmContentInfo)
    {
        if (mDrmCacheInfo == null)
            mDrmCacheInfo = drmContentInfo.getDRMContent(HomeActivity.this).getDRMCacheInfo();
        return mDrmCacheInfo == null ? DRMCacheState.NONE : mDrmCacheInfo.getDRMCacheState();
    }

    protected String getDRMCachedBitrate(final DRMContentInfo drmContentInfo)
    {
        if (mDrmCacheInfo == null)
            mDrmCacheInfo = drmContentInfo.getDRMContent(HomeActivity.this).getDRMCacheInfo();
        return mDrmCacheInfo == null ? ""+(-1) : mDrmCacheInfo.getCachedVideoQualityLevel() == DRMContent.SINGLE_VIDEO_QUALITY_LEVEL ? "Single video stream" : "" + mDrmCacheInfo.getCachedVideoQualityLevel().mBitRate;
    }

    protected String getDRMCachedAudioTrackName(final DRMContentInfo drmContentInfo)
    {
        if (mDrmCacheInfo == null)
            mDrmCacheInfo = drmContentInfo.getDRMContent(HomeActivity.this).getDRMCacheInfo();

        if (mDrmCacheInfo == null)
        {
            return "N/A";
        }

        final StringBuilder stringBuilder = new StringBuilder();

        for (Iterator<DRMContent.AudioTrack> iterator = mDrmCacheInfo.getCachedAudioTracks().iterator(); iterator.hasNext(); )
        {
            DRMContent.AudioTrack audioTrack = iterator.next();

            stringBuilder.append(audioTrack.mName);

            if (iterator.hasNext())
            {
                stringBuilder.append(", ");
            }

        }

        return stringBuilder.toString();
    }

    protected String getCachedSize(final DRMContentInfo drmContentInfo)
    {
        if (mDrmCacheInfo == null)
            mDrmCacheInfo = drmContentInfo.getDRMContent(HomeActivity.this).getDRMCacheInfo();
        return mDrmCacheInfo == null ? "0" : Tools.readableFileSize(mDrmCacheInfo.getCachedDataSize(false));
    }


    private void setTextInTextView(final Dialog dialog, int viewResourceID, int textResourceID, String text)
    {
        final TextView textView = (TextView) dialog.findViewById(viewResourceID);
        textView.setText(String.format(getString(textResourceID), text));
    }

    private String formatDate(final Date validFrom)
    {
        return validFrom.toString();
    }

    private void initiatePlayback(final DRMContentInfo info, final Class<? extends Activity> activityClass)
    {
        try
        {
            final Intent intent = new Intent(getBaseContext(), activityClass);

            final DRMContent drmContent = info.getDRMContent(HomeActivity.this);

            final PlaybackInfo playbackInfo = new PlaybackInfo(info.mTitle, drmContent.getDRMContentFormat(), drmContent.getDRMScheme(), info.mContentLocation);

            // Optional attributes are simply set
            playbackInfo.mLicenseAcquisitionURL = info.mLaURLOverride;
            playbackInfo.mCustomData = getCustomData(info);
            playbackInfo.mSubtitleFileLocation = info.mSubtitleFileLocation;


            intent.putExtra(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO, playbackInfo);

            startActivity(intent);
        }
        catch (DRMAgentException e)
        {
            switch (e.getDRMError())
            {
                case IO_HTTP_OFFLINE_MODE_ERROR:
                    showDialog(OFFLINE_MODE);
                    break;
                default:
                    showDialog(INITIATE_PLAYBACK_FAILED);
                    break;
            }
        }
        catch (Exception e)
        {
            Log.e(TAG,"Error while initiating playback: " + e.getMessage(),e);
            showDialog(INITIATE_PLAYBACK_FAILED);
        }

    }

    public boolean isClearText(final DRMContentInfo drmContentInfo)
    {
        return drmContentInfo.mDRMScheme == DRMScheme.CLEARTEXT;
    }

    public DRMScheme retrieveDRMScheme(final DRMContentInfo contentInfo)
    {
        return contentInfo.getDRMContent(HomeActivity.this).getDRMScheme();
    }

    public boolean hasRights(final DRMContentInfo drmContentInfo)
    {
        return drmContentInfo.getDRMContent(HomeActivity.this).getDRMScheme() == DRMScheme.CLEARTEXT
                || drmContentInfo.getDRMContent(HomeActivity.this).getDRMRights().getDRMRightsType() == DRMRights.DRMRightsType.VALID;
    }

    @Override
    public void onCreateContextMenu(ContextMenu contextMenu, View v, ContextMenu.ContextMenuInfo contextMenuInfo)
    {
        super.onCreateContextMenu(contextMenu, v, contextMenuInfo);

        final MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.content_item_context_menu, contextMenu);
        contextMenu.setHeaderTitle(getString(R.string.content_info_dialog_title_actions));

        final MenuItem playAdvancedMenuItem = contextMenu.findItem(R.id.play_advanced);
        playAdvancedMenuItem.setVisible(true);

        playAdvancedMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                if (sSelectedDrmContentInfo != null)
                {
                    initiatePlayback(sSelectedDrmContentInfo,AdvancedPlayActivity.class);
                }
                return true;
            }
        });

        final MenuItem performIntegrityCheckMenuItem = contextMenu.findItem(R.id.perform_integrity_check);
        performIntegrityCheckMenuItem.setVisible(true);

        performIntegrityCheckMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                if (sSelectedDrmContentInfo != null)
                {
                    performIntegrityCheck(sSelectedDrmContentInfo);
                    return true;
                }
                return false;
            }
        });

        final MenuItem clearCachedContentMenuItem = contextMenu.findItem(R.id.clear_cached_content);
        clearCachedContentMenuItem.setVisible(true);

        clearCachedContentMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                if (sSelectedDrmContentInfo != null)
                {
                    clearCachedData(sSelectedDrmContentInfo);
                    return true;
                }
                return false;
            }
        });

        final MenuItem rightsMenuGroupItem = contextMenu.findItem(R.id.rights_submenu);
        rightsMenuGroupItem.setVisible(true);

        final MenuItem deleteRightsMenuItem = contextMenu.findItem(R.id.delete_rights);
        deleteRightsMenuItem.setVisible(true);
        deleteRightsMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                if (sSelectedDrmContentInfo != null) {
                    sSelectedDrmContentInfo.getDRMContent(HomeActivity.this).deleteRights();

                    //if the protection is cleartext
                    sSelectedDrmContentInfo.mIsClearText = isClearText(sSelectedDrmContentInfo);

                    notifyDataSetChanged(sSelectedDrmContentInfo.mDRMContentFormat);
                    return true;
                }
                return false;
            }
        });

        MenuItem acquireRightsMenuItem = contextMenu.findItem(R.id.acquire_rights_using_webinitiator);
        acquireRightsMenuItem.setVisible(true);
        acquireRightsMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                if (sSelectedDrmContentInfo != null)
                {
                    if (LicenseAcquisitionHelper.canDoWebInitiator(HomeActivity.this, sSelectedDrmContentInfo))
                    {
                        showDialog(HomeActivity.RETRIEVING_WEB_INITIATOR);
                        Loader.Loadable loadable = new WebInitiatorLoadable(sSelectedDrmContentInfo, sSelectedDrmContentInfo.mWebInitiatorURL != null ? sSelectedDrmContentInfo.mWebInitiatorURL.toString() : null);
                        mLoader.startLoading(mHandler.getLooper(), loadable, HomeActivity.this);
                            }
                    else
                    {
                        showDialog(HomeActivity.INFO_WEB_INITIATOR_NOT_SUPPORTED);
                    }
                    return true;
                }
                return false;
            }
        });

        // Only display the delete rights for DRM protected content
        if (isClearText(sSelectedDrmContentInfo))
        {
            rightsMenuGroupItem.setVisible(false);
        }

    }

    private void performIntegrityCheck(final DRMContentInfo drmContentInfo)
    {
        Log.d(TAG, "Initiating integrity check of cached data for Content: " + drmContentInfo.mContentDescriptorLocation);
        ContentHandler.performIntegrityCheck(this, drmContentInfo);
    }

    protected void clearCachedData(final DRMContentInfo drmContentInfo)
    {
        Log.d(TAG, "Initiating Clearing of Cached data for Content: " + drmContentInfo.mContentDescriptorLocation);
        ContentHandler.clearCachedContent(this, drmContentInfo);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.home_menu, menu);

        //add streaming url
        MenuItem menuItem = menu.findItem(R.id.add_streaming_url);
        menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                Log.d(TAG, "Going to add AddURLActivity activity");
                startActivity(new Intent(getBaseContext(), DRMFusionAgentReferenceApplication.sAddURLActivityClass));
                return true;
            }
        });

        //refresh
        menuItem = menu.findItem(R.id.refresh_content_list);
        menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                Log.d(TAG, "Refreshing Home Page");
                refreshContentList();
                return true;
            }
        });

        //settings
        menuItem = menu.findItem(R.id.settings);
        menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                Log.d(TAG, "Going to Settings Activity");
                startActivity(new Intent(getBaseContext(), DRMFusionAgentReferenceApplication.sSettingsClass));
                return true;
            }
        });

        //about
        menuItem = menu.findItem(R.id.about);
        menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                Log.d(TAG, "Displaying About");
                showDialog(HomeActivity.ABOUT_DIALOG);
                return true;
            }
        });

        //YBOptions
        menuItem = menu.findItem(R.id.youbora_options);
        menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            public boolean onMenuItemClick(final MenuItem menuItem)
            {
                Log.d(TAG, "Displaying About");
                YouboraConfigManager.getInstance().showConfig(getBaseContext());
                return true;
            }
        });

        return true;
    }
    @Override
    public void onLoadCanceled(final Loader.Loadable loadable)
    {

    }

    @Override
    public void onLoadCompleted(final Loader.Loadable loadable)
    {
        if (loadable instanceof WebInitiatorLoadable)
        {
            dismissDialog(HomeActivity.RETRIEVING_WEB_INITIATOR);
            removeDialog(HomeActivity.RETRIEVING_WEB_INITIATOR);
            WebInitiatorLoadable webInitiatorLoadable = (WebInitiatorLoadable) loadable;
            boolean success = webInitiatorLoadable.successful();
            showDialog(success ? HomeActivity.WEB_INITIATOR_RETRIEVED : HomeActivity.ERROR_RETRIEVING_WEB_INITIATOR);
            if (success)
            {
                //if the protection is cleartext
                webInitiatorLoadable._drmContentInfo.mIsClearText = isClearText(
                        webInitiatorLoadable._drmContentInfo);
                notifyDataSetChanged(webInitiatorLoadable._drmContentInfo.mDRMContentFormat);
            }
        }
    }

    @Override
    public void onLoadError(final Loader.Loadable loadable, final IOException exception)
    {

    }

    public class ContentListAdapter extends BaseAdapter
    {
        private static final int DEL_ICON_VISIBILITY_DELAY = 5000;
        private List<DRMContentInfo> mContentInfoList;
        private List<Boolean> mItemsDeleteIconVisibility;

        private ContentListAdapter() {
            mContentInfoList = new ArrayList<DRMContentInfo>();
            mItemsDeleteIconVisibility = new ArrayList<Boolean>();
        }

        public View getView(final int position, View convertView, ViewGroup parent) {
            final DRMContentInfo drmContentInfo = mContentInfoList.get(position);

            if(mNewContentFileName != null && drmContentInfo.mContentDescriptorLocation.contains(mNewContentFileName)) {
                initiatePlayback(drmContentInfo, LicenseAcquisitionActivity.class);
                mNewContentFileName = null;
            }

            final View v;
            if (convertView == null) {
                v = getLayoutInflater().inflate(R.layout.content_icon, null);
            } else {
                v = convertView;
            }

            final ImageView deleteContentImg = (ImageView) v.findViewById(R.id.delete_img);
            final Handler disappearDeleteIconHandler = new Handler();
            final Runnable disappearRunnable = new Runnable() {
                @Override
                public void run() {
                    if(mContentInfoList.contains(drmContentInfo)) {
                        deleteContentImg.setVisibility(View.INVISIBLE);
                        mItemsDeleteIconVisibility.set(mContentInfoList.indexOf(drmContentInfo), false);
                    }
                }
            };

            if(!mItemsDeleteIconVisibility.get(position)) {
                deleteContentImg.setVisibility(View.INVISIBLE);
            } else {
                deleteContentImg.setVisibility(View.VISIBLE);
                disappearDeleteIconHandler.postDelayed(disappearRunnable, DEL_ICON_VISIBILITY_DELAY);
            }

            deleteContentImg.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    disappearDeleteIconHandler.removeCallbacks(disappearRunnable);

                    ContentHandler.deleteContent(drmContentInfo);
                    mItemsDeleteIconVisibility.remove(mContentInfoList.indexOf(drmContentInfo));
                    mContentInfoList.remove(drmContentInfo);
                    notifyDataSetChanged();
                    showOrHideEmptyListViews();
                }
            });

            v.setOnTouchListener(new SwipeDetector(new SwipeDetectorListener() {

                @Override
                public void onSwipedFromRightToLeft() {
                    deleteContentImg.setVisibility(View.INVISIBLE);
                    mItemsDeleteIconVisibility.set(position, false);
                    disappearDeleteIconHandler.removeCallbacks(disappearRunnable);

                }

                @Override
                public void onSwipedFromLeftToRight() {
                    deleteContentImg.setVisibility(View.VISIBLE);
                    mItemsDeleteIconVisibility.set(position, true);
                    disappearDeleteIconHandler.removeCallbacks(disappearRunnable);
                    disappearDeleteIconHandler.postDelayed(disappearRunnable, DEL_ICON_VISIBILITY_DELAY);
                }

                @Override
                public void onClick() {
                    sSelectedDrmContentInfo = drmContentInfo;
                    registerForContextMenu(v);
                    openContextMenu(v);
                    unregisterForContextMenu(v);
                }
            }));

            //set the title to needed textview
            final TextView contentTitle = (TextView) v.findViewById(R.id.icon_text);
            contentTitle.setText(drmContentInfo.mTitle);

            //if it is live the live_img will be visible
            v.findViewById(R.id.live_img).setVisibility(drmContentInfo.mStreamLive ? View.VISIBLE : View.GONE);

            final ImageView fileLocationImg = (ImageView) v.findViewById(R.id.file_location_img);
            if ((drmContentInfo.mDRMContentFormat == DRMContentFormat.CFF) ||
                (drmContentInfo.mDRMContentFormat == DRMContentFormat.PIFF))
            {
                //Checking if the content is local
                if (drmContentInfo.mContentLocation.getScheme() == null || !drmContentInfo.mContentLocation.getScheme().startsWith("http")) {
                    fileLocationImg.setImageResource(R.drawable.ic_local);
                } else {
                    fileLocationImg.setImageResource(R.drawable.ic_progressive);
                }
            }
            else
            {
                fileLocationImg.setVisibility(View.GONE);
            }

            //checking the protection of current content
            final ImageView fileRightsImg = (ImageView) v.findViewById(R.id.rights_img);
            switch (drmContentInfo.mDRMScheme)
            {
                case CLEARTEXT:
                    fileRightsImg.setImageResource(R.drawable.ic_cleartext);
                    break;
                case PLAYREADY:
                    fileRightsImg.setImageResource(R.drawable.ic_playready);
                    break;
                default:
                    fileRightsImg.setImageResource(R.drawable.ic_widevine);
                    break;
            }

            //initiate play imageview
            final ImageView playImg = (ImageView) v.findViewById(R.id.play_img);
            playImg.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
                    initiatePlayback(drmContentInfo, LicenseAcquisitionActivity.class);
                }
            });

            //this is used on android TV to open advanced play
            playImg.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {

                    sSelectedDrmContentInfo = drmContentInfo;
                    registerForContextMenu(v);
                    openContextMenu(v);
                    unregisterForContextMenu(v);
                    return true;
                }
            }) ;

            //initiate info imageview
            final ImageView infoImg = (ImageView) v.findViewById(R.id.info_img);
            infoImg.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    sSelectedDrmContentInfo = drmContentInfo;
                    Log.d(TAG, "Initiating Display of Content Information: " + sSelectedDrmContentInfo.mContentLocation);
                    showDialog(HomeActivity.CONTENT_INFO_DIALOG);
                }
            });

            return v;
        }

        @Override
        public int getViewTypeCount()
        {
            return 1;
        }

        public void addContentInfo(final DRMContentInfo drmContentInfo) {
            mContentInfoList.add(drmContentInfo);
            mItemsDeleteIconVisibility.add(false);
        }
        
        public final int getCount()
        {
            return mContentInfoList.size();
        }

        public final Object getItem(int position)
        {
            return mContentInfoList.get(position);
        }

        public final long getItemId(int position)
        {
            return position;
        }

        @Override
        public boolean isEmpty()
        {
            return mContentInfoList.isEmpty();
        }

        @Override
        public boolean areAllItemsEnabled()
        {
            return true;
        }

    }

    private class WebInitiatorLoadable implements Loader.Loadable
    {
        private DRMContentInfo _drmContentInfo;
        private String _url;
        private boolean _successful;

        public WebInitiatorLoadable(final DRMContentInfo drmContentInfo, final String url)
        {
            _drmContentInfo = drmContentInfo;
            _url = url;
        }

        @Override
        public void cancelLoad()
        {

        }

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

        @Override
        public void load() throws IOException, InterruptedException
        {
            Log.d(TAG, "Initiating web-initiator acquisition for: " + (_drmContentInfo != null ? _drmContentInfo.mContentLocation : null));
            _successful = LicenseAcquisitionHelper.retrieveAndInstallWebInitiator(HomeActivity.this, _drmContentInfo, _url);
        }

        public boolean successful()
        {
            return _successful;
        }
    }

}
