/*
 * Copyright (C) 2012 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.server.display;

import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;

import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.media.RemoteDisplay;
import android.os.Handler;
import android.os.IBinder;
import android.util.Slog;
import android.view.Surface;

import java.io.PrintWriter;
import java.util.Arrays;

/**
 * Connects to Wifi displays that implement the Miracast protocol.
 * <p>
 * The Wifi display protocol relies on Wifi direct for discovering and pairing
 * with the display.  Once connected, the Media Server opens an RTSP socket and accepts
 * a connection from the display.  After session negotiation, the Media Server
 * streams encoded buffers to the display.
 * </p><p>
 * This class is responsible for connecting to Wifi displays and mediating
 * the interactions between Media Server, Surface Flinger and the Display Manager Service.
 * </p><p>
 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
 * </p>
 */
final class WifiDisplayAdapter extends DisplayAdapter {
    private static final String TAG = "WifiDisplayAdapter";

    private WifiDisplayHandle mDisplayHandle;
    private WifiDisplayController mDisplayController;

    private WifiDisplayStatus mCurrentStatus;
    private boolean mEnabled;
    private int mScanState;
    private int mActiveDisplayState;
    private WifiDisplay mActiveDisplay;
    private WifiDisplay[] mKnownDisplays = WifiDisplay.EMPTY_ARRAY;

    private boolean mPendingStatusChangeBroadcast;

    public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
            Context context, Handler handler, Listener listener) {
        super(syncRoot, context, handler, listener, TAG);
    }

    @Override
    public void dumpLocked(PrintWriter pw) {
        super.dumpLocked(pw);

        if (mDisplayHandle == null) {
            pw.println("mDisplayHandle=null");
        } else {
            pw.println("mDisplayHandle:");
            mDisplayHandle.dumpLocked(pw);
        }

        pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
        pw.println("mEnabled=" + mEnabled);
        pw.println("mScanState=" + mScanState);
        pw.println("mActiveDisplayState=" + mActiveDisplayState);
        pw.println("mActiveDisplay=" + mActiveDisplay);
        pw.println("mKnownDisplays=" + Arrays.toString(mKnownDisplays));
        pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);

        // Try to dump the controller state.
        if (mDisplayController == null) {
            pw.println("mDisplayController=null");
        } else {
            pw.println("mDisplayController:");
            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
            ipw.increaseIndent();
            DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
        }
    }

    @Override
    public void registerLocked() {
        super.registerLocked();

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                mDisplayController = new WifiDisplayController(
                        getContext(), getHandler(), mWifiDisplayListener);
            }
        });
    }

    public void requestScanLocked() {
        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestScan();
                }
            }
        });
    }

    public void requestConnectLocked(final String address) {
        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestConnect(address);
                }
            }
        });
    }

    public void requestDisconnectLocked() {
        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestDisconnect();
                }
            }
        });
    }

    public WifiDisplayStatus getWifiDisplayStatusLocked() {
        if (mCurrentStatus == null) {
            mCurrentStatus = new WifiDisplayStatus(mEnabled, mScanState, mActiveDisplayState,
                    mActiveDisplay, mKnownDisplays);
        }
        return mCurrentStatus;
    }

    private void handleConnectLocked(WifiDisplay display, String iface) {
        handleDisconnectLocked();

        mDisplayHandle = new WifiDisplayHandle(display.getDeviceName(), iface);
    }

    private void handleDisconnectLocked() {
        if (mDisplayHandle != null) {
            mDisplayHandle.disposeLocked();
            mDisplayHandle = null;
        }
    }

    private void scheduleStatusChangedBroadcastLocked() {
        if (!mPendingStatusChangeBroadcast) {
            mPendingStatusChangeBroadcast = true;
            getHandler().post(mStatusChangeBroadcast);
        }
    }

    private final Runnable mStatusChangeBroadcast = new Runnable() {
        @Override
        public void run() {
            final Intent intent;
            synchronized (getSyncRoot()) {
                if (!mPendingStatusChangeBroadcast) {
                    return;
                }

                mPendingStatusChangeBroadcast = false;
                intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
                        getWifiDisplayStatusLocked());
            }

            // Send protected broadcast about wifi display status to receivers that
            // have the required permission.
            getContext().sendBroadcast(intent,
                    android.Manifest.permission.CONFIGURE_WIFI_DISPLAY);
        }
    };

    private final WifiDisplayController.Listener mWifiDisplayListener =
            new WifiDisplayController.Listener() {
        @Override
        public void onEnablementChanged(boolean enabled) {
            synchronized (getSyncRoot()) {
                if (mEnabled != enabled) {
                    mCurrentStatus = null;
                    mEnabled = enabled;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }

        @Override
        public void onScanStarted() {
            synchronized (getSyncRoot()) {
                if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) {
                    mCurrentStatus = null;
                    mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }

        public void onScanFinished(WifiDisplay[] knownDisplays) {
            synchronized (getSyncRoot()) {
                if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
                        || !Arrays.equals(mKnownDisplays, knownDisplays)) {
                    mCurrentStatus = null;
                    mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
                    mKnownDisplays = knownDisplays;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }

        @Override
        public void onDisplayConnecting(WifiDisplay display) {
            synchronized (getSyncRoot()) {
                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING
                        || mActiveDisplay == null
                        || !mActiveDisplay.equals(display)) {
                    mCurrentStatus = null;
                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
                    mActiveDisplay = display;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }

        @Override
        public void onDisplayConnectionFailed() {
            synchronized (getSyncRoot()) {
                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
                        || mActiveDisplay != null) {
                    mCurrentStatus = null;
                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
                    mActiveDisplay = null;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }

        @Override
        public void onDisplayConnected(WifiDisplay display, String iface) {
            synchronized (getSyncRoot()) {
                handleConnectLocked(display, iface);

                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
                        || mActiveDisplay == null
                        || !mActiveDisplay.equals(display)) {
                    mCurrentStatus = null;
                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
                    mActiveDisplay = display;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }

        @Override
        public void onDisplayDisconnected() {
            // Stop listening.
            synchronized (getSyncRoot()) {
                handleDisconnectLocked();

                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
                        || mActiveDisplay != null) {
                    mCurrentStatus = null;
                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
                    mActiveDisplay = null;
                    scheduleStatusChangedBroadcastLocked();
                }
            }
        }
    };

    private final class WifiDisplayDevice extends DisplayDevice {
        private final String mName;
        private final int mWidth;
        private final int mHeight;
        private final float mRefreshRate;
        private final int mFlags;

        private Surface mSurface;
        private DisplayDeviceInfo mInfo;

        public WifiDisplayDevice(IBinder displayToken, String name,
                int width, int height, float refreshRate, int flags,
                Surface surface) {
            super(WifiDisplayAdapter.this, displayToken);
            mName = name;
            mWidth = width;
            mHeight = height;
            mRefreshRate = refreshRate;
            mFlags = flags;
            mSurface = surface;
        }

        public void clearSurfaceLocked() {
            mSurface = null;
            sendTraversalRequestLocked();
        }

        @Override
        public void performTraversalInTransactionLocked() {
            setSurfaceInTransactionLocked(mSurface);
        }

        @Override
        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
            if (mInfo == null) {
                mInfo = new DisplayDeviceInfo();
                mInfo.name = mName;
                mInfo.width = mWidth;
                mInfo.height = mHeight;
                mInfo.refreshRate = mRefreshRate;
                mInfo.flags = mFlags;
                mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
                mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight);
            }
            return mInfo;
        }
    }

    private final class WifiDisplayHandle implements RemoteDisplay.Listener {
        private final String mName;
        private final String mIface;
        private final RemoteDisplay mRemoteDisplay;

        private WifiDisplayDevice mDevice;
        private int mLastError;

        public WifiDisplayHandle(String name, String iface) {
            mName = name;
            mIface = iface;
            mRemoteDisplay = RemoteDisplay.listen(iface, this, getHandler());

            Slog.i(TAG, "Listening for Wifi display connections on " + iface
                    + " from " + mName);
        }

        public void disposeLocked() {
            Slog.i(TAG, "Stopped listening for Wifi display connections on " + mIface
                    + " from " + mName);

            removeDisplayLocked();
            mRemoteDisplay.dispose();
        }

        public void dumpLocked(PrintWriter pw) {
            pw.println("  " + mName + ": " + (mDevice != null ? "connected" : "disconnected"));
            pw.println("    mIface=" + mIface);
            pw.println("    mLastError=" + mLastError);
        }

        // Called on the handler thread.
        @Override
        public void onDisplayConnected(Surface surface, int width, int height, int flags) {
            synchronized (getSyncRoot()) {
                mLastError = 0;
                removeDisplayLocked();
                addDisplayLocked(surface, width, height, flags);

                Slog.i(TAG, "Wifi display connected: " + mName);
            }
        }

        // Called on the handler thread.
        @Override
        public void onDisplayDisconnected() {
            synchronized (getSyncRoot()) {
                mLastError = 0;
                removeDisplayLocked();

                Slog.i(TAG, "Wifi display disconnected: " + mName);
            }
        }

        // Called on the handler thread.
        @Override
        public void onDisplayError(int error) {
            synchronized (getSyncRoot()) {
                mLastError = error;
                removeDisplayLocked();

                Slog.i(TAG, "Wifi display disconnected due to error " + error + ": " + mName);
            }
        }

        private void addDisplayLocked(Surface surface, int width, int height, int flags) {
            int deviceFlags = 0;
            if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
                deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
            }

            float refreshRate = 60.0f; // TODO: get this for real

            IBinder displayToken = Surface.createDisplay(mName);
            mDevice = new WifiDisplayDevice(displayToken, mName, width, height,
                    refreshRate, deviceFlags, surface);
            sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
        }

        private void removeDisplayLocked() {
            if (mDevice != null) {
                mDevice.clearSurfaceLocked();
                sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);
                mDevice = null;
            }
        }
    }
}
