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

import android.app.*;
import android.content.*;
import android.content.Loader;
import android.os.*;
import android.text.*;
import android.util.Log;
import android.view.*;
import android.widget.*;
import com.insidesecure.drm.android.reference.*;
import com.insidesecure.drm.android.reference.xoplayer.R;
import com.insidesecure.drm.android.reference.services.DownloadService;
import com.insidesecure.drm.android.reference.tools.DRMLogProvider;
import com.insidesecure.drmagent.*;

import java.io.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

public abstract class SettingsActivity extends AbstractDRMActivity
{
    protected static final String TAG = "SettingsActivity";
    private static final int REVOCATION_UPDATE_LOADER_ID = 2;
    protected static Dialog sLastDisplayedDialog;
    protected SharedPreferences mPreferences;
    protected SharedPreferences.Editor mEditor;
    public static final int EXPORT_HDS_REPORTED = 1;

    public static final int REVOCATION_LIST_UPDATE_ONGOING = 6;
    public static final int REVOCATION_LIST_UPDATE_SUCCESSFUL = 7;
    public static final int REVOCATION_LIST_UPDATE_FAILED = 8;
    public static final int REVOCATION_LIST_UPDATE_CONFIRM = 9;

    public static final int PLAY_ENABLERS_SELECTION = 10;

    public static final int DUMP_ROOT_CHECK_REPORT = 11;

    private CheckBox forceTimebasedLicenseForContent;
    private EditText timeBasedLicenseValue;
    private CheckBox forceIntervalLicenseForContent;
    private EditText intervalBasedLicenseValue;
    private CheckBox forceOPLLicenseForContent;
    private EditText oplLicenseValue;
    private CheckBox askForLicenseAck;
    private CheckBox useWebInitiatorLaHandler;

    private Dialog mExportHdsDialog, playEnablersSelectionDialog, mDumpRootCheckReportDialog;

    private boolean mIsServiceBound = false;
    private DownloadService mService;
    private ServiceConnection mServiceConnection = new ServiceConnection()
    {
        public void onServiceConnected(ComponentName componentName, IBinder iBinder)
        {
            mIsServiceBound = true;
            DownloadService.DownloadServiceBinder binder = (DownloadService.DownloadServiceBinder) iBinder;
            mService = binder.getService();
            initDownloadContentFromRemoteServer();
        }

        public void onServiceDisconnected(ComponentName componentName)
        {
            mIsServiceBound = false;
            mService = null;
        }
    };

    private void initDownloadContentFromRemoteServer()
    {
        final Dialog dialog = Tools.createSimpleProgressDialog(SettingsActivity.this, getText(R.string.dialog_title),getText(R.string.dialog_text_restore_content));
        dialog.show();
        sLastDisplayedDialog = dialog;
        mService.downloadDefaultContent(getRemoteContentLocation(), new ContentHandler.OnCDescRetrieveFinishedCallback()
        {

            public void onRetrieveFinished(String loadedFilePath)
            {
                SettingsActivity.this.runOnUiThread(new Runnable()
                {
                    public void run()
                    {
                        dialog.dismiss();
                        sLastDisplayedDialog = null;
                        Toast.makeText(SettingsActivity.this, "Default content restored successfully", Toast.LENGTH_SHORT).show();
                    }
                });
            }

            public void onRetrieveFailed(final String errorMessage)
            {
                SettingsActivity.this.runOnUiThread(new Runnable()
                {
                    public void run() {
                        dialog.dismiss();
                        sLastDisplayedDialog = null;
                        Toast.makeText(SettingsActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

    @Override
    protected void onSaveInstanceState(final Bundle outState)
    {
        super.onSaveInstanceState(outState);
        if (sLastDisplayedDialog != null)
        {
            sLastDisplayedDialog.dismiss();
        }
    }

    @Override
    protected void onRestoreInstanceState(final Bundle savedInstanceState)
    {
        super.onRestoreInstanceState(savedInstanceState);
        if (sLastDisplayedDialog != null)
        {
            sLastDisplayedDialog.show();
        }
    }

    @Override
    protected Dialog onCreateDialog(int id)
    {
        switch (id)
        {
            case EXPORT_HDS_REPORTED:
                return mExportHdsDialog;
            case REVOCATION_LIST_UPDATE_ONGOING:
                return Tools.createSimpleProgressDialog(this, getText(R.string.dialog_title), getText(R.string.updating_revocation_list));
            case REVOCATION_LIST_UPDATE_CONFIRM:
                return createPerformRevocationUpdateConfirmDialog();
            case REVOCATION_LIST_UPDATE_SUCCESSFUL:
                return Tools.createAlertDialog(this, getText(R.string.dialog_title), getText(R.string.revocation_list_update_successful), false, getText(R.string.dialog_button_ok), new DialogInterface.OnClickListener()
                {
                    public void onClick(final DialogInterface dialog, final int which)
                    {
                        dialog.dismiss();
                    }
                }, null, null);
            case REVOCATION_LIST_UPDATE_FAILED:
                return Tools.createAlertDialog(this, getText(R.string.dialog_title), getText(R.string.revocation_list_update_failed), false, getText(R.string.dialog_button_ok), new DialogInterface.OnClickListener()
                {
                    public void onClick(final DialogInterface dialog, final int which)
                    {
                        dialog.dismiss();
                    }
                }, null, null);
            case PLAY_ENABLERS_SELECTION:
                // ...Any dialog that is created by this method will automatically be saved and restored for you, including whether it is showing.
                return playEnablersSelectionDialog;
            case DUMP_ROOT_CHECK_REPORT:
                return mDumpRootCheckReportDialog;
            default:
                Log.d(TAG, "No such dialog");
                return null;
        }
    }

    @Override
    protected void onPrepareDialog(int    id,
                                   Dialog dialog)
    {

            switch (id)
            {
                case PLAY_ENABLERS_SELECTION:
                    ((MultipleSelectionDialog) playEnablersSelectionDialog).setDialog();
                    break;
            }
    }

    private Dialog createPerformRevocationUpdateConfirmDialog()
    {
        return createCustomAlertDialog(getText(R.string.revocation_list_update_confirm), new DialogInterface.OnClickListener()
        {
            public void onClick(final DialogInterface dialog, final int which) {

                getLoaderManager().initLoader(REVOCATION_UPDATE_LOADER_ID, null,
                        new LoaderManager.LoaderCallbacks<Boolean>() {

                            @Override
                            public Loader<Boolean> onCreateLoader(int id, Bundle args) {
                                showDialog(SettingsActivity.REVOCATION_LIST_UPDATE_ONGOING);
                                return new AsyncTaskLoader<Boolean>(SettingsActivity.this) {
                                    @Override
                                    public Boolean loadInBackground() {
                                        return DRMAgentDelegate.performRevocationListUpdate(SettingsActivity.this);
                                    }
                                };
                            }

                            @Override
                            public void onLoadFinished(Loader<Boolean> loader, Boolean success) {
                                dismissDialog(SettingsActivity.REVOCATION_LIST_UPDATE_ONGOING);
                                showDialog(success ? SettingsActivity.REVOCATION_LIST_UPDATE_SUCCESSFUL
                                        : SettingsActivity.REVOCATION_LIST_UPDATE_FAILED);
                            }

                            @Override
                            public void onLoaderReset(Loader<Boolean> loader) {
                            }
                        }).forceLoad();
            }
        });
    }

    @Override
    protected void onResume()
    {
        mPreferences = getSharedPreferences(Constants.PREFERENCES_FILENAME, Context.MODE_PRIVATE);
        mEditor = mPreferences.edit();
        super.onResume();
    }

    private boolean isUrlValid(String url)
    {

        try
        {
            new URL(url).openStream();
        }

        catch (IOException exception)
        {
            return false;
        }

        catch (Exception exception)
        {
            exception.printStackTrace();
            Log.e(TAG, "Unexpected error " + exception.toString());
            return false;
        }

        return true;
    }


    private void setControlsStateForUseUrlFromHeader(boolean isChecked)
    {
        forceTimebasedLicenseForContent.setEnabled(!isChecked);
        timeBasedLicenseValue.setEnabled(!isChecked);

        forceIntervalLicenseForContent.setEnabled(!isChecked);
        intervalBasedLicenseValue.setEnabled(!isChecked);

        forceOPLLicenseForContent.setEnabled(!isChecked);
        oplLicenseValue.setEnabled(!isChecked);

        askForLicenseAck.setEnabled(!isChecked);

    }


    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        final String pathToHDS = this.getFilesDir().getParent() + File.separator + "playready.hds";
        final String pathToRootCheckReport = "sdcard/insidesecure/report.bin";

        mPreferences = getSharedPreferences(Constants.PREFERENCES_FILENAME, Context.MODE_PRIVATE);
        mEditor = mPreferences.edit();

        Button button = (Button) findViewById(R.id.button_delete_all_content);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {
                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.delete_content_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Initiating deletion of all registered content");
                        com.insidesecure.drm.android.reference.ContentHandler.deleteAllContent();
                        sLastDisplayedDialog = null;
                    }
                });
                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });

        button = (Button) findViewById(R.id.button_reset_drm_store);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {

                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.reset_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Initiating purge of all installed licenses");
                        DRMAgentDelegate.purgeLicenses(SettingsActivity.this);
                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });

        button = (Button) findViewById(R.id.button_cleanup_resources);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {

                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.pooled_cleanup_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Initiating purge all pooled objects");
                        DRMAgentDelegate.purgePooledObjects(SettingsActivity.this);
                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });


        button = (Button) findViewById(R.id.delete_drm_databases);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {

                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.delete_drm_databases_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Initiating reset of DRM databases");
                        DRMAgentDelegate.deleteDRMDatabases(SettingsActivity.this);
                        Log.d(TAG, "Reset continuing...");
                        File file = new File(Constants.CONFIGURATION_CDESC_PATH + Constants.CONFIGURATION_PROPERTIES_FILE);
                        if(file.exists())
                        {
                            file.renameTo(new File(Constants.CONFIGURATION_CDESC_PATH + "_" + Constants.CONFIGURATION_PROPERTIES_FILE));
                        }
                        Log.d(TAG, "Reset completed.");

                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });

        button = (Button) findViewById(R.id.button_clear_cached_files);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {

                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.clear_cache_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        ClearCache();
                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });

        button = (Button) findViewById(R.id.button_restore_content);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {

                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.restore_content), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Restoring all content");
                        restoreContentFromRemoteServer();
                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });

        //button_manage_cached_media
        configButtonManageCachedMediaAction();

        //button_cancel_all_downloads
        configButtonCancelAllDownloads();

        //button_export_hds
        button = (Button) findViewById(R.id.button_export_hds);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {
                Log.d(TAG, "Initiating export of hds from " + pathToHDS);

                String retVal = Tools.exportHDS(pathToHDS);
                Log.d(TAG, "retVal=" + retVal);


                String messageToShow = "PlayReady.hds exported to " + retVal;

                if (retVal.length() == 0)
                {
                    messageToShow = "Hds file not found at " + pathToHDS;
                }

                final DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dialog, int id)
                    {
                        dialog.cancel();
                    }
                };
                mExportHdsDialog = Tools.createAlertDialog(SettingsActivity.this, "DRM Fusion Agent for Android", messageToShow, true, "Ok", positiveListener, null, null);
                showDialog(EXPORT_HDS_REPORTED);
            }
        });

        //button_dump_root_check_report
        button = (Button) findViewById(R.id.button_dump_root_check_report);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {
                Log.d(TAG, "Initiating dump of root check report to " + pathToRootCheckReport);

                File file = new File(pathToRootCheckReport);
                if (file.exists())
                {
                    file.delete();
                }

                boolean retVal = DRMAgentDelegate.dumpRootCheckReport(pathToRootCheckReport);

                String messageToShow;

                if (retVal)
                {
                    if (file.exists())
                    {
                        messageToShow = "Root check report dumped to " + pathToRootCheckReport;
                    }
                    else
                    {
                        messageToShow = "Root check report not found at " + pathToRootCheckReport;
                    }
                }
                else
                {
                    messageToShow = "Root check report not generated";
                }

                final DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dialog, int id)
                    {
                        dialog.cancel();
                    }
                };
                mDumpRootCheckReportDialog = Tools.createAlertDialog(SettingsActivity.this, "DRM Fusion Agent for Android", messageToShow, true, "Ok", positiveListener, null, null);
                showDialog(DUMP_ROOT_CHECK_REPORT);
            }
        });

        // Setup the update revocation list update button
        configButtonPerformRevocationListUpdate();

        Spinner agentLogLevelSpinner = (Spinner) findViewById(R.id.agent_log_level);
        ArrayAdapter adapter = ArrayAdapter.createFromResource(
                this, R.array.agent_log_levels, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        agentLogLevelSpinner.setAdapter(adapter);
        final int agentPlayerLogLevel = mPreferences.getInt(Constants.PREFERENCES_AGENT_LOG_LEVEL, 4);
        agentLogLevelSpinner.setSelection(agentPlayerLogLevel);
        agentLogLevelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
        {
            public void onItemSelected(final AdapterView<?> parent, final View view, final int position, final long id)
            {
                mEditor.putInt(Constants.PREFERENCES_AGENT_LOG_LEVEL, position);
            }

            public void onNothingSelected(final AdapterView<?> parent)
            {
            }
        });


        forceTimebasedLicenseForContent = (CheckBox) findViewById(R.id.force_timebased_license_for_content);
        timeBasedLicenseValue = (EditText) findViewById(R.id.timebased_license_value);
        forceIntervalLicenseForContent = (CheckBox) findViewById(R.id.force_interval_license_for_content);
        intervalBasedLicenseValue = (EditText) findViewById(R.id.interval_license_value);
        forceOPLLicenseForContent = (CheckBox) findViewById(R.id.force_opl_license_for_content);
        oplLicenseValue = (EditText) findViewById(R.id.opl_license_value);
        askForLicenseAck = (CheckBox) findViewById(R.id.ask_for_license_acknowledgement_for_licenses);
        useWebInitiatorLaHandler = (CheckBox) findViewById(R.id.use_web_initiator_la_handler);

        //save_logfile
        CheckBox saveLogFileCkBox = (CheckBox) findViewById(R.id.save_logfile);
        saveLogFileCkBox.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_SAVE_LOGS, false));

        saveLogFileCkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if (isChecked) {
                    Tools.saveLogs(SettingsActivity.this);
                } else {
                    Tools.stopLogSavingProcess();
                }
                mPreferences.edit().putBoolean(Constants.PREFERENCES_SAVE_LOGS, isChecked).apply();
            }
        });

        //store logs from DRMAgent
        CheckBox storeDRMLogsCheckBox = (CheckBox) findViewById(R.id.enable_storing_drm_logs_checkbox);
        storeDRMLogsCheckBox.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_STORE_DRM_LOGS, false));

        final Button showLastDRMLogsBtn = (Button) findViewById(R.id.show_last_drm_logs_btn);
        showLastDRMLogsBtn.setVisibility(mPreferences.getBoolean(Constants.PREFERENCES_STORE_DRM_LOGS, false) ? View.VISIBLE : View.GONE);
        showLastDRMLogsBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (DRMLogProvider.getInstance().getLastLogs().size() != 0) {
                    createCustomAlertDialog(DRMLogProvider.getInstance().getLastLogs()).show();
                } else {
                    Toast.makeText(SettingsActivity.this, getString(R.string.no_drm_logs_to_show_toast), Toast.LENGTH_LONG).show();
                }
            }
        });

        storeDRMLogsCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                DRMAgent.DRMAgentFactory.setDRMLogCallback(isChecked ? DRMLogProvider.getInstance() : null);
                showLastDRMLogsBtn.setVisibility(isChecked ? View.VISIBLE : View.GONE);
                mPreferences.edit().putBoolean(Constants.PREFERENCES_STORE_DRM_LOGS, isChecked).apply();
            }
        });

        //use_url_from_header_label
        CheckBox useUrlFromHeader = (CheckBox) findViewById(R.id.use_url_from_header);
        useUrlFromHeader.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_USE_URL_FROM_HEADER, false));

        //enable/disable other controls
        setControlsStateForUseUrlFromHeader(useUrlFromHeader.isChecked());

        useUrlFromHeader.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                //enable/disable other controls
                setControlsStateForUseUrlFromHeader(isChecked);

                //set the value
                mEditor.putBoolean(Constants.PREFERENCES_USE_URL_FROM_HEADER, isChecked);
                mEditor.commit();
            }
        });

        //force_timebased_license_for_content
        forceTimebasedLicenseForContent.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_FORCE_TIMEBASED_LICENSE_FOR_CONTENT, false));
        forceTimebasedLicenseForContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_FORCE_TIMEBASED_LICENSE_FOR_CONTENT, isChecked);
                mEditor.commit();
            }
        });

        //timeBasedLicenseValue
        timeBasedLicenseValue.setText("" + mPreferences.getInt(Constants.PREFERENCES_TIMEBASED_LICENSE_NUM_MINUTES, 2), TextView.BufferType.NORMAL);
        timeBasedLicenseValue.addTextChangedListener(new TextWatcher()
        {
            public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after)
            {
            }

            public void onTextChanged(final CharSequence s, final int start, final int before, final int count)
            {
            }

            public void afterTextChanged(final Editable editable)
            {
                final String s = editable.toString();
                try
                {
                    final int value = Integer.parseInt(s);
                    mEditor.putInt(Constants.PREFERENCES_TIMEBASED_LICENSE_NUM_MINUTES, value);
                    mEditor.commit();
                }
                catch (NumberFormatException e)
                {
                    // Error parsing the integer - signal that error
                    timeBasedLicenseValue.setError("Input must be a valid, +ve integer");
                }
            }
        });

        //force_interval_license_for_content
        forceIntervalLicenseForContent.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_FORCE_INTERVAL_LICENSE_FOR_CONTENT, false));
        forceIntervalLicenseForContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_FORCE_INTERVAL_LICENSE_FOR_CONTENT, isChecked);
                mEditor.commit();
            }
        });

        //interval_license_value
        intervalBasedLicenseValue.setText("" + mPreferences.getInt(Constants.PREFERENCES_INTERVAL_LICENSE_NUM_SECONDS, 30), TextView.BufferType.NORMAL);
        intervalBasedLicenseValue.addTextChangedListener(new TextWatcher()
        {
            public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after)
            {
            }

            public void onTextChanged(final CharSequence s, final int start, final int before, final int count)
            {
            }

            public void afterTextChanged(final Editable editable)
            {
                final String s = editable.toString();
                try
                {
                    final int value = Integer.parseInt(s);
                    mEditor.putInt(Constants.PREFERENCES_INTERVAL_LICENSE_NUM_SECONDS, value);
                    mEditor.commit();
                }
                catch (NumberFormatException e)
                {
                    // Error parsing the integer - signal that error
                    timeBasedLicenseValue.setError("Input must be a valid, +ve integer");
                }
            }
        });


        //force_opl_license_for_content
        forceOPLLicenseForContent.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_FORCE_OPL_LICENSE_FOR_CONTENT, false));
        forceOPLLicenseForContent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_FORCE_OPL_LICENSE_FOR_CONTENT, isChecked);
                mEditor.commit();
            }
        });

        //opl_license_value
        oplLicenseValue.setText("" + mPreferences.getInt(Constants.PREFERENCES_OPL_LICENSE_LEVEL, 100), TextView.BufferType.NORMAL);
        oplLicenseValue.addTextChangedListener(new TextWatcher()
        {
            public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after)
            {
            }

            public void onTextChanged(final CharSequence s, final int start, final int before, final int count)
            {
            }

            public void afterTextChanged(final Editable editable)
            {
                final String s = editable.toString();
                try
                {
                    final int value = Integer.parseInt(s);
                    mEditor.putInt(Constants.PREFERENCES_OPL_LICENSE_LEVEL, value);
                    mEditor.commit();
                }
                catch (NumberFormatException e)
                {
                    // Error parsing the integer - signal that error
                    oplLicenseValue.setError("Input must be a valid, +ve integer");
                }
            }
        });

        //Play enablers
        playEnablersSelectionDialog = new MultipleSelectionDialog(this,
                                                                  getResources().getStringArray(R.array.play_enablers),
                                                                  mPreferences,
                                                                  Constants.PREFERENCES_PLAY_ENABLERS,
                                                                  getResources().getString(R.string.play_enablers_label_text));

        button = (Button) findViewById(R.id.play_enablers_button);
        button.setOnClickListener(new View.OnClickListener()
        {


            public void onClick(final View view)
            {

                showDialog(PLAY_ENABLERS_SELECTION);
            }
        });

        button = (Button) findViewById(R.id.button_purge_database);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {

                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.delete_drm_databases_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Purge database");
                        DRMAgentDelegate.purgeDatabase(SettingsActivity.this);
                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });

        //ask_for_license_acknowledgement_for_licenses
        askForLicenseAck.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_FORCE_ACKNOWLEDGEMENT_LICENSE_FOR_CONTENT, false));
        askForLicenseAck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_FORCE_ACKNOWLEDGEMENT_LICENSE_FOR_CONTENT, isChecked);
                mEditor.commit();
            }
        });

        //use_web_initiator_la_handler
        useWebInitiatorLaHandler.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_USE_WEB_INITIATOR_LA_HANDLER, false));
        useWebInitiatorLaHandler.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_USE_WEB_INITIATOR_LA_HANDLER, isChecked);
                mEditor.commit();
            }
        });

        // use headless HLS
        final CheckBox useHeadlessHLS = (CheckBox) findViewById(R.id.use_headless_hls);
        useHeadlessHLS.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_USE_HEADLESS_HLS, false));
        useHeadlessHLS.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_USE_HEADLESS_HLS, isChecked);
                mEditor.commit();
            }
        });

        // use content from US
        final CheckBox useContentFromUS = (CheckBox) findViewById(R.id.use_content_from_us);
        useContentFromUS.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_USE_CONTENT_FROM_US, false));
        useContentFromUS.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_USE_CONTENT_FROM_US, isChecked);
                mEditor.commit();
                //we clear also the cache
                ClearCache();
            }
        });

        // trust all SSL certificates
        final CheckBox trustAllCerts = (CheckBox) findViewById(R.id.https_client_trust_all_certs);
        trustAllCerts.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_HTTPS_CLIENT_TRUST_ALL_CERTS, false));
        trustAllCerts.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_HTTPS_CLIENT_TRUST_ALL_CERTS, isChecked);
                final DRMAgentConfiguration agentConfig = getDRMAgent().getDRMAgentConfiguration();
                if (agentConfig.isHttpsTrustAllSSLCertificates() != isChecked)
                {
                    agentConfig.setHttpsTrustAllSSLCertificates(isChecked);
                    getDRMAgent().setDRMAgentConfiguration(agentConfig);
                }
                mEditor.commit();
            }
        });

        // Show timestamp in live streams - useful for tests.
        final CheckBox showTimestampInLiveStreams = (CheckBox) findViewById(R.id.show_timestamp_in_live_streams);
        showTimestampInLiveStreams.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_SHOW_TIMESTAMP_IN_LIVE_STREAMS, false));
        showTimestampInLiveStreams.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                mEditor.putBoolean(Constants.PREFERENCES_SHOW_TIMESTAMP_IN_LIVE_STREAMS, isChecked);
                mEditor.commit();
            }
        });


        // show advanced options
        final CheckBox showAdvancedOptions = (CheckBox) findViewById(R.id.show_advanced_options);
        showAdvancedOptions.setChecked(mPreferences.getBoolean(Constants.PREFERENCES_SHOW_ADVANCED_OPTIONS, false));
        showAdvancedOptions.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked)
            {
                setAdvancedOptionsVisibility(findViewById(android.R.id.content), isChecked);
                mEditor.putBoolean(Constants.PREFERENCES_SHOW_ADVANCED_OPTIONS, isChecked);
                mEditor.commit();
            }
        });

        setAdvancedOptionsVisibility(findViewById(android.R.id.content),
                mPreferences.getBoolean(Constants.PREFERENCES_SHOW_ADVANCED_OPTIONS, false));
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        if(mIsServiceBound)
        {
            unbindService(mServiceConnection);
        }
    }

    private void restoreContentFromRemoteServer()
    {
        if(!mIsServiceBound)
        {
            bindService(new Intent(getApplication(), DownloadService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
        }
        else
        {
            initDownloadContentFromRemoteServer();
        }
    }

    protected abstract String getRemoteContentLocation();

    private void ClearCache()
    {
        Log.d(TAG, "Initiating delete of all cached content");
        DRMAgentDelegate.purgeCachedFiles(this);
        ClearNexCache();
    }

    private static void setAdvancedOptionsVisibility(View rootView, boolean isVisible)
    {
        ArrayList<View> views = getViewsByTag(rootView, Constants.ADVANCED_OPTIONS_TAG);

        final int visibility = isVisible ? View.VISIBLE : View.GONE;

        for (View view: views)
        {
            view.setVisibility(visibility);
        }
    }

    private static ArrayList<View> getViewsByTag(View view, String tag)
    {
        ArrayList<View> views = new ArrayList<View>();

        final Object tagObj = view.getTag();
        if (tagObj != null && tagObj.equals(tag))
        {
            views.add(view);
        }
        else if (view instanceof ViewGroup)
        {
            for (int i = 0; i < ((ViewGroup)view).getChildCount(); i++)
            {
                final View child = ((ViewGroup)view).getChildAt(i);
                views.addAll(getViewsByTag(child, tag));
            }
        }

        return views;
    }

    protected void ClearNexCache()
    {
        //do nothing
    }

    protected void configButtonManageCachedMediaAction()
    {
        Button button = (Button) findViewById(R.id.button_manage_cached_media);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {
                startActivity(new Intent(getBaseContext(), CacheMediaManagementActivity.class));
            }
        });
    }

    protected void configButtonCancelAllDownloads()
    {
        Button button = (Button) findViewById(R.id.button_cancel_all_downloads);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {
                AlertDialog customAlertDialog = createCustomAlertDialog(getText(R.string.cancel_all_downloads_warning), new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dlg, int sumthin)
                    {
                        Log.d(TAG, "Cancel All Pending Content downloads");
                        mDownloadService.cancelAllPendingDownloads();
                        sLastDisplayedDialog = null;
                    }
                });

                sLastDisplayedDialog = customAlertDialog;
                customAlertDialog.show();
            }
        });
    }

    protected void configButtonPerformRevocationListUpdate()
    {
        final Button button = (Button) findViewById(R.id.update_revocation_list);
        button.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(final View view)
            {
                showDialog(SettingsActivity.REVOCATION_LIST_UPDATE_CONFIRM);
            }
        });
    }

    @Override
    protected void onPause()
    {
        mEditor.commit();

        // Push any changes made in config into agent as well
        DRMAgentDelegate.reconfigure(SettingsActivity.this);

        super.onPause();
    }

    @Override
    protected void onStop()
    {
        mEditor.commit();
        super.onStop();
    }

    protected AlertDialog createCustomAlertDialog(CharSequence message, DialogInterface.OnClickListener onClickListener)
    {
        final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setTitle(R.string.warning);
        alertDialogBuilder.setMessage(message);
        alertDialogBuilder.setInverseBackgroundForced(true);
        alertDialogBuilder.setPositiveButton(getText(R.string.Yes), onClickListener);
        alertDialogBuilder.setNegativeButton(getText(R.string.No), new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dlg, int sumthin)
            {
                // Do nothing?
                sLastDisplayedDialog = null;
            }
        });


        return alertDialogBuilder.create();
    }

    protected AlertDialog createCustomAlertDialog(List<DRMLogCallback.DRMLogEntry> drmLogEntries)
    {
        final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);

        alertDialogBuilder.setTitle(getString(R.string.drm_logs_dialog_title));

        final List<String> drmLogs = new ArrayList<>();
        for(DRMLogCallback.DRMLogEntry drmLogEntry : drmLogEntries){
            drmLogs.add(new SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(drmLogEntry.getTimeStamp()) +
                    "  " + drmLogEntry.getDRMLogLevel() + "/" + drmLogEntry.getTag() + ": " + drmLogEntry.getMessage());
        }

        final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(SettingsActivity.this,
                android.R.layout.simple_list_item_1, drmLogs);
        alertDialogBuilder.setAdapter(arrayAdapter, null);
        return alertDialogBuilder.create();

    }
}
