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

import com.android.internal.widget.LockPatternUtils;

import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.IActivityManager.WaitResult;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;

import com.android.keyguard.KeyguardHostView.OnDismissAction;

import java.util.List;

public abstract class KeyguardActivityLauncher {
    private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
    private static final boolean DEBUG = KeyguardConstants.DEBUG;
    private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
    private static final Intent SECURE_CAMERA_INTENT =
            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
                    .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    private static final Intent INSECURE_CAMERA_INTENT =
            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);

    abstract Context getContext();

    abstract LockPatternUtils getLockPatternUtils();

    abstract void setOnDismissAction(OnDismissAction action);

    abstract void requestDismissKeyguard();

    public static class CameraWidgetInfo {
        public String contextPackage;
        public int layoutId;
    }

    public CameraWidgetInfo getCameraWidgetInfo() {
        CameraWidgetInfo info = new CameraWidgetInfo();
        Intent intent = getCameraIntent();
        PackageManager packageManager = getContext().getPackageManager();
        final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
                intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
        if (appList.size() == 0) {
            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Nothing found");
            return null;
        }
        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
                getLockPatternUtils().getCurrentUser());
        if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): resolved: " + resolved);
        if (wouldLaunchResolverActivity(resolved, appList)) {
            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Would launch resolver");
            return info;
        }
        if (resolved == null || resolved.activityInfo == null) {
            return null;
        }
        if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no metadata found");
            return info;
        }
        int layoutId = resolved.activityInfo.metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
        if (layoutId == 0) {
            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no layout specified");
            return info;
        }
        info.contextPackage = resolved.activityInfo.packageName;
        info.layoutId = layoutId;
        return info;
    }

    public void launchCamera(Handler worker, Runnable onSecureCameraStarted) {
        LockPatternUtils lockPatternUtils = getLockPatternUtils();

        // Workaround to avoid camera release/acquisition race when resuming face unlock
        // after showing lockscreen camera (bug 11063890).
        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
        updateMonitor.setAlternateUnlockEnabled(false);

        if (mustLaunchSecurely()) {
            // Launch the secure version of the camera
            if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) {
                // TODO: Show disambiguation dialog instead.
                // For now, we'll treat this like launching any other app from secure keyguard.
                // When they do, user sees the system's ResolverActivity which lets them choose
                // which secure camera to use.
                launchActivity(SECURE_CAMERA_INTENT, false, false, null, null);
            } else {
                launchActivity(SECURE_CAMERA_INTENT, true, false, worker, onSecureCameraStarted);
            }
        } else {
            // Launch the normal camera
            launchActivity(INSECURE_CAMERA_INTENT, false, false, null, null);
        }
    }

    private boolean mustLaunchSecurely() {
        LockPatternUtils lockPatternUtils = getLockPatternUtils();
        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
        int currentUser = lockPatternUtils.getCurrentUser();
        return lockPatternUtils.isSecure() && !updateMonitor.getUserHasTrust(currentUser);
    }

    public void launchWidgetPicker(int appWidgetId) {
        Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);

        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
        pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);

        Bundle options = new Bundle();
        options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
        pickIntent.addFlags(
                Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_SINGLE_TOP
                | Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

        launchActivity(pickIntent, false, false, null, null);
    }

    /**
     * Launches the said intent for the current foreground user.
     *
     * @param intent
     * @param showsWhileLocked true if the activity can be run on top of keyguard.
     *   See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
     * @param useDefaultAnimations true if default transitions should be used, else suppressed.
     * @param worker if supplied along with onStarted, used to launch the blocking activity call.
     * @param onStarted if supplied along with worker, called after activity is started.
     */
    public void launchActivity(final Intent intent,
            boolean showsWhileLocked,
            boolean useDefaultAnimations,
            final Handler worker,
            final Runnable onStarted) {

        final Context context = getContext();
        final Bundle animation = useDefaultAnimations ? null
                : ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
        launchActivityWithAnimation(intent, showsWhileLocked, animation, worker, onStarted);
    }

    public void launchActivityWithAnimation(final Intent intent,
            boolean showsWhileLocked,
            final Bundle animation,
            final Handler worker,
            final Runnable onStarted) {

        LockPatternUtils lockPatternUtils = getLockPatternUtils();
        intent.addFlags(
                Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_SINGLE_TOP
                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        boolean mustLaunchSecurely = mustLaunchSecurely();
        if (!mustLaunchSecurely || showsWhileLocked) {
            if (!mustLaunchSecurely) {
                dismissKeyguardOnNextActivity();
            }
            try {
                if (DEBUG) Log.d(TAG, String.format("Starting activity for intent %s at %s",
                        intent, SystemClock.uptimeMillis()));
                startActivityForCurrentUser(intent, animation, worker, onStarted);
            } catch (ActivityNotFoundException e) {
                Log.w(TAG, "Activity not found for intent + " + intent.getAction());
            }
        } else {
            // Create a runnable to start the activity and ask the user to enter their
            // credentials.
            setOnDismissAction(new OnDismissAction() {
                @Override
                public boolean onDismiss() {
                    dismissKeyguardOnNextActivity();
                    startActivityForCurrentUser(intent, animation, worker, onStarted);
                    return true;
                }
            });
            requestDismissKeyguard();
        }
    }

    private void dismissKeyguardOnNextActivity() {
        try {
            WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
        } catch (RemoteException e) {
            Log.w(TAG, "Error dismissing keyguard", e);
        }
    }

    private void startActivityForCurrentUser(final Intent intent, final Bundle options,
            Handler worker, final Runnable onStarted) {
        final UserHandle user = new UserHandle(UserHandle.USER_CURRENT);
        if (worker == null || onStarted == null) {
            getContext().startActivityAsUser(intent, options, user);
            return;
        }
        // if worker + onStarted are supplied, run blocking activity launch call in the background
        worker.post(new Runnable(){
            @Override
            public void run() {
                try {
                    WaitResult result = ActivityManagerNative.getDefault().startActivityAndWait(
                            null /*caller*/,
                            null /*caller pkg*/,
                            intent,
                            intent.resolveTypeIfNeeded(getContext().getContentResolver()),
                            null /*resultTo*/,
                            null /*resultWho*/,
                            0 /*requestCode*/,
                            Intent.FLAG_ACTIVITY_NEW_TASK,
                            null /*profilerInfo*/,
                            options,
                            user.getIdentifier());
                    if (DEBUG) Log.d(TAG, String.format("waitResult[%s,%s,%s,%s] at %s",
                            result.result, result.thisTime, result.totalTime, result.who,
                            SystemClock.uptimeMillis()));
                } catch (RemoteException e) {
                    Log.w(TAG, "Error starting activity", e);
                    return;
                }
                try {
                    onStarted.run();
                } catch (Throwable t) {
                    Log.w(TAG, "Error running onStarted callback", t);
                }
            }});
    }

    private Intent getCameraIntent() {
        return mustLaunchSecurely() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
    }

    private boolean wouldLaunchResolverActivity(Intent intent) {
        PackageManager packageManager = getContext().getPackageManager();
        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
                PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
        List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
                intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
        return wouldLaunchResolverActivity(resolved, appList);
    }

    private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
        // If the list contains the above resolved activity, then it can't be
        // ResolverActivity itself.
        for (int i = 0; i < appList.size(); i++) {
            ResolveInfo tmp = appList.get(i);
            if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
                    && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
                return false;
            }
        }
        return true;
    }
}
