/*
 * Copyright (C) 2018 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.biometrics;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.WindowManager;

import com.android.internal.os.SomeArgs;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;

/**
 * Receives messages sent from AuthenticationClient and shows the appropriate biometric UI (e.g.
 * BiometricDialogView).
 */
public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callbacks {
    private static final String TAG = "BiometricDialogImpl";
    private static final boolean DEBUG = true;

    private static final int MSG_SHOW_DIALOG = 1;
    private static final int MSG_BIOMETRIC_AUTHENTICATED = 2;
    private static final int MSG_BIOMETRIC_HELP = 3;
    private static final int MSG_BIOMETRIC_ERROR = 4;
    private static final int MSG_HIDE_DIALOG = 5;
    private static final int MSG_BUTTON_NEGATIVE = 6;
    private static final int MSG_USER_CANCELED = 7;
    private static final int MSG_BUTTON_POSITIVE = 8;
    private static final int MSG_TRY_AGAIN_PRESSED = 9;

    private SomeArgs mCurrentDialogArgs;
    private BiometricDialogView mCurrentDialog;
    private WindowManager mWindowManager;
    private IBiometricServiceReceiverInternal mReceiver;
    private boolean mDialogShowing;
    private Callback mCallback = new Callback();

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case MSG_SHOW_DIALOG:
                    handleShowDialog((SomeArgs) msg.obj, false /* skipAnimation */,
                            null /* savedState */);
                    break;
                case MSG_BIOMETRIC_AUTHENTICATED:
                    handleBiometricAuthenticated((boolean) msg.obj);
                    break;
                case MSG_BIOMETRIC_HELP:
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleBiometricHelp((String) args.arg1 /* message */,
                            (boolean) args.arg2 /* requireTryAgain */);
                    args.recycle();
                    break;
                case MSG_BIOMETRIC_ERROR:
                    handleBiometricError((String) msg.obj);
                    break;
                case MSG_HIDE_DIALOG:
                    handleHideDialog((Boolean) msg.obj);
                    break;
                case MSG_BUTTON_NEGATIVE:
                    handleButtonNegative();
                    break;
                case MSG_USER_CANCELED:
                    handleUserCanceled();
                    break;
                case MSG_BUTTON_POSITIVE:
                    handleButtonPositive();
                    break;
                case MSG_TRY_AGAIN_PRESSED:
                    handleTryAgainPressed();
                    break;
                default:
                    Log.w(TAG, "Unknown message: " + msg.what);
                    break;
            }
        }
    };

    private class Callback implements DialogViewCallback {
        @Override
        public void onUserCanceled() {
            mHandler.obtainMessage(MSG_USER_CANCELED).sendToTarget();
        }

        @Override
        public void onErrorShown() {
            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_HIDE_DIALOG,
                    false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY);
        }

        @Override
        public void onNegativePressed() {
            mHandler.obtainMessage(MSG_BUTTON_NEGATIVE).sendToTarget();
        }

        @Override
        public void onPositivePressed() {
            mHandler.obtainMessage(MSG_BUTTON_POSITIVE).sendToTarget();
        }

        @Override
        public void onTryAgainPressed() {
            mHandler.obtainMessage(MSG_TRY_AGAIN_PRESSED).sendToTarget();
        }
    }

    @Override
    public void start() {
        final PackageManager pm = mContext.getPackageManager();
        if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
                || pm.hasSystemFeature(PackageManager.FEATURE_FACE)
                || pm.hasSystemFeature(PackageManager.FEATURE_IRIS)) {
            getComponent(CommandQueue.class).addCallback(this);
            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        }
    }

    @Override
    public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
            int type, boolean requireConfirmation, int userId) {
        if (DEBUG) {
            Log.d(TAG, "showBiometricDialog, type: " + type
                    + ", requireConfirmation: " + requireConfirmation);
        }
        // Remove these messages as they are part of the previous client
        mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
        mHandler.removeMessages(MSG_BIOMETRIC_HELP);
        mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
        mHandler.removeMessages(MSG_HIDE_DIALOG);
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = bundle;
        args.arg2 = receiver;
        args.argi1 = type;
        args.arg3 = requireConfirmation;
        args.argi2 = userId;
        mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
    }

    @Override
    public void onBiometricAuthenticated(boolean authenticated) {
        if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: " + authenticated);
        mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED, authenticated).sendToTarget();
    }

    @Override
    public void onBiometricHelp(String message) {
        if (DEBUG) Log.d(TAG, "onBiometricHelp: " + message);
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = message;
        args.arg2 = false; // requireTryAgain
        mHandler.obtainMessage(MSG_BIOMETRIC_HELP, args).sendToTarget();
    }

    @Override
    public void onBiometricError(String error) {
        if (DEBUG) Log.d(TAG, "onBiometricError: " + error);
        mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
    }

    @Override
    public void hideBiometricDialog() {
        if (DEBUG) Log.d(TAG, "hideBiometricDialog");
        mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
    }

    private void handleShowDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
        mCurrentDialogArgs = args;
        final int type = args.argi1;

        if (type == BiometricAuthenticator.TYPE_FINGERPRINT) {
            mCurrentDialog = new FingerprintDialogView(mContext, mCallback);
        } else if (type == BiometricAuthenticator.TYPE_FACE) {
            mCurrentDialog = new FaceDialogView(mContext, mCallback);
        } else {
            Log.e(TAG, "Unsupported type: " + type);
        }

        if (savedState != null) {
            mCurrentDialog.restoreState(savedState);
        }

        if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
                + mCurrentDialog.isAnimatingAway() + " type: " + type);

        if (mCurrentDialog.isAnimatingAway()) {
            mCurrentDialog.forceRemove();
        } else if (mDialogShowing) {
            Log.w(TAG, "Dialog already showing");
            return;
        }
        mReceiver = (IBiometricServiceReceiverInternal) args.arg2;
        mCurrentDialog.setBundle((Bundle)args.arg1);
        mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
        mCurrentDialog.setUserId(args.argi2);
        mCurrentDialog.setSkipIntro(skipAnimation);
        mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
        mDialogShowing = true;
    }

    private void handleBiometricAuthenticated(boolean authenticated) {
        if (DEBUG) Log.d(TAG, "handleBiometricAuthenticated: " + authenticated);

        if (authenticated) {
            mCurrentDialog.announceForAccessibility(
                    mContext.getResources()
                            .getText(mCurrentDialog.getAuthenticatedAccessibilityResourceId()));
            if (mCurrentDialog.requiresConfirmation()) {
                mCurrentDialog.showConfirmationButton(true /* show */);
            } else {
                mCurrentDialog.updateState(BiometricDialogView.STATE_AUTHENTICATED);
                mHandler.postDelayed(() -> {
                    handleHideDialog(false /* userCanceled */);
                }, mCurrentDialog.getDelayAfterAuthenticatedDurationMs());
            }
        } else {
            handleBiometricHelp(mContext.getResources()
                    .getString(com.android.internal.R.string.biometric_not_recognized),
                    true /* requireTryAgain */);
            mCurrentDialog.showTryAgainButton(true /* show */);
        }
    }

    private void handleBiometricHelp(String message, boolean requireTryAgain) {
        if (DEBUG) Log.d(TAG, "handleBiometricHelp: " + message);
        mCurrentDialog.showHelpMessage(message, requireTryAgain);
    }

    private void handleBiometricError(String error) {
        if (DEBUG) Log.d(TAG, "handleBiometricError: " + error);
        if (!mDialogShowing) {
            if (DEBUG) Log.d(TAG, "Dialog already dismissed");
            return;
        }
        mCurrentDialog.showErrorMessage(error);
    }

    private void handleHideDialog(boolean userCanceled) {
        if (DEBUG) Log.d(TAG, "handleHideDialog, userCanceled: " + userCanceled);
        if (!mDialogShowing) {
            // This can happen if there's a race and we get called from both
            // onAuthenticated and onError, etc.
            Log.w(TAG, "Dialog already dismissed, userCanceled: " + userCanceled);
            return;
        }
        if (userCanceled) {
            try {
                mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException when hiding dialog", e);
            }
        }
        mReceiver = null;
        mDialogShowing = false;
        mCurrentDialog.startDismiss();
    }

    private void handleButtonNegative() {
        if (mReceiver == null) {
            Log.e(TAG, "Receiver is null");
            return;
        }
        try {
            mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
        } catch (RemoteException e) {
            Log.e(TAG, "Remote exception when handling negative button", e);
        }
        handleHideDialog(false /* userCanceled */);
    }

    private void handleButtonPositive() {
        if (mReceiver == null) {
            Log.e(TAG, "Receiver is null");
            return;
        }
        try {
            mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_POSITIVE);
        } catch (RemoteException e) {
            Log.e(TAG, "Remote exception when handling positive button", e);
        }
        handleHideDialog(false /* userCanceled */);
    }

    private void handleUserCanceled() {
        handleHideDialog(true /* userCanceled */);
    }

    private void handleTryAgainPressed() {
        try {
            mCurrentDialog.clearTemporaryMessage();
            mReceiver.onTryAgainPressed();
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException when handling try again", e);
        }
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        final boolean wasShowing = mDialogShowing;

        // Save the state of the current dialog (buttons showing, etc)
        final Bundle savedState = new Bundle();
        if (mCurrentDialog != null) {
            mCurrentDialog.onSaveState(savedState);
        }

        if (mDialogShowing) {
            mCurrentDialog.forceRemove();
            mDialogShowing = false;
        }

        if (wasShowing) {
            handleShowDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
        }
    }
}
