/*
 * 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;

import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
import static android.media.MediaConstants.KEY_PACKAGE_NAME;
import static android.media.MediaConstants.KEY_PID;
import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
import static android.media.MediaConstants.KEY_SESSION2LINK;
import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
import static android.media.Session2Command.Result.RESULT_ERROR_UNKNOWN_ERROR;
import static android.media.Session2Command.Result.RESULT_INFO_SKIPPED;
import static android.media.Session2Token.TYPE_SESSION;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;

import java.util.concurrent.Executor;

/**
 * This API is not generally intended for third party application developers.
 * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
 * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
 * Library</a> for consistent behavior across all devices.
 *
 * Allows an app to interact with an active {@link MediaSession2} or a
 * {@link MediaSession2Service} which would provide {@link MediaSession2}. Media buttons and other
 * commands can be sent to the session.
 */
public class MediaController2 implements AutoCloseable {
    static final String TAG = "MediaController2";
    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    final ControllerCallback mCallback;

    private final IBinder.DeathRecipient mDeathRecipient = () -> close();
    private final Context mContext;
    private final Session2Token mSessionToken;
    private final Executor mCallbackExecutor;
    private final Controller2Link mControllerStub;
    private final Handler mResultHandler;
    private final SessionServiceConnection mServiceConnection;

    private final Object mLock = new Object();
    //@GuardedBy("mLock")
    private boolean mClosed;
    //@GuardedBy("mLock")
    private int mNextSeqNumber;
    //@GuardedBy("mLock")
    private Session2Link mSessionBinder;
    //@GuardedBy("mLock")
    private Session2CommandGroup mAllowedCommands;
    //@GuardedBy("mLock")
    private Session2Token mConnectedToken;
    //@GuardedBy("mLock")
    private ArrayMap<ResultReceiver, Integer> mPendingCommands;
    //@GuardedBy("mLock")
    private ArraySet<Integer> mRequestedCommandSeqNumbers;
    //@GuardedBy("mLock")
    private boolean mPlaybackActive;

    /**
     * Create a {@link MediaController2} from the {@link Session2Token}.
     * This connects to the session and may wake up the service if it's not available.
     *
     * @param context context
     * @param token token to connect to
     * @param connectionHints a session-specific argument to send to the session when connecting.
     *                        The contents of this bundle may affect the connection result.
     * @param executor executor to run callbacks on.
     * @param callback controller callback to receive changes in.
     */
    MediaController2(@NonNull Context context, @NonNull Session2Token token,
            @NonNull Bundle connectionHints, @NonNull Executor executor,
            @NonNull ControllerCallback callback) {
        if (context == null) {
            throw new IllegalArgumentException("context shouldn't be null");
        }
        if (token == null) {
            throw new IllegalArgumentException("token shouldn't be null");
        }
        mContext = context;
        mSessionToken = token;
        mCallbackExecutor = (executor == null) ? context.getMainExecutor() : executor;
        mCallback = (callback == null) ? new ControllerCallback() {} : callback;
        mControllerStub = new Controller2Link(this);
        // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
        mResultHandler = new Handler(context.getMainLooper());

        mNextSeqNumber = 0;
        mPendingCommands = new ArrayMap<>();
        mRequestedCommandSeqNumbers = new ArraySet<>();

        boolean connectRequested;
        if (token.getType() == TYPE_SESSION) {
            mServiceConnection = null;
            connectRequested = requestConnectToSession(connectionHints);
        } else {
            mServiceConnection = new SessionServiceConnection(connectionHints);
            connectRequested = requestConnectToService();
        }
        if (!connectRequested) {
            close();
        }
    }

    @Override
    public void close() {
        synchronized (mLock) {
            if (mClosed) {
                // Already closed. Ignore rest of clean up code.
                // Note: unbindService() throws IllegalArgumentException when it's called twice.
                return;
            }
            mClosed = true;
            if (mServiceConnection != null) {
                // Note: This should be called even when the bindService() has returned false.
                mContext.unbindService(mServiceConnection);
            }
            if (mSessionBinder != null) {
                try {
                    mSessionBinder.disconnect(mControllerStub, getNextSeqNumber());
                    mSessionBinder.unlinkToDeath(mDeathRecipient, 0);
                } catch (RuntimeException e) {
                    // No-op
                }
            }
            mConnectedToken = null;
            mPendingCommands.clear();
            mRequestedCommandSeqNumbers.clear();
            mCallbackExecutor.execute(() -> {
                mCallback.onDisconnected(MediaController2.this);
            });
            mSessionBinder = null;
        }
    }

    /**
     * Returns {@link Session2Token} of the connected session.
     * If it is not connected yet, it returns {@code null}.
     * <p>
     * This may differ with the {@link Session2Token} from the constructor. For example, if the
     * controller is created with the token for {@link MediaSession2Service}, this would return
     * token for the {@link MediaSession2} in the service.
     *
     * @return Session2Token of the connected session, or {@code null} if not connected
     */
    @Nullable
    public Session2Token getConnectedToken() {
        synchronized (mLock) {
            return mConnectedToken;
        }
    }

    /**
     * Returns whether the session's playback is active.
     *
     * @return {@code true} if playback active. {@code false} otherwise.
     * @see ControllerCallback#onPlaybackActiveChanged(MediaController2, boolean)
     */
    public boolean isPlaybackActive() {
        synchronized (mLock) {
            return mPlaybackActive;
        }
    }

    /**
     * Sends a session command to the session
     * <p>
     * @param command the session command
     * @param args optional arguments
     * @return a token which will be sent together in {@link ControllerCallback#onCommandResult}
     *        when its result is received.
     */
    @NonNull
    public Object sendSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
        if (command == null) {
            throw new IllegalArgumentException("command shouldn't be null");
        }

        ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                synchronized (mLock) {
                    mPendingCommands.remove(this);
                }
                mCallbackExecutor.execute(() -> {
                    mCallback.onCommandResult(MediaController2.this, this,
                            command, new Session2Command.Result(resultCode, resultData));
                });
            }
        };

        synchronized (mLock) {
            if (mSessionBinder != null) {
                int seq = getNextSeqNumber();
                mPendingCommands.put(resultReceiver, seq);
                try {
                    mSessionBinder.sendSessionCommand(mControllerStub, seq, command, args,
                            resultReceiver);
                } catch (RuntimeException e)  {
                    mPendingCommands.remove(resultReceiver);
                    resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
                }
            }
        }
        return resultReceiver;
    }

    /**
     * Cancels the session command previously sent.
     *
     * @param token the token which is returned from {@link #sendSessionCommand}.
     */
    public void cancelSessionCommand(@NonNull Object token) {
        if (token == null) {
            throw new IllegalArgumentException("token shouldn't be null");
        }
        synchronized (mLock) {
            if (mSessionBinder == null) return;
            Integer seq = mPendingCommands.remove(token);
            if (seq != null) {
                mSessionBinder.cancelSessionCommand(mControllerStub, seq);
            }
        }
    }

    // Called by Controller2Link.onConnected
    void onConnected(int seq, Bundle connectionResult) {
        Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK);
        Session2CommandGroup allowedCommands =
                connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
        boolean playbackActive = connectionResult.getBoolean(KEY_PLAYBACK_ACTIVE);

        Bundle tokenExtras = connectionResult.getBundle(KEY_TOKEN_EXTRAS);
        if (tokenExtras == null) {
            Log.w(TAG, "extras shouldn't be null.");
            tokenExtras = Bundle.EMPTY;
        } else if (MediaSession2.hasCustomParcelable(tokenExtras)) {
            Log.w(TAG, "extras contain custom parcelable. Ignoring.");
            tokenExtras = Bundle.EMPTY;
        }

        if (DEBUG) {
            Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder
                    + ", allowedCommands=" + allowedCommands);
        }
        if (sessionBinder == null || allowedCommands == null) {
            // Connection rejected.
            close();
            return;
        }
        synchronized (mLock) {
            mSessionBinder = sessionBinder;
            mAllowedCommands = allowedCommands;
            mPlaybackActive = playbackActive;

            // Implementation for the local binder is no-op,
            // so can be used without worrying about deadlock.
            sessionBinder.linkToDeath(mDeathRecipient, 0);
            mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION,
                    mSessionToken.getPackageName(), sessionBinder, tokenExtras);
        }
        mCallbackExecutor.execute(() -> {
            mCallback.onConnected(MediaController2.this, allowedCommands);
        });
    }

    // Called by Controller2Link.onDisconnected
    void onDisconnected(int seq) {
        // close() will call mCallback.onDisconnected
        close();
    }

    // Called by Controller2Link.onPlaybackActiveChanged
    void onPlaybackActiveChanged(int seq, boolean playbackActive) {
        synchronized (mLock) {
            mPlaybackActive = playbackActive;
        }
        mCallbackExecutor.execute(() -> {
            mCallback.onPlaybackActiveChanged(MediaController2.this, playbackActive);
        });
    }

    // Called by Controller2Link.onSessionCommand
    void onSessionCommand(int seq, Session2Command command, Bundle args,
            @Nullable ResultReceiver resultReceiver) {
        synchronized (mLock) {
            mRequestedCommandSeqNumbers.add(seq);
        }
        mCallbackExecutor.execute(() -> {
            boolean isCanceled;
            synchronized (mLock) {
                isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
            }
            if (isCanceled) {
                if (resultReceiver != null) {
                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
                }
                return;
            }
            Session2Command.Result result = mCallback.onSessionCommand(
                    MediaController2.this, command, args);
            if (resultReceiver != null) {
                if (result == null) {
                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
                } else {
                    resultReceiver.send(result.getResultCode(), result.getResultData());
                }
            }
        });
    }

    // Called by Controller2Link.onSessionCommand
    void onCancelCommand(int seq) {
        synchronized (mLock) {
            mRequestedCommandSeqNumbers.remove(seq);
        }
    }

    private int getNextSeqNumber() {
        synchronized (mLock) {
            return mNextSeqNumber++;
        }
    }

    private Bundle createConnectionRequest(@NonNull Bundle connectionHints) {
        Bundle connectionRequest = new Bundle();
        connectionRequest.putString(KEY_PACKAGE_NAME, mContext.getPackageName());
        connectionRequest.putInt(KEY_PID, Process.myPid());
        connectionRequest.putBundle(KEY_CONNECTION_HINTS, connectionHints);
        return connectionRequest;
    }

    private boolean requestConnectToSession(@NonNull Bundle connectionHints) {
        Session2Link sessionBinder = mSessionToken.getSessionLink();
        Bundle connectionRequest = createConnectionRequest(connectionHints);
        try {
            sessionBinder.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
        } catch (RuntimeException e) {
            Log.w(TAG, "Failed to call connection request", e);
            return false;
        }
        return true;
    }

    private boolean requestConnectToService() {
        // Service. Needs to get fresh binder whenever connection is needed.
        final Intent intent = new Intent(MediaSession2Service.SERVICE_INTERFACE);
        intent.setClassName(mSessionToken.getPackageName(), mSessionToken.getServiceName());

        // Use bindService() instead of startForegroundService() to start session service for three
        // reasons.
        // 1. Prevent session service owner's stopSelf() from destroying service.
        //    With the startForegroundService(), service's call of stopSelf() will trigger immediate
        //    onDestroy() calls on the main thread even when onConnect() is running in another
        //    thread.
        // 2. Minimize APIs for developers to take care about.
        //    With bindService(), developers only need to take care about Service.onBind()
        //    but Service.onStartCommand() should be also taken care about with the
        //    startForegroundService().
        // 3. Future support for UI-less playback
        //    If a service wants to keep running, it should be either foreground service or
        //    bound service. But there had been request for the feature for system apps
        //    and using bindService() will be better fit with it.
        synchronized (mLock) {
            boolean result = mContext.bindService(
                    intent, mServiceConnection, Context.BIND_AUTO_CREATE);
            if (!result) {
                Log.w(TAG, "bind to " + mSessionToken + " failed");
                return false;
            } else if (DEBUG) {
                Log.d(TAG, "bind to " + mSessionToken + " succeeded");
            }
        }
        return true;
    }

    /**
     * This API is not generally intended for third party application developers.
     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
     * Library</a> for consistent behavior across all devices.
     * <p>
     * Builder for {@link MediaController2}.
     * <p>
     * Any incoming event from the {@link MediaSession2} will be handled on the callback
     * executor. If it's not set, {@link Context#getMainExecutor()} will be used by default.
     */
    public static final class Builder {
        private Context mContext;
        private Session2Token mToken;
        private Bundle mConnectionHints;
        private Executor mCallbackExecutor;
        private ControllerCallback mCallback;

        /**
         * Creates a builder for {@link MediaController2}.
         *
         * @param context context
         * @param token token of the session to connect to
         */
        public Builder(@NonNull Context context, @NonNull Session2Token token) {
            if (context == null) {
                throw new IllegalArgumentException("context shouldn't be null");
            }
            if (token == null) {
                throw new IllegalArgumentException("token shouldn't be null");
            }
            mContext = context;
            mToken = token;
        }

        /**
         * Set the connection hints for the controller.
         * <p>
         * {@code connectionHints} is a session-specific argument to send to the session when
         * connecting. The contents of this bundle may affect the connection result.
         * <p>
         * An {@link IllegalArgumentException} will be thrown if the bundle contains any
         * non-framework Parcelable objects.
         *
         * @param connectionHints a bundle which contains the connection hints
         * @return The Builder to allow chaining
         */
        @NonNull
        public Builder setConnectionHints(@NonNull Bundle connectionHints) {
            if (connectionHints == null) {
                throw new IllegalArgumentException("connectionHints shouldn't be null");
            }
            if (MediaSession2.hasCustomParcelable(connectionHints)) {
                throw new IllegalArgumentException("connectionHints shouldn't contain any custom "
                        + "parcelables");
            }
            mConnectionHints = new Bundle(connectionHints);
            return this;
        }

        /**
         * Set callback for the controller and its executor.
         *
         * @param executor callback executor
         * @param callback session callback.
         * @return The Builder to allow chaining
         */
        @NonNull
        public Builder setControllerCallback(@NonNull Executor executor,
                @NonNull ControllerCallback callback) {
            if (executor == null) {
                throw new IllegalArgumentException("executor shouldn't be null");
            }
            if (callback == null) {
                throw new IllegalArgumentException("callback shouldn't be null");
            }
            mCallbackExecutor = executor;
            mCallback = callback;
            return this;
        }

        /**
         * Build {@link MediaController2}.
         *
         * @return a new controller
         */
        @NonNull
        public MediaController2 build() {
            if (mCallbackExecutor == null) {
                mCallbackExecutor = mContext.getMainExecutor();
            }
            if (mCallback == null) {
                mCallback = new ControllerCallback() {};
            }
            if (mConnectionHints == null) {
                mConnectionHints = Bundle.EMPTY;
            }
            return new MediaController2(
                    mContext, mToken, mConnectionHints, mCallbackExecutor, mCallback);
        }
    }

    /**
     * This API is not generally intended for third party application developers.
     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
     * Library</a> for consistent behavior across all devices.
     * <p>
     * Interface for listening to change in activeness of the {@link MediaSession2}.
     */
    public abstract static class ControllerCallback {
        /**
         * Called when the controller is successfully connected to the session. The controller
         * becomes available afterwards.
         *
         * @param controller the controller for this event
         * @param allowedCommands commands that's allowed by the session.
         */
        public void onConnected(@NonNull MediaController2 controller,
                @NonNull Session2CommandGroup allowedCommands) {}

        /**
         * Called when the session refuses the controller or the controller is disconnected from
         * the session. The controller becomes unavailable afterwards and the callback wouldn't
         * be called.
         * <p>
         * It will be also called after the {@link #close()}, so you can put clean up code here.
         * You don't need to call {@link #close()} after this.
         *
         * @param controller the controller for this event
         */
        public void onDisconnected(@NonNull MediaController2 controller) {}

        /**
         * Called when the session's playback activeness is changed.
         *
         * @param controller the controller for this event
         * @param playbackActive {@code true} if the session's playback is active.
         *                       {@code false} otherwise.
         * @see MediaController2#isPlaybackActive()
         */
        public void onPlaybackActiveChanged(@NonNull MediaController2 controller,
                boolean playbackActive) {}

        /**
         * Called when the connected session sent a session command.
         *
         * @param controller the controller for this event
         * @param command the session command
         * @param args optional arguments
         * @return the result for the session command. If {@code null}, RESULT_INFO_SKIPPED
         *         will be sent to the session.
         */
        @Nullable
        public Session2Command.Result onSessionCommand(@NonNull MediaController2 controller,
                @NonNull Session2Command command, @Nullable Bundle args) {
            return null;
        }

        /**
         * Called when the command sent to the connected session is finished.
         *
         * @param controller the controller for this event
         * @param token the token got from {@link MediaController2#sendSessionCommand}
         * @param command the session command
         * @param result the result of the session command
         */
        public void onCommandResult(@NonNull MediaController2 controller, @NonNull Object token,
                @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
    }

    // This will be called on the main thread.
    private class SessionServiceConnection implements ServiceConnection {
        private final Bundle mConnectionHints;

        SessionServiceConnection(@Nullable Bundle connectionHints) {
            mConnectionHints = connectionHints;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // Note that it's always main-thread.
            boolean connectRequested = false;
            try {
                if (DEBUG) {
                    Log.d(TAG, "onServiceConnected " + name + " " + this);
                }
                // Sanity check
                if (!mSessionToken.getPackageName().equals(name.getPackageName())) {
                    Log.wtf(TAG, "Expected connection to " + mSessionToken.getPackageName()
                            + " but is connected to " + name);
                    return;
                }
                IMediaSession2Service iService = IMediaSession2Service.Stub.asInterface(service);
                if (iService == null) {
                    Log.wtf(TAG, "Service interface is missing.");
                    return;
                }
                Bundle connectionRequest = createConnectionRequest(mConnectionHints);
                iService.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
                connectRequested = true;
            } catch (RemoteException e) {
                Log.w(TAG, "Service " + name + " has died prematurely", e);
            } finally {
                if (!connectRequested) {
                    close();
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // Temporal lose of the binding because of the service crash. System will automatically
            // rebind, so just no-op.
            if (DEBUG) {
                Log.w(TAG, "Session service " + name + " is disconnected.");
            }
            close();
        }

        @Override
        public void onBindingDied(ComponentName name) {
            // Permanent lose of the binding because of the service package update or removed.
            // This SessionServiceRecord will be removed accordingly, but forget session binder here
            // for sure.
            close();
        }
    }
}
