/*
 * 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.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Outline;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;

import com.android.systemui.R;

/**
 * This class loads the view for the system-provided dialog. The view consists of:
 * Application Icon, Title, Subtitle, Description, Biometric Icon, Error/Help message area,
 * and positive/negative buttons.
 */
public class FaceDialogView extends BiometricDialogView {

    private static final String TAG = "FaceDialogView";
    private static final String KEY_DIALOG_SIZE = "key_dialog_size";
    private static final String KEY_DIALOG_ANIMATED_IN = "key_dialog_animated_in";

    private static final int HIDE_DIALOG_DELAY = 500; // ms
    private static final int IMPLICIT_Y_PADDING = 16; // dp
    private static final int GROW_DURATION = 150; // ms
    private static final int TEXT_ANIMATE_DISTANCE = 32; // dp

    private static final int SIZE_UNKNOWN = 0;
    private static final int SIZE_SMALL = 1;
    private static final int SIZE_GROWING = 2;
    private static final int SIZE_BIG = 3;

    private int mSize;
    private float mIconOriginalY;
    private DialogOutlineProvider mOutlineProvider = new DialogOutlineProvider();
    private IconController mIconController;
    private boolean mDialogAnimatedIn;

    /**
     * Class that handles the biometric icon animations.
     */
    private final class IconController extends Animatable2.AnimationCallback {

        private boolean mLastPulseDirection; // false = dark to light, true = light to dark

        int mState;

        IconController() {
            mState = STATE_IDLE;
        }

        public void animateOnce(int iconRes) {
            animateIcon(iconRes, false);
        }

        public void showStatic(int iconRes) {
            mBiometricIcon.setImageDrawable(mContext.getDrawable(iconRes));
        }

        public void startPulsing() {
            mLastPulseDirection = false;
            animateIcon(R.drawable.face_dialog_pulse_dark_to_light, true);
        }

        public void showIcon(int iconRes) {
            final Drawable drawable = mContext.getDrawable(iconRes);
            mBiometricIcon.setImageDrawable(drawable);
        }

        private void animateIcon(int iconRes, boolean repeat) {
            final AnimatedVectorDrawable icon =
                    (AnimatedVectorDrawable) mContext.getDrawable(iconRes);
            mBiometricIcon.setImageDrawable(icon);
            icon.forceAnimationOnUI();
            if (repeat) {
                icon.registerAnimationCallback(this);
            }
            icon.start();
        }

        private void pulseInNextDirection() {
            int iconRes = mLastPulseDirection ? R.drawable.face_dialog_pulse_dark_to_light
                    : R.drawable.face_dialog_pulse_light_to_dark;
            animateIcon(iconRes, true /* repeat */);
            mLastPulseDirection = !mLastPulseDirection;
        }

        @Override
        public void onAnimationEnd(Drawable drawable) {
            super.onAnimationEnd(drawable);

            if (mState == STATE_AUTHENTICATING) {
                // Still authenticating, pulse the icon
                pulseInNextDirection();
            }
        }
    }

    private final class DialogOutlineProvider extends ViewOutlineProvider {

        float mY;

        @Override
        public void getOutline(View view, Outline outline) {
            outline.setRoundRect(
                    0 /* left */,
                    (int) mY, /* top */
                    mDialog.getWidth() /* right */,
                    mDialog.getBottom(), /* bottom */
                    getResources().getDimension(R.dimen.biometric_dialog_corner_size));
        }

        int calculateSmall() {
            final float padding = dpToPixels(IMPLICIT_Y_PADDING);
            return mDialog.getHeight() - mBiometricIcon.getHeight() - 2 * (int) padding;
        }

        void setOutlineY(float y) {
            mY = y;
        }
    }

    private final Runnable mErrorToIdleAnimationRunnable = () -> {
        updateState(STATE_IDLE);
        mErrorText.setVisibility(View.INVISIBLE);
        announceAccessibilityEvent();
    };

    public FaceDialogView(Context context,
            DialogViewCallback callback) {
        super(context, callback);
        mIconController = new IconController();
    }

    private void updateSize(int newSize) {
        final float padding = dpToPixels(IMPLICIT_Y_PADDING);
        final float iconSmallPositionY = mDialog.getHeight() - mBiometricIcon.getHeight() - padding;

        if (newSize == SIZE_SMALL) {
            // These fields are required and/or always hold a spot on the UI, so should be set to
            // INVISIBLE so they keep their position
            mTitleText.setVisibility(View.INVISIBLE);
            mErrorText.setVisibility(View.INVISIBLE);
            mNegativeButton.setVisibility(View.INVISIBLE);

            // These fields are optional, so set them to gone or invisible depending on their
            // usage. If they're empty, they're already set to GONE in BiometricDialogView.
            if (!TextUtils.isEmpty(mSubtitleText.getText())) {
                mSubtitleText.setVisibility(View.INVISIBLE);
            }
            if (!TextUtils.isEmpty(mDescriptionText.getText())) {
                mDescriptionText.setVisibility(View.INVISIBLE);
            }

            // Move the biometric icon to the small spot
            mBiometricIcon.setY(iconSmallPositionY);

            // Clip the dialog to the small size
            mDialog.setOutlineProvider(mOutlineProvider);
            mOutlineProvider.setOutlineY(mOutlineProvider.calculateSmall());

            mDialog.setClipToOutline(true);
            mDialog.invalidateOutline();

            mSize = newSize;
            announceAccessibilityEvent();
        } else if (mSize == SIZE_SMALL && newSize == SIZE_BIG) {
            mSize = SIZE_GROWING;

            // Animate the outline
            final ValueAnimator outlineAnimator =
                    ValueAnimator.ofFloat(mOutlineProvider.calculateSmall(), 0);
            outlineAnimator.addUpdateListener((animation) -> {
                final float y = (float) animation.getAnimatedValue();
                mOutlineProvider.setOutlineY(y);
                mDialog.invalidateOutline();
            });

            // Animate the icon back to original big position
            final ValueAnimator iconAnimator =
                    ValueAnimator.ofFloat(iconSmallPositionY, mIconOriginalY);
            iconAnimator.addUpdateListener((animation) -> {
                final float y = (float) animation.getAnimatedValue();
                mBiometricIcon.setY(y);
            });

            // Animate the error text so it slides up with the icon
            final ValueAnimator textSlideAnimator =
                    ValueAnimator.ofFloat(dpToPixels(TEXT_ANIMATE_DISTANCE), 0);
            textSlideAnimator.addUpdateListener((animation) -> {
                final float y = (float) animation.getAnimatedValue();
                mErrorText.setTranslationY(y);
            });

            // Opacity animator for things that should fade in (title, subtitle, details, negative
            // button)
            final ValueAnimator opacityAnimator = ValueAnimator.ofFloat(0, 1);
            opacityAnimator.addUpdateListener((animation) -> {
                final float opacity = (float) animation.getAnimatedValue();

                // These fields are required and/or always hold a spot on the UI
                mTitleText.setAlpha(opacity);
                mErrorText.setAlpha(opacity);
                mNegativeButton.setAlpha(opacity);
                mTryAgainButton.setAlpha(opacity);

                // These fields are optional, so only animate them if they're supposed to be showing
                if (!TextUtils.isEmpty(mSubtitleText.getText())) {
                    mSubtitleText.setAlpha(opacity);
                }
                if (!TextUtils.isEmpty(mDescriptionText.getText())) {
                    mDescriptionText.setAlpha(opacity);
                }
            });

            // Choreograph together
            final AnimatorSet as = new AnimatorSet();
            as.setDuration(GROW_DURATION);
            as.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    // Set the visibility of opacity-animating views back to VISIBLE
                    mTitleText.setVisibility(View.VISIBLE);
                    mErrorText.setVisibility(View.VISIBLE);
                    mNegativeButton.setVisibility(View.VISIBLE);
                    mTryAgainButton.setVisibility(View.VISIBLE);

                    if (!TextUtils.isEmpty(mSubtitleText.getText())) {
                        mSubtitleText.setVisibility(View.VISIBLE);
                    }
                    if (!TextUtils.isEmpty(mDescriptionText.getText())) {
                        mDescriptionText.setVisibility(View.VISIBLE);
                    }
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    mSize = SIZE_BIG;
                }
            });
            as.play(outlineAnimator).with(iconAnimator).with(opacityAnimator)
                    .with(textSlideAnimator);
            as.start();
        } else if (mSize == SIZE_BIG) {
            mDialog.setClipToOutline(false);
            mDialog.invalidateOutline();

            mBiometricIcon.setY(mIconOriginalY);

            mSize = newSize;
        }
    }

    @Override
    public void onSaveState(Bundle bundle) {
        super.onSaveState(bundle);
        bundle.putInt(KEY_DIALOG_SIZE, mSize);
        bundle.putBoolean(KEY_DIALOG_ANIMATED_IN, mDialogAnimatedIn);
    }


    @Override
    protected void handleResetMessage() {
        mErrorText.setTextColor(mTextColor);
        mErrorText.setVisibility(View.INVISIBLE);
        announceAccessibilityEvent();
    }

    @Override
    public void restoreState(Bundle bundle) {
        super.restoreState(bundle);
        // Keep in mind that this happens before onAttachedToWindow()
        mSize = bundle.getInt(KEY_DIALOG_SIZE);
        mDialogAnimatedIn = bundle.getBoolean(KEY_DIALOG_ANIMATED_IN);
    }

    /**
     * Do small/big layout here instead of onAttachedToWindow, since:
     * 1) We need the big layout to be measured, etc for small -> big animation
     * 2) We need the dialog measurements to know where to move the biometric icon to
     *
     * BiometricDialogView already sets the views to their default big state, so here we only
     * need to hide the ones that are unnecessary.
     */
    @Override
    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        if (mIconOriginalY == 0) {
            mIconOriginalY = mBiometricIcon.getY();
        }

        // UNKNOWN means size hasn't been set yet. First time we create the dialog.
        // onLayout can happen when visibility of views change (during animation, etc).
        if (mSize != SIZE_UNKNOWN) {
            // Probably not the cleanest way to do this, but since dialog is big by default,
            // and small dialogs can persist across orientation changes, we need to set it to
            // small size here again.
            if (mSize == SIZE_SMALL) {
                updateSize(SIZE_SMALL);
            }
            return;
        }

        // If we don't require confirmation, show the small dialog first (until errors occur).
        if (!requiresConfirmation()) {
            updateSize(SIZE_SMALL);
        } else {
            updateSize(SIZE_BIG);
        }
    }

    @Override
    public void onErrorReceived(String error) {
        super.onErrorReceived(error);
        // All error messages will cause the dialog to go from small -> big. Error messages
        // are messages such as lockout, auth failed, etc.
        if (mSize == SIZE_SMALL) {
            updateSize(SIZE_BIG);
        }
    }

    @Override
    public void onAuthenticationFailed(String message) {
        super.onAuthenticationFailed(message);
        showTryAgainButton(true);
    }

    @Override
    public void showTryAgainButton(boolean show) {
        if (show && mSize == SIZE_SMALL) {
            // Do not call super, we will nicely animate the alpha together with the rest
            // of the elements in here.
            updateSize(SIZE_BIG);
        } else {
            if (show) {
                mTryAgainButton.setVisibility(View.VISIBLE);
            } else {
                mTryAgainButton.setVisibility(View.GONE);
                announceAccessibilityEvent();
            }
        }

        if (show) {
            mPositiveButton.setVisibility(View.GONE);
            announceAccessibilityEvent();
        }
    }

    @Override
    protected int getHintStringResourceId() {
        return 0;
    }

    @Override
    protected int getAuthenticatedAccessibilityResourceId() {
        if (mRequireConfirmation) {
            return com.android.internal.R.string.face_authenticated_confirmation_required;
        } else {
            return com.android.internal.R.string.face_authenticated_no_confirmation_required;
        }
    }

    @Override
    protected int getIconDescriptionResourceId() {
        return R.string.accessibility_face_dialog_face_icon;
    }

    @Override
    protected void updateIcon(int oldState, int newState) {
        mIconController.mState = newState;

        if (newState == STATE_AUTHENTICATING) {
            mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
            if (mDialogAnimatedIn) {
                mIconController.startPulsing();
            } else {
                mIconController.showIcon(R.drawable.face_dialog_pulse_dark_to_light);
            }
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_authenticating));
        } else if (oldState == STATE_PENDING_CONFIRMATION && newState == STATE_AUTHENTICATED) {
            mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_confirmed));
        } else if (oldState == STATE_ERROR && newState == STATE_IDLE) {
            mIconController.animateOnce(R.drawable.face_dialog_error_to_idle);
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_idle));
        } else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
            mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
            mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_authenticated));
        } else if (newState == STATE_ERROR) {
            // It's easier to only check newState and gate showing the animation on the
            // mErrorToIdleAnimationRunnable as a proxy, than add a ton of extra state. For example,
            // we may go from error -> error due to configuration change which is valid and we
            // should show the animation, or we can go from error -> error by receiving repeated
            // acquire messages in which case we do not want to repeatedly start the animation.
            if (!mHandler.hasCallbacks(mErrorToIdleAnimationRunnable)) {
                mIconController.animateOnce(R.drawable.face_dialog_dark_to_error);
                mHandler.postDelayed(mErrorToIdleAnimationRunnable,
                        BiometricPrompt.HIDE_DIALOG_DELAY);
            }
        } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
            mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_authenticated));
        } else if (newState == STATE_PENDING_CONFIRMATION) {
            mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
            mIconController.animateOnce(R.drawable.face_dialog_wink_from_dark);
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_authenticated));
        } else if (newState == STATE_IDLE) {
            mIconController.showStatic(R.drawable.face_dialog_idle_static);
            mBiometricIcon.setContentDescription(mContext.getString(
                    R.string.biometric_dialog_face_icon_description_idle));
        } else {
            Log.w(TAG, "Unknown animation from " + oldState + " -> " + newState);
        }

        // Note that this must be after the newState == STATE_ERROR check above since this affects
        // the logic.
        if (oldState == STATE_ERROR && newState == STATE_ERROR) {
            // Keep the error icon and text around for a while longer if we keep receiving
            // STATE_ERROR
            mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
            mHandler.postDelayed(mErrorToIdleAnimationRunnable, BiometricPrompt.HIDE_DIALOG_DELAY);
        }
    }

    @Override
    public void onDialogAnimatedIn() {
        mDialogAnimatedIn = true;
        mIconController.startPulsing();
    }

    @Override
    protected int getDelayAfterAuthenticatedDurationMs() {
        return HIDE_DIALOG_DELAY;
    }

    @Override
    protected boolean shouldGrayAreaDismissDialog() {
        if (mSize == SIZE_SMALL) {
            return false;
        }
        return true;
    }

    private float dpToPixels(float dp) {
        return dp * ((float) mContext.getResources().getDisplayMetrics().densityDpi
                / DisplayMetrics.DENSITY_DEFAULT);
    }

    private float pixelsToDp(float pixels) {
        return pixels / ((float) mContext.getResources().getDisplayMetrics().densityDpi
                / DisplayMetrics.DENSITY_DEFAULT);
    }
}
