/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.media;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaTimestamp;
import android.media.TimedMetaData;
import android.net.Uri;
import android.support.test.rule.ActivityTestRule;
import android.view.SurfaceHolder;

import androidx.annotation.CallSuper;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;

import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

/**
 * Base class for tests which use MediaPlayer2 to play audio or video.
 */
public class MediaPlayer2TestBase {
    private static final Logger LOG = Logger.getLogger(MediaPlayer2TestBase.class.getName());

    protected static final int SLEEP_TIME = 1000;
    protected static final int LONG_SLEEP_TIME = 6000;
    protected static final int STREAM_RETRIES = 20;

    protected Monitor mOnVideoSizeChangedCalled = new Monitor();
    protected Monitor mOnVideoRenderingStartCalled = new Monitor();
    protected Monitor mOnBufferingUpdateCalled = new Monitor();
    protected Monitor mOnPrepareCalled = new Monitor();
    protected Monitor mOnPlayCalled = new Monitor();
    protected Monitor mOnDeselectTrackCalled = new Monitor();
    protected Monitor mOnSeekCompleteCalled = new Monitor();
    protected Monitor mOnCompletionCalled = new Monitor();
    protected Monitor mOnInfoCalled = new Monitor();
    protected Monitor mOnErrorCalled = new Monitor();
    protected int mCallStatus;

    protected Context mContext;
    protected Resources mResources;

    protected ExecutorService mExecutor;

    protected MediaPlayer2 mPlayer = null;
    protected MediaPlayer2 mPlayer2 = null;
    protected MediaStubActivity mActivity;

    protected final Object mEventCbLock = new Object();
    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks =
            new ArrayList<MediaPlayer2.MediaPlayer2EventCallback>();
    protected final Object mEventCbLock2 = new Object();
    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks2 =
            new ArrayList<MediaPlayer2.MediaPlayer2EventCallback>();

    @Rule
    public ActivityTestRule<MediaStubActivity> mActivityRule =
            new ActivityTestRule<>(MediaStubActivity.class);

    // convenience functions to create MediaPlayer2
    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri) {
        return createMediaPlayer2(context, uri, null);
    }

    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri,
            SurfaceHolder holder) {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        int s = am.generateAudioSessionId();
        return createMediaPlayer2(context, uri, holder, null, s > 0 ? s : 0);
    }

    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri, SurfaceHolder holder,
            AudioAttributesCompat audioAttributes, int audioSessionId) {
        try {
            MediaPlayer2 mp = MediaPlayer2.create();
            final AudioAttributesCompat aa = audioAttributes != null ? audioAttributes :
                    new AudioAttributesCompat.Builder().build();
            mp.setAudioAttributes(aa);
            mp.setAudioSessionId(audioSessionId);
            mp.setDataSource(new DataSourceDesc.Builder()
                    .setDataSource(context, uri)
                    .build());
            if (holder != null) {
                mp.setSurface(holder.getSurface());
            }
            final Monitor onPrepareCalled = new Monitor();
            ExecutorService executor = Executors.newFixedThreadPool(1);
            MediaPlayer2.MediaPlayer2EventCallback ecb =
                    new MediaPlayer2.MediaPlayer2EventCallback() {
                        @Override
                        public void onInfo(
                                MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                            if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
                                onPrepareCalled.signal();
                            }
                        }
                    };
            mp.setMediaPlayer2EventCallback(executor, ecb);
            mp.prepare();
            onPrepareCalled.waitForSignal();
            mp.clearMediaPlayer2EventCallback();
            executor.shutdown();
            return mp;
        } catch (IllegalArgumentException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        } catch (SecurityException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        } catch (InterruptedException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        }
        return null;
    }

    protected static MediaPlayer2 createMediaPlayer2(Context context, int resid) {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        int s = am.generateAudioSessionId();
        return createMediaPlayer2(context, resid, null, s > 0 ? s : 0);
    }

    protected static MediaPlayer2 createMediaPlayer2(Context context, int resid,
            AudioAttributesCompat audioAttributes, int audioSessionId) {
        try {
            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
            if (afd == null) {
                return null;
            }

            MediaPlayer2 mp = MediaPlayer2.create();

            final AudioAttributesCompat aa = audioAttributes != null ? audioAttributes :
                    new AudioAttributesCompat.Builder().build();
            mp.setAudioAttributes(aa);
            mp.setAudioSessionId(audioSessionId);

            mp.setDataSource(new DataSourceDesc.Builder()
                    .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
                    .build());

            final Monitor onPrepareCalled = new Monitor();
            ExecutorService executor = Executors.newFixedThreadPool(1);
            MediaPlayer2.MediaPlayer2EventCallback ecb =
                    new MediaPlayer2.MediaPlayer2EventCallback() {
                        @Override
                        public void onInfo(
                                MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                            if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
                                onPrepareCalled.signal();
                            }
                        }
                    };
            mp.setMediaPlayer2EventCallback(executor, ecb);
            mp.prepare();
            onPrepareCalled.waitForSignal();
            mp.clearMediaPlayer2EventCallback();
            afd.close();
            executor.shutdown();
            return mp;
        } catch (IOException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        } catch (IllegalArgumentException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        } catch (SecurityException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        } catch (InterruptedException ex) {
            LOG.warning("create failed:" + ex);
            // fall through
        }
        return null;
    }

    public static class Monitor {
        private int mNumSignal;

        public synchronized void reset() {
            mNumSignal = 0;
        }

        public synchronized void signal() {
            mNumSignal++;
            notifyAll();
        }

        public synchronized boolean waitForSignal() throws InterruptedException {
            return waitForCountedSignals(1) > 0;
        }

        public synchronized int waitForCountedSignals(int targetCount) throws InterruptedException {
            while (mNumSignal < targetCount) {
                wait();
            }
            return mNumSignal;
        }

        public synchronized boolean waitForSignal(long timeoutMs) throws InterruptedException {
            return waitForCountedSignals(1, timeoutMs) > 0;
        }

        public synchronized int waitForCountedSignals(int targetCount, long timeoutMs)
                throws InterruptedException {
            if (timeoutMs == 0) {
                return waitForCountedSignals(targetCount);
            }
            long deadline = System.currentTimeMillis() + timeoutMs;
            while (mNumSignal < targetCount) {
                long delay = deadline - System.currentTimeMillis();
                if (delay <= 0) {
                    break;
                }
                wait(delay);
            }
            return mNumSignal;
        }

        public synchronized boolean isSignalled() {
            return mNumSignal >= 1;
        }

        public synchronized int getNumSignal() {
            return mNumSignal;
        }
    }

    @Before
    @CallSuper
    public void setUp() throws Exception {
        mActivity = mActivityRule.getActivity();
        try {
            mActivityRule.runOnUiThread(new Runnable() {
                public void run() {
                    mPlayer = MediaPlayer2.create();
                    mPlayer2 = MediaPlayer2.create();
                }
            });
        } catch (Throwable e) {
            e.printStackTrace();
            fail();
        }
        mContext = mActivityRule.getActivity();
        mResources = mContext.getResources();
        mExecutor = Executors.newFixedThreadPool(1);

        setUpMP2ECb(mPlayer, mEventCbLock, mEventCallbacks);
        setUpMP2ECb(mPlayer2, mEventCbLock2, mEventCallbacks2);
    }

    @After
    @CallSuper
    public void tearDown() throws Exception {
        if (mPlayer != null) {
            mPlayer.close();
            mPlayer = null;
        }
        if (mPlayer2 != null) {
            mPlayer2.close();
            mPlayer2 = null;
        }
        mExecutor.shutdown();
        mActivity = null;
    }

    protected void setUpMP2ECb(MediaPlayer2 mp, final Object cbLock,
            final List<MediaPlayer2.MediaPlayer2EventCallback> ecbs) {
        mp.setMediaPlayer2EventCallback(mExecutor, new MediaPlayer2.MediaPlayer2EventCallback() {
            @Override
            public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd, int w, int h) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onVideoSizeChanged(mp, dsd, w, h);
                    }
                }
            }

            @Override
            public void onTimedMetaDataAvailable(MediaPlayer2 mp, DataSourceDesc dsd,
                    TimedMetaData data) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onTimedMetaDataAvailable(mp, dsd, data);
                    }
                }
            }

            @Override
            public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onError(mp, dsd, what, extra);
                    }
                }
            }

            @Override
            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onInfo(mp, dsd, what, extra);
                    }
                }
            }

            @Override
            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onCallCompleted(mp, dsd, what, status);
                    }
                }
            }

            @Override
            public void onMediaTimeChanged(MediaPlayer2 mp, DataSourceDesc dsd,
                    MediaTimestamp timestamp) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onMediaTimeChanged(mp, dsd, timestamp);
                    }
                }
            }

            @Override
            public void onCommandLabelReached(MediaPlayer2 mp, Object label) {
                synchronized (cbLock) {
                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
                        ecb.onCommandLabelReached(mp, label);
                    }
                }
            }
        });
    }

    // returns true on success
    protected boolean loadResource(int resid) throws Exception {
        /* FIXME: ensure device has capability.
        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
            return false;
        }
        */

        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
        try {
            mPlayer.setDataSource(new DataSourceDesc.Builder()
                    .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
                    .build());
        } finally {
            // TODO: close afd only after setDataSource is confirmed.
            // afd.close();
        }
        return true;
    }

    protected DataSourceDesc createDataSourceDesc(int resid) throws Exception {
        /* FIXME: ensure device has capability.
        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
            return null;
        }
        */

        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
        return new DataSourceDesc.Builder()
                .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
                .build();
    }

    protected boolean checkLoadResource(int resid) throws Exception {
        return loadResource(resid);

        /* FIXME: ensure device has capability.
        return MediaUtils.check(loadResource(resid), "no decoder found");
        */
    }

    protected void playLiveVideoTest(String path, int playTime) throws Exception {
        playVideoWithRetries(path, null, null, playTime);
    }

    protected void playLiveAudioOnlyTest(String path, int playTime) throws Exception {
        playVideoWithRetries(path, -1, -1, playTime);
    }

    protected void playVideoTest(String path, int width, int height) throws Exception {
        playVideoWithRetries(path, width, height, 0);
    }

    protected void playVideoWithRetries(String path, Integer width, Integer height, int playTime)
            throws Exception {
        boolean playedSuccessfully = false;
        final Uri uri = Uri.parse(path);
        for (int i = 0; i < STREAM_RETRIES; i++) {
            try {
                mPlayer.setDataSource(new DataSourceDesc.Builder()
                        .setDataSource(mContext, uri)
                        .build());
                playLoadedVideo(width, height, playTime);
                playedSuccessfully = true;
                break;
            } catch (PrepareFailedException e) {
                // prepare() can fail because of network issues, so try again
                LOG.warning("prepare() failed on try " + i + ", trying playback again");
            }
        }
        assertTrue("Stream did not play successfully after all attempts", playedSuccessfully);
    }

    protected void playVideoTest(int resid, int width, int height) throws Exception {
        if (!checkLoadResource(resid)) {
            return; // skip
        }

        playLoadedVideo(width, height, 0);
    }

    protected void playLiveVideoTest(
            Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
            int playTime) throws Exception {
        playVideoWithRetries(uri, headers, cookies, null /* width */, null /* height */, playTime);
    }

    protected void playVideoWithRetries(
            Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
            Integer width, Integer height, int playTime) throws Exception {
        boolean playedSuccessfully = false;
        for (int i = 0; i < STREAM_RETRIES; i++) {
            try {
                mPlayer.setDataSource(new DataSourceDesc.Builder()
                        .setDataSource(mContext,
                            uri, headers, cookies)
                        .build());
                playLoadedVideo(width, height, playTime);
                playedSuccessfully = true;
                break;
            } catch (PrepareFailedException e) {
                // prepare() can fail because of network issues, so try again
                // playLoadedVideo already has reset the player so we can try again safely.
                LOG.warning("prepare() failed on try " + i + ", trying playback again");
            }
        }
        assertTrue("Stream did not play successfully after all attempts", playedSuccessfully);
    }

    /**
     * Play a video which has already been loaded with setDataSource().
     *
     * @param width width of the video to verify, or null to skip verification
     * @param height height of the video to verify, or null to skip verification
     * @param playTime length of time to play video, or 0 to play entire video.
     * with a non-negative value, this method stops the playback after the length of
     * time or the duration the video is elapsed. With a value of -1,
     * this method simply starts the video and returns immediately without
     * stoping the video playback.
     */
    protected void playLoadedVideo(final Integer width, final Integer height, int playTime)
            throws Exception {
        final float volume = 0.5f;

        boolean audioOnly = (width != null && width.intValue() == -1)
                || (height != null && height.intValue() == -1);

        mPlayer.setSurface(mActivity.getSurfaceHolder().getSurface());
        /* FIXME: ensure that screen is on in activity level.
        mPlayer.setScreenOnWhilePlaying(true);
        */

        synchronized (mEventCbLock) {
            mEventCallbacks.add(new MediaPlayer2.MediaPlayer2EventCallback() {
                @Override
                public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd, int w, int h) {
                    if (w == 0 && h == 0) {
                        // A size of 0x0 can be sent initially one time when using NuPlayer.
                        assertFalse(mOnVideoSizeChangedCalled.isSignalled());
                        return;
                    }
                    mOnVideoSizeChangedCalled.signal();
                    if (width != null) {
                        assertEquals(width.intValue(), w);
                    }
                    if (height != null) {
                        assertEquals(height.intValue(), h);
                    }
                }

                @Override
                public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                    fail("Media player had error " + what + " playing video");
                }

                @Override
                public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                    if (what == MediaPlayer2.MEDIA_INFO_VIDEO_RENDERING_START) {
                        mOnVideoRenderingStartCalled.signal();
                    } else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
                        mOnPrepareCalled.signal();
                    }
                }

                @Override
                public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
                        int what, int status) {
                    if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
                        mOnPlayCalled.signal();
                    }
                }
            });
        }
        try {
            mOnPrepareCalled.reset();
            mPlayer.prepare();
            mOnPrepareCalled.waitForSignal();
        } catch (Exception e) {
            mPlayer.reset();
            throw new PrepareFailedException();
        }

        mOnPlayCalled.reset();
        mPlayer.play();
        mOnPlayCalled.waitForSignal();
        if (!audioOnly) {
            mOnVideoSizeChangedCalled.waitForSignal();
            mOnVideoRenderingStartCalled.waitForSignal();
        }
        mPlayer.setPlayerVolume(volume);

        // waiting to complete
        if (playTime == -1) {
            return;
        } else if (playTime == 0) {
            while (mPlayer.getPlayerState() == MediaPlayerBase.PLAYER_STATE_PLAYING) {
                Thread.sleep(SLEEP_TIME);
            }
        } else {
            Thread.sleep(playTime);
        }

        mPlayer.reset();
    }

    private static class PrepareFailedException extends Exception {}

    protected void setOnErrorListener() {
        synchronized (mEventCbLock) {
            mEventCallbacks.add(new MediaPlayer2.MediaPlayer2EventCallback() {
                @Override
                public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
                    mOnErrorCalled.signal();
                }
            });
        }
    }
}
