package com.viaccessorca.voplayerdemo.activities;

import static com.viaccessorca.voplayerdemo.Constants.DRM_AGENT_TYPE_AES;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.viaccessorca.common.VOUtils;
import com.viaccessorca.exceptions.VOException;
import com.viaccessorca.voplayer.VOPlayer;
import com.viaccessorca.voplayerdemo.Constants;
import com.viaccessorca.voplayerdemo.R;
import com.viaccessorca.voplayerdemo.adapters.DlVariantsAdapter;
import com.viaccessorca.voplayerdemo.database.DatabaseInfo;
import com.viaccessorca.voplayerdemo.database.MediaMetaInfoDB;
import com.viaccessorca.voplayerdemo.downloader.DLVariantListItem;
import com.viaccessorca.voplayerdemo.downloader.DownloadManager;
import com.viaccessorca.voplayerdemo.downloader.DownloaderWrapper;
import com.viaccessorca.voplayerdemo.downloader.DownloaderWrapper.OnErrorListener;
import com.viaccessorca.voplayerdemo.downloader.DownloaderWrapper.OnInfoListener;
import com.viaccessorca.voplayerdemo.downloader.DownloaderWrapper.OnPreparedListener;
import com.viaccessorca.voplayerdemo.drm.DrmManager;

public class DownloadActivity extends Activity implements
OnItemClickListener, OnErrorListener, OnPreparedListener, OnInfoListener
{
    private static final String TAG = "DownloadActivity";

    private DlVariantsAdapter variantsAdapter = null;
    private List<DLVariantListItem> variants = null;

    private TextView streamUrlTxt = null;
    private TextView streamInfoTxt = null;
    private LinearLayout waitingWheel = null;

    private String currentMediaId = null;
    private Uri currentStreamUri = null;
    private String vmxBootAddress = null;
    private String vmxCompanyName = null;
    private String drmAgentType = null;
    private String drmPersonalizationUrl = null;
    private String drmPersonalizationAppVersion = null;
    private String drmPersonalizationCustomData = null;
    private String drmLicenseAcquisitionUrl = null;
    private String drmLicenseAcquisitionUrlParameters = null;
    private String drmLicenseAcquisitionCustomData = null;
    private String drmLicenseAcquisitionCookie = null;

    private String  httpAuthUsername       = null;
    private String  httpAuthPassword       = null;
    private String  SSLCACertFilePath      = null;
    private int     SSLCACertFileType      = Constants.SSL_TYPE_UNKNOWN;
    private String  SSLClientCertFilePath  = null;
    private int     SSLClientCertFileType  = Constants.SSL_TYPE_UNKNOWN;
    private String  SSLClientKeyFilePath   = null;
    private int     SSLClientKeyFileType   = Constants.SSL_TYPE_UNKNOWN;
    private String  httpCustomHeader       = null;

    private DownloadManager dlMgr = null;
    private DownloaderWrapper downloader;

    private boolean downloadStarted = false;

    private int selectedItemId = -1;

    private Intent incomingIntent = null;

    // proxy settings
    private String mProxyUrl = null;
    private int mProxyPort = 0;
    private int mProxyType = 0;


    /**
     * Convert an SSL type into an int to correspond to structure in stack http
     * @param type SSL type
     * @return integer
     */
    private int changeOpSSLType(String type){
        if(type == null) return Constants.SSL_TYPE_UNKNOWN;
        if(type.equalsIgnoreCase("SSLTypePEM")){
            return Constants.SSL_TYPE_PEM;
        }else if (type.equalsIgnoreCase("SSLTypeDER")){
            return Constants.SSL_TYPE_DER;
        }else if (type.equalsIgnoreCase("SSLTypeENG")){
            return Constants.SSL_TYPE_ENG;
        }else{
            return Constants.SSL_TYPE_UNKNOWN;
        }
    }

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

        setContentView(R.layout.download_activity);

        ListView variantsList = (ListView) findViewById(R.id.variantsList);
        variantsList.setOnItemClickListener(this);

        variants = new ArrayList<DLVariantListItem>(0);
        variantsAdapter = new DlVariantsAdapter(getApplicationContext(), R.layout.download_variant_item, variants);

        variantsList.setAdapter(variantsAdapter);

        streamUrlTxt = (TextView)findViewById(R.id.streamUrlTxt);
        streamInfoTxt = (TextView)findViewById(R.id.streamDurationTxt);
        waitingWheel = (LinearLayout)findViewById(R.id.processingLayout);

        incomingIntent = getIntent();
        currentStreamUri = incomingIntent.getData();
        currentMediaId = incomingIntent.getStringExtra(Constants.MEDIA_ID_SKEY);

        vmxBootAddress = incomingIntent.getStringExtra(Constants.VCAS_BOOT_ADDRESS_INTENT_SKEY);
        vmxCompanyName = incomingIntent.getStringExtra(Constants.VCAS_COMPANY_NAME_INTENT_SKEY);
        Log.d(TAG, "extractInfoFromIncomingIntent - verimatrix Boot Address = " + vmxBootAddress + "; verimatrix Company Name = " + vmxCompanyName);

        drmAgentType = incomingIntent.getStringExtra(Constants.DRM_AGENT_TYPE);
        drmPersonalizationUrl = incomingIntent.getStringExtra(Constants.DRM_PERSONALIZATION_URL);
        drmPersonalizationAppVersion = incomingIntent.getStringExtra(Constants.DRM_PERSONALIZATION_APPVERSION);
        drmPersonalizationCustomData = incomingIntent.getStringExtra(Constants.DRM_PERSONALIZATION_CUSTOM_DATA);
        drmLicenseAcquisitionUrl = incomingIntent.getStringExtra(Constants.DRM_LICENSE_URL_SKEY);
        drmLicenseAcquisitionUrlParameters = incomingIntent.getStringExtra(Constants.DRM_LICENSE_URL_PARAMETERS_SKEY);
        drmLicenseAcquisitionCustomData = incomingIntent.getStringExtra(Constants.DRM_LICENSE_CUSTOM_DATA_SKEY);
        drmLicenseAcquisitionCookie = incomingIntent.getStringExtra(Constants.DRM_LICENSE_COOKIE_SKEY);
        Log.d(TAG, "extractInfoFromIncomingIntent - drmLicenseAcquisitionUrl="+drmLicenseAcquisitionUrl);

        // extract HTTP credentials, SSL CA/Client/Client Key Path and Type, Http Custom Header
        httpAuthUsername = incomingIntent.getStringExtra(Constants.AUTH_USER_NAME_INTENT_SKEY);
        httpAuthPassword = incomingIntent.getStringExtra(Constants.AUTH_PASSWORD_INTENT_SKEY);
        Log.d(TAG, "extractInfoFromIncomingIntent - httpAuthUsername = " + httpAuthUsername + "; httpAuthPassword = " + httpAuthPassword);
        SSLCACertFilePath = incomingIntent.getStringExtra(Constants.SSL_CA_CERT_FILE_PATH_INTENT_SKEY);
        SSLCACertFileType = changeOpSSLType(incomingIntent.getStringExtra(Constants.SSL_CA_CERT_FILE_TYPE_INTENT_SKEY));
        Log.d(TAG, "extractInfoFromIncomingIntent - SSLCACertFilePath = " + SSLCACertFilePath + "; SSLCACertFileType = " + SSLCACertFileType);
        SSLClientCertFilePath = incomingIntent.getStringExtra(Constants.SSL_CLIENT_CERT_FILE_PATH_INTENT_SKEY);
        SSLClientCertFileType = changeOpSSLType(incomingIntent.getStringExtra(Constants.SSL_CLIENT_CERT_FILE_TYPE_INTENT_SKEY));
        Log.d(TAG, "extractInfoFromIncomingIntent - SSLClientCertFilePath = " + SSLClientCertFilePath + "; SSLClientCertFileType = " + SSLClientCertFileType);
        SSLClientKeyFilePath = incomingIntent.getStringExtra(Constants.SSL_CLIENT_KEY_FILE_PATH_INTENT_SKEY);
        SSLClientKeyFileType = changeOpSSLType(incomingIntent.getStringExtra(Constants.SSL_CLIENT_KEY_FILE_TYPE_INTENT_SKEY));
        Log.d(TAG, "extractInfoFromIncomingIntent - SSLClientKeyFilePath = " + SSLClientKeyFilePath + "; SSLClientKeyFileType = " + SSLClientKeyFileType);
        httpCustomHeader = incomingIntent.getStringExtra(Constants.HTTP_CUSTOM_HEADER_INTENT_SKEY);
        Log.d(TAG, "extractInfoFromIncomingIntent - httpCustomHeader = " + httpCustomHeader);

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        String proxyTypePref = prefs.getString(Constants.PREF_PROXY_TYPE, "No proxy");
        if (proxyTypePref.equals("HTTP")) {
            mProxyType = 1;
        } else if (proxyTypePref.equals("SOCKS v4")) {
            mProxyType = 2;
        } else if (proxyTypePref.equals("SOCKS v5")) {
            mProxyType = 3;
        } else {
            mProxyType = 0;
        }
        mProxyUrl = prefs.getString(Constants.PREF_PROXY_URL, null);
        mProxyPort = Integer.parseInt(prefs.getString(Constants.PREF_PROXY_PORT, "0"));

        streamUrlTxt.setText(currentStreamUri.toString());
    }

    @Override
    protected void onResume() {
        Log.d(TAG, "onResume");

        dlMgr = DownloadManager.getInstance(getApplicationContext());
        dlMgr.registerOnErrorListener(this);
        dlMgr.registerOnPreparedListener(this);
        dlMgr.registerOnInfoListener(this);

        if(null != currentStreamUri) {
            if(dlMgr.getNbAvailableDownloaders() > 0) {
                processCurrentUri();
            }
            else {
                Log.e(TAG, "onResume - no downloader available ! this should not happen...");
            }
        }
        super.onResume();
    }

    @Override
    protected void onPause() {

        // if we didn't start a download, we need to release the downloader here
        if(!downloadStarted) {
            dlMgr.releaseDownloaderForMediaId(currentMediaId);
        }
        dlMgr.unregisterOnErrorListener(this);
        dlMgr.unregisterOnPreparedListener(this);
        dlMgr.unregisterOnInfoListener(this);
        super.onPause();
    }


    private void processCurrentUri() {
        Log.d(TAG, "processCurrentUri - Start");

        this.downloader = dlMgr.createDownloaderForMediaId(currentMediaId, currentStreamUri.toString(), vmxBootAddress, vmxCompanyName);

        /* set parameters : authentec user name/password, SSL CA cert path, SSL CA file Type, Http custom header */
        if(null != httpAuthUsername && null != httpAuthPassword) {
            Log.d(TAG, "processCurrentUri - httpAuthUsername = "+httpAuthUsername+" httpAuthPassword = "+httpAuthPassword);
            downloader.setDigestAuthentication(httpAuthUsername,httpAuthPassword);
        }
        if(null != SSLCACertFilePath && Constants.SSL_TYPE_UNKNOWN != SSLCACertFileType) {
            Log.d(TAG, "processCurrentUri - SSLCACertFilePath = "+SSLCACertFilePath+" SSLCACertFileType = "+SSLCACertFileType);
            downloader.setCACertificate(SSLCACertFilePath, SSLCACertFileType);
        }
        if( null != SSLClientCertFilePath && Constants.SSL_TYPE_UNKNOWN != SSLClientCertFileType &&
            null != SSLClientKeyFilePath && Constants.SSL_TYPE_UNKNOWN != SSLClientKeyFileType) {
            Log.d(TAG, "processCurrentUri - SSLClientCertFilePath = "+SSLClientCertFilePath+" SSLClientCertFileType = "+SSLClientCertFileType);
            Log.d(TAG, "processCurrentUri - SSLClientKeyFilePath = "+SSLClientKeyFilePath+" SSLClientKeyFileType = "+SSLClientKeyFileType);
            downloader.setClientCertificate(SSLClientCertFilePath, SSLClientCertFileType, SSLClientKeyFilePath, SSLClientKeyFileType);
        }
        if(null != httpCustomHeader) {
            Log.d(TAG, "processCurrentUri - httpCustomHeader = "+httpCustomHeader);
            downloader.setHttpCustomHeader(httpCustomHeader);
        }

         if (mProxyType > 0 && mProxyPort > 0 && null != mProxyUrl) {

            Log.d(TAG, "processCurrentUri - downloader.setProxy :"+mProxyUrl+ "; proxy port = " + mProxyPort + "; proxy type = " + mProxyType);
            downloader.setProxy(mProxyUrl,mProxyPort, mProxyType);
        }
        else{
            Log.d(TAG, "processCurrentUri - reset proxy values ");
            downloader.setProxy("", 0, 0);
        }

        // specifc code for PlayReady legacy configuration
        if (VOPlayer.getDRMAgentVersion() == VOPlayer.DRMAgentVersion.VERSION_1){
            if (Constants.DRM_AGENT_TYPE_PLAYREADY.equals(drmAgentType)) {
                try {
                    downloader.getAgentPlayready().setPersonalizationURL("file:///android_asset/PlayReady/");
                    if (null != drmLicenseAcquisitionUrl) {
                        downloader.getAgentPlayready().setLicenseAcquisitionURL(drmLicenseAcquisitionUrl);
                    }
                    if (null != drmLicenseAcquisitionUrlParameters) {
                        downloader.getAgentPlayready().setLicenseAcquisitionURLParameters(drmLicenseAcquisitionUrlParameters);
                    }
                    if (null != drmLicenseAcquisitionCustomData) {
                        downloader.getAgentPlayready().setLicenseAcquisitionCustomData(drmLicenseAcquisitionCustomData);
                    }
                } catch (VOException e) {
                    Log.e(TAG, "processCurrentUri exception while using playreadyAgent " + e.getStatus().toString());
                }
            }
        }

        downloader.asyncPrepare();
    }


    @Override
    public boolean onError(DownloaderWrapper downloader, int what, int extra) {
        Log.d(TAG, "onError - " + what + " " + extra);
        streamInfoTxt.setText("Error, please try again later");
        streamInfoTxt.setVisibility(View.VISIBLE);
        return true;
    }

    @Override
    public void onPrepared(DownloaderWrapper downloader) {
        Log.d(TAG, "onPrepared");

        if(currentStreamUri.toString().equalsIgnoreCase(downloader.getUri())) {
            try {
                populateVariantsList(downloader);
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            waitingWheel.setVisibility(View.GONE);
        }
        else {
            Log.d(TAG, "onPrepared recieved for another Uri");
        }
    }


    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

        if(null == downloader) {
            Log.d(TAG, "No Downloader !!!");
            return;
        }
        selectedItemId = arg2;
        askForDownloadAction();
    }


    private void askForDownloadAction() {

        final String DownloadOnlyActionString = "Download Only";
        final String DownloadAndPlayActionString = "Download & Play";
        final String SelectAudioTracksString = "Select Audio Tracks";
        final String SelectSubtitleTracksString = "Select Subtitle Tracks";

        //populate menu with actions
        final ArrayList<CharSequence> actions = new ArrayList<CharSequence>();
        actions.add(DownloadOnlyActionString);
        actions.add(DownloadAndPlayActionString);
        if (!variants.get(selectedItemId).audioTracksSelectedHashMap.isEmpty()){
            actions.add(SelectAudioTracksString);
        }
        if (!variants.get(selectedItemId).subtitleTracksSelectedHashMap.isEmpty()){
            actions.add(SelectSubtitleTracksString);
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.select_download_action);
        builder.setCancelable(true);
        CharSequence[] actionsList = new CharSequence[actions.size()];
        actions.toArray(actionsList);
        builder.setItems(actionsList,  new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
                dialog.dismiss();
                if (actions.get(item).equals(DownloadOnlyActionString)){
                    executeDownloadOnlyAction();
                }else if (actions.get(item).equals(DownloadAndPlayActionString)){
                    executeDownloadAndPlayAction();
                }else if (actions.get(item).equals(SelectAudioTracksString)){
                    executeSelectTracksAction(true);
                }else if (actions.get(item).equals(SelectSubtitleTracksString)){
                    executeSelectTracksAction(false);
                }
            }
        });
        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
            public void onCancel(DialogInterface dialog) {
                dialog.dismiss();
            }});

        AlertDialog alert = builder.create();
        alert.show();
    }

    private void executeDownloadAndPlayAction() {
        if(startDownload()) {
            startPlayback();
        } else {
            Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
        }
        this.finish();
    }


    private void executeDownloadOnlyAction() {
        startDownload();
        this.finish();
    }


    private void executeSelectTracksAction(boolean bAudioTrack) {

        //get multi choices values
        HashMap<String, Boolean> tracksHashMap = null;
        final String[] tracksStringList;
        final boolean[] tracksSelectedlList;
        final boolean bIsAudioTrack = bAudioTrack;
        if (bAudioTrack){
            tracksHashMap = variants.get(selectedItemId).audioTracksSelectedHashMap;
            if(null == tracksHashMap || tracksHashMap.isEmpty()) {
                Toast.makeText(getApplicationContext(), "No audio track found", Toast.LENGTH_SHORT).show();
                return;
            }
        } else {
            tracksHashMap = variants.get(selectedItemId).subtitleTracksSelectedHashMap;
            if(null == tracksHashMap || tracksHashMap.isEmpty()) {
                Toast.makeText(getApplicationContext(), "No subtitle track found", Toast.LENGTH_SHORT).show();
                return;
            }
        }
        tracksStringList = new String[tracksHashMap.size()];
        tracksSelectedlList = new boolean[tracksHashMap.size()];
        int index=0;
        for (Map.Entry<String, Boolean> mapEntry : tracksHashMap.entrySet()) {
            tracksStringList[index] = mapEntry.getKey();
            tracksSelectedlList[index] = mapEntry.getValue();
            index++;
        }

        //build and show dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.choose_action_title));
        builder.setCancelable(true);

        builder.setPositiveButton("OK", new DialogInterface.OnClickListener () {
            public void onClick(DialogInterface dialog, int which) {
                //save values
                if (bIsAudioTrack){
                    variants.get(selectedItemId).audioTracksSelectedHashMap.clear();
                    for (int i=0; i< tracksStringList.length; i++){
                        variants.get(selectedItemId).audioTracksSelectedHashMap.put(tracksStringList[i], tracksSelectedlList[i]);
                    }
                } else {
                    variants.get(selectedItemId).subtitleTracksSelectedHashMap.clear();
                    for (int i=0; i< tracksStringList.length; i++){
                        variants.get(selectedItemId).subtitleTracksSelectedHashMap.put(tracksStringList[i], tracksSelectedlList[i]);
                    }
                }
            }
        });

        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener () {
        public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        builder.setMultiChoiceItems(tracksStringList, tracksSelectedlList,
                                    new DialogInterface.OnMultiChoiceClickListener() {
            public void onClick(DialogInterface dialog, int which, boolean isChecked){
                tracksSelectedlList[which] = isChecked;
            }
        });
        builder.create().show();
    }


    private boolean startDownload() {
        if(selectedItemId < 0) {
            Log.e(TAG, "executeDownloadOnlyAction: no selected item !");
            return false;
        }
        DLVariantListItem item = variants.get(selectedItemId);

        Log.d(TAG, "Selected bitrate: " + item.bitrate);
        Log.d(TAG, "startDownload - SET QUALITY !!!!");
        downloader.selectQualityByIndex(selectedItemId);

        // Set the audio tracks for download if any selected
        String selectedAudioTracks = null;
        if (null != item.audioTracksSelectedHashMap){
            ArrayList<String> audioTracksListToDownload = new ArrayList<String> ();
            for (Map.Entry<String, Boolean> mapEntry : item.audioTracksSelectedHashMap.entrySet()) {
                if (mapEntry.getValue()){
                    String language = mapEntry.getKey();
                    audioTracksListToDownload.add(language);
                }
            }
            if (!audioTracksListToDownload.isEmpty()){
                selectedAudioTracks = new String();
                String audioToDownloadTab[] = new String[audioTracksListToDownload.size()];
                for (int j=0;j< audioTracksListToDownload.size();j++){
                    audioToDownloadTab[j] = audioTracksListToDownload.get(j);
                    Log.d(TAG, "startDownload - add audiotrack  "+ audioToDownloadTab[j]);
                    selectedAudioTracks +=  audioTracksListToDownload.get(j) + ",";
                }
                selectedAudioTracks = selectedAudioTracks.substring(0, selectedAudioTracks.length()-1);
                //set audio tracks to download
                downloader.setAudioTracks(audioToDownloadTab);
            }
        }
        // Set the subtitle tracks for download if any selected
        String selectedSubTracks = null;
        if (null != item.subtitleTracksSelectedHashMap){
            ArrayList<String> subtitleTracksListToDownload = new ArrayList<String> ();
            for (Map.Entry<String, Boolean> mapEntry : item.subtitleTracksSelectedHashMap.entrySet()) {
                if (mapEntry.getValue()){
                    String language = mapEntry.getKey();
                    subtitleTracksListToDownload.add(language);
                }
            }
            if (! subtitleTracksListToDownload.isEmpty()){
                selectedSubTracks = new String();
                String subtitleToDownloadTab[] = new String[subtitleTracksListToDownload.size()];
                for (int j=0;j< subtitleTracksListToDownload.size();j++){
                    subtitleToDownloadTab[j] = subtitleTracksListToDownload.get(j);
                    Log.d(TAG, "startDownload - add subtitletrack  "+ subtitleToDownloadTab[j]);
                    selectedSubTracks +=  subtitleTracksListToDownload.get(j) + ",";
                }
                selectedSubTracks = selectedSubTracks.substring(0, selectedSubTracks.length()-1);
                //set subtitle tracks to download
                downloader.setSubtitleTracks(subtitleToDownloadTab);
            }
        }

        //acquire rights if not needed only
        DrmManager.ActionParams drmAction = new DrmManager.ActionParams();
        drmAction.actionType = DrmManager.ActionType.PERSO_AND_ACQUIRE_RIGHT_IF_NOT_ALREADY_DONE;
        drmAction.contentUrl = currentStreamUri.toString();
        drmAction.drmAgentType = drmAgentType;
        if (null != drmPersonalizationUrl) {
            drmAction.persoUrl = drmPersonalizationUrl;
        }
        if (null != drmPersonalizationAppVersion) {
            drmAction.persoAppVersion = drmPersonalizationAppVersion;
        }
        drmAction.persoCustomData = drmPersonalizationCustomData;
        drmAction.licenseAcquisitionUrl = drmLicenseAcquisitionUrl;
        drmAction.licenseAcquisitionUrlParameters = drmLicenseAcquisitionUrlParameters;
        drmAction.licenseAcquisitionCustomData = drmLicenseAcquisitionCustomData;
        drmAction.licenseAcquisitionCookie = drmLicenseAcquisitionCookie;
        dlMgr.acquireRightsIfNeededForUri(drmAction);

        int progress = downloader.getDownloadedDuration();
        Log.d(TAG, "Already downloaded: " + progress);
        try {
            downloader.start();
            if((null != vmxBootAddress) || (Constants.DRM_AGENT_TYPE_AES.equals(drmAgentType))) {
                downloader.renewOfflineKeys();
            }
         } catch (UnsupportedOperationException e) {
            e.printStackTrace();
            return false;
         }


        int streamDuration = 0;
        try {
            streamDuration = downloader.getDuration();
        } catch (Exception e) {
            Log.e(TAG, "Downloader getDuration failed");
            Toast.makeText(getApplicationContext(), "Stream duration is unavailable", Toast.LENGTH_SHORT).show();
        }

        MediaMetaInfoDB db = MediaMetaInfoDB.getInstance(getApplicationContext());
        db.setDlInfoForMediaId(currentMediaId, DatabaseInfo.DL_STATUS_DOWNLOADING, streamDuration, item.bitrate, 0, downloader.getLocalServerUrl(), selectedSubTracks, selectedAudioTracks);

        downloadStarted = true;
        return true;
    }

    private void populateVariantsList(DownloaderWrapper gla) throws ExecutionException {

        Log.d(TAG, "populateVariantsListFromGateway - START");

        //save the last variants to re-use some values (for example, audio tracks)
        List<DLVariantListItem> previousVariants = new ArrayList<DLVariantListItem>(variants);

        variants.clear();

        int streamDuration = 0;
        try {
            streamDuration = downloader.getDuration();
        } catch (Exception e) {
            Log.e(TAG, "Downloader getDuration failed");
            Toast.makeText(getApplicationContext(), "Stream duration is unavailable", Toast.LENGTH_SHORT).show();
        }

        streamInfoTxt.setText("Estimated stream duration: " + VOUtils.convertTimeToText(streamDuration));
        streamInfoTxt.setVisibility(View.VISIBLE);

        Log.v(TAG, "populateVariantsList: infos " + streamDuration);

        if(0 == streamDuration) {
            Toast.makeText(getApplicationContext(), "Live stream, impossible to cache", Toast.LENGTH_SHORT).show();
            return;
        }

        int nbVariants = 0;
        try {
            nbVariants = downloader.getNbQualities();
        }catch(Exception e){
            Log.e(TAG, "populateVariantsList - error after getNbQualities:" + ", exception:" + e);
            Toast.makeText(getApplicationContext(), "Impossible to get number of qualities", Toast.LENGTH_SHORT).show();
        }
        Log.d(TAG, "populateVariantsListFromGateway - nbVariants = " + nbVariants);

        for(int i=0; i<nbVariants; i++) {

            DLVariantListItem item = new DLVariantListItem();
            item.bitrate = downloader.getBitrateByIndex(i);
            item.resolution = downloader.getResolutionByIndex(i);
            item.estimatedSizeInMB = (item.bitrate / (8 * 1000)) * (streamDuration/1000) / 1024;
            downloader.selectQualityByIndex(i);

            //get audio tracks for the variant
            item.audioTracksSelectedHashMap = new HashMap<String, Boolean>();
            DownloaderWrapper.AudioTrackInfo[] audioTracksList = downloader.getAudioTracks();
            if (null != audioTracksList){
                for (int j=0; j<audioTracksList.length ; j++){
                    boolean bAudioTrackSelected = false;
                    //check if a value was already set by the user
                    if (null != previousVariants){
                        for (int k=0; k< previousVariants.size() ;k++){
                            if ( item.bitrate == previousVariants.get(k).bitrate){
                                HashMap<String, Boolean> previousAudioTrackHashMap = previousVariants.get(k).audioTracksSelectedHashMap;
                                if (null != previousAudioTrackHashMap){
                                    if (true == previousAudioTrackHashMap.containsValue(audioTracksList[j].name)){
                                        bAudioTrackSelected = previousAudioTrackHashMap.get(audioTracksList[j].name);
                                    }
                                }
                            }
                        }
                    }
                    //add the audiotrack to the list
                    item.audioTracksSelectedHashMap.put(audioTracksList[j].name, bAudioTrackSelected);
                }
            }

            //get subtitle tracks for the variant
            item.subtitleTracksSelectedHashMap = new HashMap<String, Boolean>();
            DownloaderWrapper.SubtitleTrackInfo[] subtitleTracksList = downloader.getSubtitleTracks();
            if (null != subtitleTracksList){
                for (int j=0; j<subtitleTracksList.length ; j++){
                    boolean bSubtitleTrackSelected = false;
                    //check if a value was already set by the user
                    if (null != previousVariants){
                        for (int k=0; k< previousVariants.size() ;k++){
                            if ( item.bitrate == previousVariants.get(k).bitrate){
                                HashMap<String, Boolean> previousSubtitleTrackHashMap = previousVariants.get(k).subtitleTracksSelectedHashMap;
                                if (null != previousSubtitleTrackHashMap){
                                    if (true == previousSubtitleTrackHashMap.containsValue(subtitleTracksList[j].name)){
                                        bSubtitleTrackSelected = previousSubtitleTrackHashMap.get(subtitleTracksList[j].name);
                                    }
                                }
                            }
                        }
                    }
                    //add the subtitletrack to the list
                    item.subtitleTracksSelectedHashMap.put(subtitleTracksList[j].name, bSubtitleTrackSelected);
                }
            }

            variants.add(item);
            Log.v(TAG, "populateVariantsList: item " + item.bitrate + " estimated size: " + item.estimatedSizeInMB);
        }

        variantsAdapter.notifyDataSetChanged();
    }

    private void startPlayback() {

        boolean started = startLocalHttpServer();
        if (!started) {
            Log.e(TAG,
                    "startPlayback - Error with local HTTP server");
            Toast.makeText(
                    getApplicationContext(),
                    "Error when starting local HTTP server.\nPlayback impossible.",
                    Toast.LENGTH_SHORT).show();
            return;
        }

        Uri mediaUri;

        Intent i = new Intent();
        i.setClass(getApplicationContext(), PlayerActivity.class);
        i.setAction(Intent.ACTION_VIEW);

        // re-use all extras sent by the media list activity
        if(null != incomingIntent.getExtras()) {
            i.putExtras(incomingIntent.getExtras());
        }

        i.putExtra(Constants.DL_ORG_URI_INTENT_SKEY, this.currentStreamUri.toString());
        i.putExtra(Constants.LOCAL_SERVER_INTENT_ZKEY, true);

        if (null != this.vmxBootAddress && null != this.vmxCompanyName) {
            i.putExtra(Constants.VCAS_BOOT_ADDRESS_INTENT_SKEY, this.vmxBootAddress);
            i.putExtra(Constants.VCAS_COMPANY_NAME_INTENT_SKEY, this.vmxCompanyName);
        }


        if (null != this.drmAgentType) {
            i.putExtra(Constants.DRM_AGENT_TYPE, this.drmAgentType);
        }
        if (null != this.drmPersonalizationUrl) {
            i.putExtra(Constants.DRM_PERSONALIZATION_URL, this.drmPersonalizationUrl);
        }
        if (null != this.drmPersonalizationAppVersion) {
            i.putExtra(Constants.DRM_PERSONALIZATION_APPVERSION, this.drmPersonalizationAppVersion);
        }
        if (null != this.drmLicenseAcquisitionCustomData) {
            i.putExtra(Constants.DRM_PERSONALIZATION_CUSTOM_DATA, this.drmLicenseAcquisitionCustomData);
        }
        if (null != this.drmLicenseAcquisitionUrl) {
            i.putExtra(Constants.DRM_LICENSE_URL_SKEY, this.drmLicenseAcquisitionUrl);
        }
        if (null != this.drmLicenseAcquisitionUrlParameters) {
            i.putExtra(Constants.DRM_LICENSE_URL_PARAMETERS_SKEY, this.drmLicenseAcquisitionUrlParameters);
        }
        if (null != this.drmLicenseAcquisitionCustomData) {
            i.putExtra(Constants.DRM_LICENSE_CUSTOM_DATA_SKEY, this.drmLicenseAcquisitionCustomData);
        }
        if (null != this.drmLicenseAcquisitionCookie) {
            i.putExtra(Constants.DRM_LICENSE_CUSTOM_DATA_SKEY, this.drmLicenseAcquisitionCookie);
        }

        mediaUri = Uri.parse(downloader.getLocalServerUrl());

        Log.d(TAG, "starting playback for uri: " + mediaUri);
        i.setData(mediaUri);

        // Inform QP it's a native browser Call
        i.putExtra("nativeBrowserCall", true);
        this.startActivity(i);
    }

    private boolean startLocalHttpServer() {
        return dlMgr.startLocalServer();
    }

    @Override
    public boolean onInfo(DownloaderWrapper downloader, int what, int extra) {

        if(currentStreamUri.toString().equalsIgnoreCase(downloader.getUri())) {
            Log.d(TAG, "onInfo received for current Uri: " + what + ", " + extra);
            switch(what) {

            case DownloaderWrapper.DOWNLOADER_INFO_OFFLINE_KEYS_RENEWAL_STARTED:
                Toast.makeText(getApplicationContext(), "Starting key renewal", Toast.LENGTH_SHORT).show();
                break;

            case DownloaderWrapper.DOWNLOADER_INFO_OFFLINE_KEYS_RENEWAL_COMPLETED:
                Toast.makeText(getApplicationContext(), "Key renewal completed", Toast.LENGTH_SHORT).show();
                break;
            case DownloaderWrapper.DOWNLOADER_INFO_OFFLINE_NOT_ALLOWED:
                Toast.makeText(getApplicationContext(), "Offline key not allowed", Toast.LENGTH_SHORT).show();
                break;
            }
        }
        return false;
    }
}
