/*
 * Copyright (C) 2013 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 com.android.media.remotedisplay;

import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.IRemoteDisplayCallback;
import android.media.IRemoteDisplayProvider;
import android.media.RemoteDisplayState;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.ArrayMap;

import java.util.Collection;

/**
 * Base class for remote display providers implemented as unbundled services.
 * <p>
 * To implement your remote display provider service, create a subclass of
 * {@link Service} and override the {@link Service#onBind Service.onBind()} method
 * to return the provider's binder when the {@link #SERVICE_INTERFACE} is requested.
 * </p>
 * <pre>
 *   public class SampleRemoteDisplayProviderService extends Service {
 *       private SampleProvider mProvider;
 *
 *       public IBinder onBind(Intent intent) {
 *           if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) {
 *               if (mProvider == null) {
 *                   mProvider = new SampleProvider(this);
 *               }
 *               return mProvider.getBinder();
 *           }
 *           return null;
 *       }
 *
 *       class SampleProvider extends RemoteDisplayProvider {
 *           public SampleProvider() {
 *               super(SampleRemoteDisplayProviderService.this);
 *           }
 *
 *           // --- Implementation goes here ---
 *       }
 *   }
 * </pre>
 * <p>
 * Declare your remote display provider service in your application manifest
 * like this:
 * </p>
 * <pre>
 *   &lt;application>
 *       &lt;uses-library android:name="com.android.media.remotedisplay" />
 *
 *       &lt;service android:name=".SampleRemoteDisplayProviderService"
 *               android:label="@string/sample_remote_display_provider_service"
 *               android:exported="true"
 *               android:permission="android.permission.BIND_REMOTE_DISPLAY">
 *           &lt;intent-filter>
 *               &lt;action android:name="com.android.media.remotedisplay.RemoteDisplayProvider" />
 *           &lt;/intent-filter>
 *       &lt;/service>
 *   &lt;/application>
 * </pre>
 * <p>
 * This object is not thread safe.  It is only intended to be accessed on the
 * {@link Context#getMainLooper main looper thread} of an application.
 * </p><p>
 * IMPORTANT: This class is effectively a public API for unbundled applications, and
 * must remain API stable. See README.txt in the root of this package for more information.
 * </p>
 */
public abstract class RemoteDisplayProvider {
    private static final int MSG_SET_CALLBACK = 1;
    private static final int MSG_SET_DISCOVERY_MODE = 2;
    private static final int MSG_CONNECT = 3;
    private static final int MSG_DISCONNECT = 4;
    private static final int MSG_SET_VOLUME = 5;
    private static final int MSG_ADJUST_VOLUME = 6;

    private final Context mContext;
    private final ProviderStub mStub;
    private final ProviderHandler mHandler;
    private final ArrayMap<String, RemoteDisplay> mDisplays =
            new ArrayMap<String, RemoteDisplay>();
    private IRemoteDisplayCallback mCallback;
    private int mDiscoveryMode = DISCOVERY_MODE_NONE;

    private PendingIntent mSettingsPendingIntent;

    /**
     * The {@link Intent} that must be declared as handled by the service.
     * Put this in your manifest.
     */
    public static final String SERVICE_INTERFACE = RemoteDisplayState.SERVICE_INTERFACE;

    /**
     * Discovery mode: Do not perform any discovery.
     */
    public static final int DISCOVERY_MODE_NONE = RemoteDisplayState.DISCOVERY_MODE_NONE;

    /**
     * Discovery mode: Passive or low-power periodic discovery.
     * <p>
     * This mode indicates that an application is interested in knowing whether there
     * are any remote displays paired or available but doesn't need the latest or
     * most detailed information.  The provider may scan at a lower rate or rely on
     * knowledge of previously paired devices.
     * </p>
     */
    public static final int DISCOVERY_MODE_PASSIVE = RemoteDisplayState.DISCOVERY_MODE_PASSIVE;

    /**
     * Discovery mode: Active discovery.
     * <p>
     * This mode indicates that the user is actively trying to connect to a route
     * and we should perform continuous scans.  This mode may use significantly more
     * power but is intended to be short-lived.
     * </p>
     */
    public static final int DISCOVERY_MODE_ACTIVE = RemoteDisplayState.DISCOVERY_MODE_ACTIVE;

    /**
     * Creates a remote display provider.
     *
     * @param context The application context for the remote display provider.
     */
    public RemoteDisplayProvider(Context context) {
        mContext = context;
        mStub = new ProviderStub();
        mHandler = new ProviderHandler(context.getMainLooper());
    }

    /**
     * Gets the context of the remote display provider.
     */
    public final Context getContext() {
        return mContext;
    }

    /**
     * Gets the Binder associated with the provider.
     * <p>
     * This is intended to be used for the onBind() method of a service that implements
     * a remote display provider service.
     * </p>
     *
     * @return The IBinder instance associated with the provider.
     */
    public IBinder getBinder() {
        return mStub;
    }

    /**
     * Called when the current discovery mode changes.
     *
     * @param mode The new discovery mode.
     */
    public void onDiscoveryModeChanged(int mode) {
    }

    /**
     * Called when the system would like to connect to a display.
     *
     * @param display The remote display.
     */
    public void onConnect(RemoteDisplay display) {
    }

    /**
     * Called when the system would like to disconnect from a display.
     *
     * @param display The remote display.
     */
    public void onDisconnect(RemoteDisplay display) {
    }

    /**
     * Called when the system would like to set the volume of a display.
     *
     * @param display The remote display.
     * @param volume The desired volume.
     */
    public void onSetVolume(RemoteDisplay display, int volume) {
    }

    /**
     * Called when the system would like to adjust the volume of a display.
     *
     * @param display The remote display.
     * @param delta An increment to add to the current volume, such as +1 or -1.
     */
    public void onAdjustVolume(RemoteDisplay display, int delta) {
    }

    /**
     * Gets the current discovery mode.
     *
     * @return The current discovery mode.
     */
    public int getDiscoveryMode() {
        return mDiscoveryMode;
    }

    /**
     * Gets the current collection of displays.
     *
     * @return The current collection of displays, which must not be modified.
     */
    public Collection<RemoteDisplay> getDisplays() {
        return mDisplays.values();
    }

    /**
     * Adds the specified remote display and notifies the system.
     *
     * @param display The remote display that was added.
     * @throws IllegalStateException if there is already a display with the same id.
     */
    public void addDisplay(RemoteDisplay display) {
        if (display == null || mDisplays.containsKey(display.getId())) {
            throw new IllegalArgumentException("display");
        }
        mDisplays.put(display.getId(), display);
        publishState();
    }

    /**
     * Updates information about the specified remote display and notifies the system.
     *
     * @param display The remote display that was added.
     * @throws IllegalStateException if the display was n
     */
    public void updateDisplay(RemoteDisplay display) {
        if (display == null || mDisplays.get(display.getId()) != display) {
            throw new IllegalArgumentException("display");
        }
        publishState();
    }

    /**
     * Removes the specified remote display and tells the system about it.
     *
     * @param display The remote display that was removed.
     */
    public void removeDisplay(RemoteDisplay display) {
        if (display == null || mDisplays.get(display.getId()) != display) {
            throw new IllegalArgumentException("display");
        }
        mDisplays.remove(display.getId());
        publishState();
    }

    /**
     * Finds the remote display with the specified id, returns null if not found.
     *
     * @param id Id of the remote display.
     * @return The display, or null if none.
     */
    public RemoteDisplay findRemoteDisplay(String id) {
        return mDisplays.get(id);
    }

    /**
     * Gets a pending intent to launch the remote display settings activity.
     *
     * @return A pending intent to launch the settings activity.
     */
    public PendingIntent getSettingsPendingIntent() {
        if (mSettingsPendingIntent == null) {
            Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
            settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            mSettingsPendingIntent = PendingIntent.getActivity(
                    mContext, 0, settingsIntent, 0, null);
        }
        return mSettingsPendingIntent;
    }

    void setCallback(IRemoteDisplayCallback callback) {
        mCallback = callback;
        publishState();
    }

    void setDiscoveryMode(int mode) {
        if (mDiscoveryMode != mode) {
            mDiscoveryMode = mode;
            onDiscoveryModeChanged(mode);
        }
    }

    void publishState() {
        if (mCallback != null) {
            RemoteDisplayState state = new RemoteDisplayState();
            final int count = mDisplays.size();
            for (int i = 0; i < count; i++) {
                final RemoteDisplay display = mDisplays.valueAt(i);
                state.displays.add(display.getInfo());
            }
            try {
                mCallback.onStateChanged(state);
            } catch (RemoteException ex) {
                // system server died?
            }
        }
    }

    final class ProviderStub extends IRemoteDisplayProvider.Stub {
        @Override
        public void setCallback(IRemoteDisplayCallback callback) {
            mHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget();
        }

        @Override
        public void setDiscoveryMode(int mode) {
            mHandler.obtainMessage(MSG_SET_DISCOVERY_MODE, mode, 0).sendToTarget();
        }

        @Override
        public void connect(String id) {
            mHandler.obtainMessage(MSG_CONNECT, id).sendToTarget();
        }

        @Override
        public void disconnect(String id) {
            mHandler.obtainMessage(MSG_DISCONNECT, id).sendToTarget();
        }

        @Override
        public void setVolume(String id, int volume) {
            mHandler.obtainMessage(MSG_SET_VOLUME, volume, 0, id).sendToTarget();
        }

        @Override
        public void adjustVolume(String id, int delta) {
            mHandler.obtainMessage(MSG_ADJUST_VOLUME, delta, 0, id).sendToTarget();
        }
    }

    final class ProviderHandler extends Handler {
        public ProviderHandler(Looper looper) {
            super(looper, null, true);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SET_CALLBACK: {
                    setCallback((IRemoteDisplayCallback)msg.obj);
                    break;
                }
                case MSG_SET_DISCOVERY_MODE: {
                    setDiscoveryMode(msg.arg1);
                    break;
                }
                case MSG_CONNECT: {
                    RemoteDisplay display = findRemoteDisplay((String)msg.obj);
                    if (display != null) {
                        onConnect(display);
                    }
                    break;
                }
                case MSG_DISCONNECT: {
                    RemoteDisplay display = findRemoteDisplay((String)msg.obj);
                    if (display != null) {
                        onDisconnect(display);
                    }
                    break;
                }
                case MSG_SET_VOLUME: {
                    RemoteDisplay display = findRemoteDisplay((String)msg.obj);
                    if (display != null) {
                        onSetVolume(display, msg.arg1);
                    }
                    break;
                }
                case MSG_ADJUST_VOLUME: {
                    RemoteDisplay display = findRemoteDisplay((String)msg.obj);
                    if (display != null) {
                        onAdjustVolume(display, msg.arg1);
                    }
                    break;
                }
            }
        }
    }
}
