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

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.IBinder.DeathRecipient;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamService;
import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;

import java.io.PrintWriter;
import java.util.NoSuchElementException;

/**
 * Internal controller for starting and stopping the current dream and managing related state.
 *
 * Assumes all operations are called from the dream handler thread.
 */
final class DreamController {
    private static final String TAG = "DreamController";

    private final Context mContext;
    private final Handler mHandler;
    private final Listener mListener;
    private final IWindowManager mIWindowManager;

    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

    private final Intent mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

    private DreamRecord mCurrentDream;

    public DreamController(Context context, Handler handler, Listener listener) {
        mContext = context;
        mHandler = handler;
        mListener = listener;
        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
    }

    public void dump(PrintWriter pw) {
        pw.println("Dreamland:");
        if (mCurrentDream != null) {
            pw.println("  mCurrentDream:");
            pw.println("    mToken=" + mCurrentDream.mToken);
            pw.println("    mName=" + mCurrentDream.mName);
            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
            pw.println("    mUserId=" + mCurrentDream.mUserId);
            pw.println("    mBound=" + mCurrentDream.mBound);
            pw.println("    mService=" + mCurrentDream.mService);
            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
        } else {
            pw.println("  mCurrentDream: null");
        }
    }

    public void startDream(Binder token, ComponentName name, boolean isTest, int userId) {
        stopDream();

        // Close the notification shade
        mContext.sendBroadcast(mCloseNotificationShadeIntent);

        Slog.i(TAG, "Starting dream: name=" + name + ", isTest=" + isTest + ", userId=" + userId);

        mCurrentDream = new DreamRecord(token, name, isTest, userId);

        try {
            mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
        } catch (RemoteException ex) {
            Slog.e(TAG, "Unable to add window token for dream.", ex);
            stopDream();
            return;
        }

        Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
        intent.setComponent(name);
        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        try {
            if (!mContext.bindService(intent, mCurrentDream,
                    Context.BIND_AUTO_CREATE, userId)) {
                Slog.e(TAG, "Unable to bind dream service: " + intent);
                stopDream();
                return;
            }
        } catch (SecurityException ex) {
            Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
            stopDream();
            return;
        }

        mCurrentDream.mBound = true;
    }

    public void stopDream() {
        if (mCurrentDream == null) {
            return;
        }

        final DreamRecord oldDream = mCurrentDream;
        mCurrentDream = null;
        Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
                + ", isTest=" + oldDream.mIsTest + ", userId=" + oldDream.mUserId);

        if (oldDream.mSentStartBroadcast) {
            mContext.sendBroadcast(mDreamingStoppedIntent);
        }

        if (oldDream.mService != null) {
            // TODO: It would be nice to tell the dream that it's being stopped so that
            // it can shut down nicely before we yank its window token out from under it.
            try {
                oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
            } catch (NoSuchElementException ex) {
                // don't care
            }
            oldDream.mService = null;
        }

        if (oldDream.mBound) {
            mContext.unbindService(oldDream);
        }

        try {
            mIWindowManager.removeWindowToken(oldDream.mToken);
        } catch (RemoteException ex) {
            Slog.w(TAG, "Error removing window token for dream.", ex);
        }

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mListener.onDreamStopped(oldDream.mToken);
            }
        });
    }

    private void attach(IDreamService service) {
        try {
            service.asBinder().linkToDeath(mCurrentDream, 0);
            service.attach(mCurrentDream.mToken);
        } catch (RemoteException ex) {
            Slog.e(TAG, "The dream service died unexpectedly.", ex);
            stopDream();
            return;
        }

        mCurrentDream.mService = service;

        if (!mCurrentDream.mIsTest) {
            mContext.sendBroadcast(mDreamingStartedIntent);
            mCurrentDream.mSentStartBroadcast = true;
        }
    }

    /**
     * Callback interface to be implemented by the {@link DreamManagerService}.
     */
    public interface Listener {
        void onDreamStopped(Binder token);
    }

    private final class DreamRecord implements DeathRecipient, ServiceConnection {
        public final Binder mToken;
        public final ComponentName mName;
        public final boolean mIsTest;
        public final int mUserId;

        public boolean mBound;
        public IDreamService mService;
        public boolean mSentStartBroadcast;

        public DreamRecord(Binder token, ComponentName name,
                boolean isTest, int userId) {
            mToken = token;
            mName = name;
            mIsTest = isTest;
            mUserId  = userId;
        }

        // May be called on any thread.
        @Override
        public void binderDied() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mService = null;
                    if (mCurrentDream == DreamRecord.this) {
                        stopDream();
                    }
                }
            });
        }

        // May be called on any thread.
        @Override
        public void onServiceConnected(ComponentName name, final IBinder service) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mCurrentDream == DreamRecord.this && mService == null) {
                        attach(IDreamService.Stub.asInterface(service));
                    }
                }
            });
        }

        // May be called on any thread.
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mService = null;
                    if (mCurrentDream == DreamRecord.this) {
                        stopDream();
                    }
                }
            });
        }
    }
}