/*
 * 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 android.media.cts;

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

import android.content.Context;
import android.media.MediaController2;
import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.ControllerInfo;
import android.media.MediaSession2.SessionCallback;
import android.media.SessionCommandGroup2;
import android.media.SessionToken2;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager.OnSessionTokensChangedListener;
import android.platform.test.annotations.AppModeFull;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Tests {@link MediaSessionManager} with {@link MediaSession2} specific APIs.
 */
@RunWith(AndroidJUnit4.class)
@SmallTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class MediaSessionManager_MediaSession2Test extends MediaSession2TestBase {
    private static final String TAG = "MediaSessionManager_MediaSession2Test";

    private MediaSessionManager mManager;
    private MediaSession2 mSession;

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
        mManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);

        // Specify TAG here so {@link MediaSession2.getInstance()} doesn't complaint about
        // per test thread differs across the {@link MediaSession2} with the same TAG.
        final MockPlayer player = new MockPlayer(1);
        mSession = new MediaSession2.Builder(mContext)
                .setPlayer(player)
                .setSessionCallback(sHandlerExecutor, new SessionCallback() { })
                .setId(TAG)
                .build();
    }

    @After
    @Override
    public void cleanUp() throws Exception {
        super.cleanUp();
        sHandler.removeCallbacksAndMessages(null);
        mSession.close();
    }

    // TODO(jaewan): Make this host-side test to see per-user behavior.
    @Ignore
    @Test
    public void testGetMediaSession2Tokens_hasMediaController() throws InterruptedException {
        final MockPlayer player = (MockPlayer) mSession.getPlayer();
        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_IDLE);

        MediaController2 controller = null;
        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
        assertNotNull(tokens);
        for (int i = 0; i < tokens.size(); i++) {
            SessionToken2 token = tokens.get(i);
            if (mContext.getPackageName().equals(token.getPackageName())
                    && TAG.equals(token.getId())) {
                assertNull(controller);
                controller = createController(token);
            }
        }
        assertNotNull(controller);

        // Test if the found controller is correct one.
        assertEquals(MediaPlayerBase.PLAYER_STATE_IDLE, controller.getPlayerState());
        controller.play();

        assertTrue(player.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
        assertTrue(player.mPlayCalled);
    }

    /**
     * Test if server recognizes a session even if the session refuses the connection from server.
     *
     * @throws InterruptedException
     */
    @Test
    @Ignore
    public void testGetSessionTokens_sessionRejected() throws InterruptedException {
        mSession.close();
        mSession = new MediaSession2.Builder(mContext).setPlayer(new MockPlayer(0))
                .setId(TAG).setSessionCallback(sHandlerExecutor, new SessionCallback() {
                    @Override
                    public SessionCommandGroup2 onConnect(
                            MediaSession2 session, ControllerInfo controller) {
                        // Reject all connection request.
                        return null;
                    }
                }).build();

        boolean foundSession = false;
        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
        assertNotNull(tokens);
        for (int i = 0; i < tokens.size(); i++) {
            SessionToken2 token = tokens.get(i);
            if (mContext.getPackageName().equals(token.getPackageName())
                    && TAG.equals(token.getId())) {
                assertFalse(foundSession);
                foundSession = true;
            }
        }
        assertTrue(foundSession);
    }

    @Test
    @Ignore
    public void testGetMediaSession2Tokens_sessionClosed() throws InterruptedException {
        mSession.close();

        // When a session is closed, it should lose binder connection between server immediately.
        // So server will forget the session.
        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
        for (int i = 0; i < tokens.size(); i++) {
            SessionToken2 token = tokens.get(i);
            assertFalse(mContext.getPackageName().equals(token.getPackageName())
                    && TAG.equals(token.getId()));
        }
    }

    @Test
    @Ignore
    public void testGetMediaSessionService2Token() throws InterruptedException {
        boolean foundTestSessionService = false;
        boolean foundTestLibraryService = false;
        List<SessionToken2> tokens = mManager.getSessionServiceTokens();
        for (int i = 0; i < tokens.size(); i++) {
            SessionToken2 token = tokens.get(i);
            if (mContext.getPackageName().equals(token.getPackageName())
                    && MockMediaSessionService2.ID.equals(token.getId())) {
                assertFalse(foundTestSessionService);
                assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
                foundTestSessionService = true;
            } else if (mContext.getPackageName().equals(token.getPackageName())
                    && MockMediaLibraryService2.ID.equals(token.getId())) {
                assertFalse(foundTestLibraryService);
                assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
                foundTestLibraryService = true;
            }
        }
        assertTrue(foundTestSessionService);
        assertTrue(foundTestLibraryService);
    }

    @Test
    @Ignore
    public void testGetAllSessionTokens() throws InterruptedException {
        boolean foundTestSession = false;
        boolean foundTestSessionService = false;
        boolean foundTestLibraryService = false;
        List<SessionToken2> tokens = mManager.getAllSessionTokens();
        for (int i = 0; i < tokens.size(); i++) {
            SessionToken2 token = tokens.get(i);
            if (!mContext.getPackageName().equals(token.getPackageName())) {
                continue;
            }
            switch (token.getId()) {
                case TAG:
                    assertFalse(foundTestSession);
                    foundTestSession = true;
                    break;
                case MockMediaSessionService2.ID:
                    assertFalse(foundTestSessionService);
                    foundTestSessionService = true;
                    assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
                    break;
                case MockMediaLibraryService2.ID:
                    assertFalse(foundTestLibraryService);
                    assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
                    foundTestLibraryService = true;
                    break;
                default:
                    fail("Unexpected session " + token + " exists in the package");
            }
        }
        assertTrue(foundTestSession);
        assertTrue(foundTestSessionService);
        assertTrue(foundTestLibraryService);
    }

    @Test
    @Ignore
    public void testAddOnSessionTokensChangedListener() throws InterruptedException {
        TokensChangedListener listener = new TokensChangedListener();
        mManager.addOnSessionTokensChangedListener(sHandlerExecutor, listener);

        listener.reset();
        MediaSession2 session1 = new MediaSession2.Builder(mContext)
                .setPlayer(new MockPlayer(0))
                .setId(UUID.randomUUID().toString())
                .build();
        assertTrue(listener.await());
        assertTrue(listener.findToken(session1.getToken()));

        listener.reset();
        session1.close();
        assertTrue(listener.await());
        assertFalse(listener.findToken(session1.getToken()));

        listener.reset();
        MediaSession2 session2 = new MediaSession2.Builder(mContext)
                .setPlayer(new MockPlayer(0))
                .setId(UUID.randomUUID().toString())
                .build();
        assertTrue(listener.await());
        assertFalse(listener.findToken(session1.getToken()));
        assertTrue(listener.findToken(session2.getToken()));

        listener.reset();
        MediaSession2 session3 = new MediaSession2.Builder(mContext)
                .setPlayer(new MockPlayer(0))
                .setId(UUID.randomUUID().toString())
                .build();
        assertTrue(listener.await());
        assertFalse(listener.findToken(session1.getToken()));
        assertTrue(listener.findToken(session2.getToken()));
        assertTrue(listener.findToken(session3.getToken()));

        listener.reset();
        session2.close();
        assertTrue(listener.await());
        assertFalse(listener.findToken(session1.getToken()));
        assertFalse(listener.findToken(session2.getToken()));
        assertTrue(listener.findToken(session3.getToken()));

        listener.reset();
        session3.close();
        assertTrue(listener.await());
        assertFalse(listener.findToken(session1.getToken()));
        assertFalse(listener.findToken(session2.getToken()));
        assertFalse(listener.findToken(session3.getToken()));

        mManager.removeOnSessionTokensChangedListener(listener);
    }

    @Test
    @Ignore
    public void testRemoveOnSessionTokensChangedListener() throws InterruptedException {
        TokensChangedListener listener = new TokensChangedListener();
        mManager.addOnSessionTokensChangedListener(sHandlerExecutor, listener);

        listener.reset();
        MediaSession2 session1 = new MediaSession2.Builder(mContext)
                .setPlayer(new MockPlayer(0))
                .setId(UUID.randomUUID().toString())
                .build();
        assertTrue(listener.await());

        mManager.removeOnSessionTokensChangedListener(listener);

        listener.reset();
        session1.close();
        assertFalse(listener.await());

        listener.reset();
        MediaSession2 session2 = new MediaSession2.Builder(mContext)
                .setPlayer(new MockPlayer(0))
                .setId(UUID.randomUUID().toString())
                .build();
        assertFalse(listener.await());

        listener.reset();
        MediaSession2 session3 = new MediaSession2.Builder(mContext)
                .setPlayer(new MockPlayer(0))
                .setId(UUID.randomUUID().toString())
                .build();
        assertFalse(listener.await());

        listener.reset();
        session2.close();
        assertFalse(listener.await());

        listener.reset();
        session3.close();
        assertFalse(listener.await());
    }

    private class TokensChangedListener implements OnSessionTokensChangedListener {
        private CountDownLatch mLatch;
        private List<SessionToken2> mTokens;

        private void reset() {
            mLatch = new CountDownLatch(1);
            mTokens = null;
        }

        private boolean await() throws InterruptedException {
            return mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
        }

        private boolean findToken(SessionToken2 token) {
            return mTokens.contains(token);
        }

        @Override
        public void onSessionTokensChanged(List<SessionToken2> tokens) {
            mTokens = tokens;
            mLatch.countDown();
        }
    }
}
