package com.insidesecure.drm.android.reference.activities;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URI;
import java.util.*;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.insidesecure.drm.android.reference.*;
import com.insidesecure.drmagent.*;
import com.insidesecure.drmagent.download.DownloadManager;
import com.insidesecure.drmagent.mediaplayer.MediaPlayer;

/**
 * @author INSIDE Secure
 */
public class ActivityHelper
{
    private static String TAG = "ActivityHelper";
    private static String mErrorMsg;

    public static void setupSelectedAudio(final MediaPlayer mediaPlayer, final Bundle extras)
    {
        final PlaybackInfo playbackInfo = (PlaybackInfo) extras.get(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO);

        if (playbackInfo != null)
        {
            DRMContent.AudioTrack audioTrack = playbackInfo.mEnabledAudioTrack;
            DRMContent.AudioQualityLevel audioQualityLevel = playbackInfo.mEnabledAudioTrackQualityLevel;
            if (audioTrack != null)
            {
                if (audioQualityLevel == null)
                {
                    audioQualityLevel = DRMContent.DEFAULT_AUDIO_QUALITY_LEVEL;
                }
                mediaPlayer.setAudioTrack(audioTrack, audioQualityLevel);
            }
        }
    }

    public static void setupSelectedSubtitleTrack(final DRMContent drmContent, final MediaPlayer mediaPlayer, final Bundle extras, final Activity activity)
    {
        final PlaybackInfo playbackInfo = (PlaybackInfo) extras.get(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO);

        // Reset the selected subtitle to no subtitle for now
        mediaPlayer.setSubtitleTrack(DRMContent.NO_SUBTITLE_TRACK);

        if (playbackInfo != null)
        {
            if (playbackInfo.mEnabledSideloadedSubtitles)
            {
                Log.i(TAG, "Enabling side-loaded subtitles as requested");

                // Sideloaded subtitles
                String[] subTitleFilePaths = retrieveSubtitles(extras, new String[]{"dfxp", "srt", "sub", "vtt"});

                if (subTitleFilePaths.length == 0)
                {
                    Log.d(TAG, "No supported subtitles for this content.");
                }
                else
                {
                    for (String subtitleFilePath : subTitleFilePaths)
                    {
                        Log.d(TAG, "Found side-loadable subtitle available in " + subtitleFilePath + ", proceeding to load");
                        try
                        {
                            loadSubtitlesFromPath(drmContent, activity, subtitleFilePath);
                            Log.d(TAG, "Subtitles loaded successfully from " + subtitleFilePath);
                        }
                        catch (Exception e)
                        {
                            Log.e(TAG, "Error while loading side-loaded subtitles: " + e.getMessage(), e);
                        }
                    }
                }
            }
            else
            {
                final DRMContent.SubtitleTrack enabledSubtitleTrack = playbackInfo.mEnabledSubtitleTrack;
                if (enabledSubtitleTrack != null)
                {
                    mediaPlayer.setSubtitleTrack(enabledSubtitleTrack);
                }
            }
        }
    }

    private static void loadSubtitlesFromPath(final DRMContent drmContent, final Activity activity, final String subtitleFilePath) throws Exception
    {
        try
        {
            DRMContent.FourCC fourCC;

            // Get the extension first
            int lastDot = subtitleFilePath.lastIndexOf(".");

            if (lastDot < 0 || lastDot == subtitleFilePath.length() - 1)
            {
                mErrorMsg = "Subtitle file with no extension specified";
                Log.e(TAG, mErrorMsg);
                throw new DRMAgentException(mErrorMsg, DRMError.INVALID_PARAMETER);
            }
            else
            {
                String extension = subtitleFilePath.substring(lastDot + 1);
                if ((fourCC = Tools.getFourCC(extension)) == null)
                {
                    mErrorMsg = "Unsupported subtitle file format: " + extension;
                    Log.e(TAG, mErrorMsg);
                    throw new DRMAgentException(mErrorMsg, DRMError.NOT_SUPPORTED);
                }
            }

            try
            {
                final BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(subtitleFilePath));
                try
                {
                    DRMContent.SubtitleTrack sideLoadedSubtitleTrack = new DRMContent.SubtitleTrack("default", subtitleFilePath, DRMContent.SubtitleTrackType.SUBTITLE, Collections.<String, String>emptyMap(), fourCC);
                    drmContent.getSideloadedSubtitleManager().addSubtitles(sideLoadedSubtitleTrack, inputStream, 0);
                }
                finally
                {
                    inputStream.close();
                }
            }
            catch (FileNotFoundException e)
            {
                mErrorMsg = "Subtitle file " + subtitleFilePath + " doesn't exist";
                Log.e(TAG, mErrorMsg);
                throw new DRMAgentException(mErrorMsg, DRMError.IO_FILE_NOT_FOUND);
            }
            catch (DRMAgentException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                mErrorMsg = "Error reading from subtitle file: " + e.getMessage();
                Log.e(TAG, mErrorMsg);
                activity.runOnUiThread(new Runnable()
                {
                    public void run()
                    {
                        Toast.makeText(activity.getApplicationContext(), mErrorMsg, Toast.LENGTH_LONG).show();
                    }
                });

                throw new DRMAgentException(mErrorMsg, DRMError.IO_ERROR);
            }
            Log.d(TAG, "Subtitles added from " + subtitleFilePath);

        }
        catch (Exception e)
        {
            mErrorMsg = "Can't open subtitle: " + e.getMessage();
            Log.e(TAG, mErrorMsg);
            activity.runOnUiThread(new Runnable()
            {
                public void run()
                {
                    Toast.makeText(activity.getApplicationContext(), mErrorMsg, Toast.LENGTH_LONG).show();
                }
            });
        }
    }


    public static void setupHDMIControl(final Activity activity, final DRMAgent drmAgent, final Bundle extras)
    {
        final PlaybackInfo playbackInfo = (PlaybackInfo) extras.get(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO);

        // Extras override settings - will use it from here
        HDMIControl hdmiControl = playbackInfo.mEnabledHDMIControl;

        // Only if we dont get it from the extras do we check settings
        if (hdmiControl == null)
        {
            Log.d(TAG, "No HDMI control value specified from extras, will use settings");
            final int hdmi = activity.getSharedPreferences(Constants.PREFERENCES_FILENAME, Context.MODE_PRIVATE).getInt(Constants.PREFERENCES_HDMI_SETTING, 0);
            hdmiControl = HDMIControl.values()[hdmi];
        }

        Log.d(TAG, "HDMI Control set to : " + hdmiControl);
        try
        {
            drmAgent.setHDMIControl(hdmiControl);
        }
        catch (Exception exception)
        {
            Log.e(TAG, exception.toString());
        }

    }


    public static void setupDownloadAndPlay(final DRMContent drmContent, final DownloadManager.DownloadEventListener downloadEventListener, final Bundle extras)
    {
        final PlaybackInfo playbackInfo = (PlaybackInfo) extras.get(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO);

        if (playbackInfo != null && playbackInfo.mDownloadAndPlay)
        {
            // Enable Download & Play - this method assumes the DRMContent instance has been
            // initilized and that the requested video quality levels and audio/subtitle track(s)
            // have already been selected

            final List<DRMContent.VideoQualityLevel> selectedVideoQualityLevels = drmContent.getSelectedVideoQualityLevels();
            DRMContent.VideoQualityLevel selectedVideoQualityLevel = null;

            if (selectedVideoQualityLevels.size() > 1)
            {
                Log.w(TAG, "More than 1 bit-rate selected for Download & Play playback, will pick first available one");
            }
            if (selectedVideoQualityLevels.size() > 0)
            {
                selectedVideoQualityLevel = selectedVideoQualityLevels.get(0);
            }

            DRMContent.DownloadAndPlayRequest downloadAndPlayRequest = new DRMContent.DownloadAndPlayRequest();

            downloadAndPlayRequest.mVideoQualityLevel = selectedVideoQualityLevel;

            @SuppressWarnings("unchecked") final List<DRMContent.AudioTrack> selectedAudioTracks = playbackInfo.mEnabledAudioTracks;
            // If nothing is specified in the Constants.ENABLED_AUDIO_TRACKS, this should be used instead
            final DRMContent.AudioTrack audioTrack = drmContent.getAudioTrack();
            downloadAndPlayRequest.mAudioTracks = selectedAudioTracks == null ? Arrays.asList(audioTrack) : selectedAudioTracks;

            // We currently download *all* subtitle tracks
            @SuppressWarnings("unchecked") final List<DRMContent.SubtitleTrack> selectedSubtitleTracks = playbackInfo.mEnabledSubtitleTracks;
            final DRMContent.SubtitleTrack selectedSubtitleTrack = drmContent.getSubtitleTrack();
            downloadAndPlayRequest.mSubtitleTracks = selectedSubtitleTracks == null ? selectedSubtitleTrack == DRMContent.NO_SUBTITLE_TRACK ? Collections.<DRMContent.SubtitleTrack>emptyList() : Arrays.asList(selectedSubtitleTrack) : selectedSubtitleTracks;

            // Enable Download & Play using the above paramters for video quality level, audio track(s) and subtitle track(s)
            drmContent.enableDownloadAndPlay(downloadAndPlayRequest);

            // Setup the listener which will be called for the download events
            drmContent.setDownloadEventListener(downloadEventListener);
        }
    }

    public static void setupSelectedVideoQualityLevels(final DRMContent drmContent, final Bundle extras)
    {

        final PlaybackInfo playbackInfo = (PlaybackInfo) extras.get(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO);

        if (playbackInfo != null)
        {
            // Set the selected quality levels
            @SuppressWarnings("unchecked") final List<DRMContent.VideoQualityLevel> enabledTracks = playbackInfo.mEnabledVideoTracks;
            if (enabledTracks == null || enabledTracks.isEmpty())
            {
                Log.d(TAG, "No video quality levels available");
                return;
            }
            final List<DRMContent.VideoQualityLevel> allLevels = drmContent.getVideoQualityLevels();
            Log.d(TAG, "Number of video quality levels: " + allLevels.size());
            Log.d(TAG, "Enabled Video Quality Levels (" + enabledTracks.size() + "/" + allLevels.size() + ") :" + enabledTracks);
            drmContent.setVideoQualityLevels(enabledTracks);
        }

    }


    public static String[] retrieveSubtitles(final Bundle extras, final String[] supportedExtensions)
    {

        final PlaybackInfo playbackInfo = (PlaybackInfo) extras.get(Constants.INTENT_EXTRA_CONTENT_PLAYBACK_INFO);

        if (playbackInfo != null)
        {
            List<String> subtitleFiles = new ArrayList<String>();
            if (playbackInfo.mSubtitleFileLocation != null)
            {
                final URI subtitleFileLocation = playbackInfo.mSubtitleFileLocation;

                if (Tools.isHTTPScheme(subtitleFileLocation))
                {
                    // Eventually suck down the content and use that for the subtitle file
                    throw new RuntimeException("Unsupported subtitle file location: " + subtitleFileLocation);
                }

                final String subtitlePath = subtitleFileLocation.getPath();
                final File subtitleFile = new File(subtitlePath);
                if (!subtitleFile.exists())
                {
                    throw new RuntimeException("Subtitle file does not exists: " + subtitleFile);
                }

                subtitleFiles.add(subtitlePath);
                return subtitleFiles.toArray(new String[subtitleFiles.size()]);
            }

            if (playbackInfo.mTitle != null)
            {
                return Tools.getSubtitlePaths(playbackInfo.mTitle, supportedExtensions);
            }
        }
        throw new RuntimeException("Could not resolve side-loaded subtitle location");
    }
}
