/*
 * Copyright (C) 2017 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.systemui.keyguard;

import static android.app.ActivityManager.TaskDescription;

import android.annotation.ColorInt;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.os.UserHandle;
import android.view.View;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;

/**
 * Bouncer between work activities and the activity used to confirm credentials before unlocking
 * a managed profile.
 * <p>
 * Shows a solid color when started, based on the organization color of the user it is supposed to
 * be blocking. Once focused, it switches to a screen to confirm credentials and auto-dismisses if
 * credentials are accepted.
 */
public class WorkLockActivity extends Activity {
    private static final String TAG = "WorkLockActivity";

    /**
     * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to
     * enable device policy management enforcement from systemui.
     */
    public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";

    /**
     * Contains a {@link TaskDescription} for the activity being covered.
     */
    static final String EXTRA_TASK_DESCRIPTION =
            "com.android.systemui.keyguard.extra.TASK_DESCRIPTION";

    private static final int REQUEST_CODE_CONFIRM_CREDENTIALS = 1;

    /**
     * Cached keyguard manager instance populated by {@link #getKeyguardManager}.
     * @see KeyguardManager
     */
    private KeyguardManager mKgm;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        registerReceiverAsUser(mLockEventReceiver, UserHandle.ALL,
                new IntentFilter(Intent.ACTION_DEVICE_LOCKED_CHANGED), /* permission */ null,
                /* scheduler */ null);

        // Once the receiver is registered, check whether anything happened between now and the time
        // when this activity was launched. If it did and the user is unlocked now, just quit.
        if (!getKeyguardManager().isDeviceLocked(getTargetUserId())) {
            finish();
            return;
        }

        // Draw captions overlaid on the content view, so the whole window is one solid color.
        setOverlayWithDecorCaptionEnabled(true);

        // Blank out the activity. When it is on-screen it will look like a Recents thumbnail with
        // redaction switched on.
        final View blankView = new View(this);
        blankView.setContentDescription(getString(R.string.accessibility_desc_work_lock));
        blankView.setBackgroundColor(getPrimaryColor());
        setContentView(blankView);
    }

    /**
     * Respond to focus events by showing the prompt to confirm credentials.
     * <p>
     * We don't have anything particularly interesting to show here (just a solid-colored page) so
     * there is no sense in sitting in the foreground doing nothing.
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        if (hasFocus) {
            showConfirmCredentialActivity();
        }
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(mLockEventReceiver);
        super.onDestroy();
    }

    @Override
    public void onBackPressed() {
        // Ignore back presses.
    }

    @Override
    public void setTaskDescription(TaskDescription taskDescription) {
        // Leave unset so we use the previous activity's task description.
    }

    private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final int targetUserId = getTargetUserId();
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, targetUserId);
            if (userId == targetUserId && !getKeyguardManager().isDeviceLocked(targetUserId)) {
                finish();
            }
        }
    };

    private void showConfirmCredentialActivity() {
        if (isFinishing() || !getKeyguardManager().isDeviceLocked(getTargetUserId())) {
            // Don't show the confirm credentials screen if we are already unlocked / unlocking.
            return;
        }

        final Intent credential = getKeyguardManager()
                .createConfirmDeviceCredentialIntent(null, null, getTargetUserId());
        if (credential == null) {
            return;
        }

        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchTaskId(getTaskId());

        // Bring this activity back to the foreground after confirming credentials.
        final PendingIntent target = PendingIntent.getActivity(this, /* request */ -1, getIntent(),
                PendingIntent.FLAG_CANCEL_CURRENT |
                PendingIntent.FLAG_ONE_SHOT |
                PendingIntent.FLAG_IMMUTABLE, options.toBundle());

        if (target != null) {
            credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
            credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
        }

        startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE_CONFIRM_CREDENTIALS &&  resultCode != RESULT_OK) {
            // The user dismissed the challenge, don't show it again.
            goToHomeScreen();
        }
    }

    private void goToHomeScreen() {
        final Intent homeIntent = new Intent(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(homeIntent);
    }

    private KeyguardManager getKeyguardManager() {
        if (mKgm == null) {
            mKgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        }
        return mKgm;
    }

    @VisibleForTesting
    @UserIdInt
    final int getTargetUserId() {
        return getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
    }

    @VisibleForTesting
    @ColorInt
    final int getPrimaryColor() {
        final TaskDescription taskDescription = (TaskDescription)
                getIntent().getExtra(EXTRA_TASK_DESCRIPTION);
        if (taskDescription != null && Color.alpha(taskDescription.getPrimaryColor()) == 255) {
            return taskDescription.getPrimaryColor();
        } else {
            // No task description. Use an organization color set by the policy controller.
            final DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
                    getSystemService(Context.DEVICE_POLICY_SERVICE);
            return devicePolicyManager.getOrganizationColorForUser(getTargetUserId());
        }
    }
}
