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

import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.graphics.Paint.FILTER_BITMAP_FLAG;

import android.animation.ArgbEvaluator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.ShapeDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
import android.widget.TextView;

import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;

import com.android.systemui.R;
import com.android.systemui.recents.TriangleShape;

/**
 * Flyout view that appears as a 'chat bubble' alongside the bubble stack. The flyout can visually
 * transform into the 'new' dot, which is used during flyout dismiss animations/gestures.
 */
public class BubbleFlyoutView extends FrameLayout {
    /** Max width of the flyout, in terms of percent of the screen width. */
    private static final float FLYOUT_MAX_WIDTH_PERCENT = .6f;

    private final int mFlyoutPadding;
    private final int mFlyoutSpaceFromBubble;
    private final int mPointerSize;
    private final int mBubbleSize;
    private final int mFlyoutElevation;
    private final int mBubbleElevation;
    private final int mFloatingBackgroundColor;
    private final float mCornerRadius;

    private final ViewGroup mFlyoutTextContainer;
    private final TextView mFlyoutText;
    /** Spring animation for the flyout. */
    private final SpringAnimation mFlyoutSpring =
            new SpringAnimation(this, DynamicAnimation.TRANSLATION_X);

    /** Values related to the 'new' dot which we use to figure out where to collapse the flyout. */
    private final float mNewDotRadius;
    private final float mNewDotSize;
    private final float mNewDotOffsetFromBubbleBounds;

    /**
     * The paint used to draw the background, whose color changes as the flyout transitions to the
     * tinted 'new' dot.
     */
    private final Paint mBgPaint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG);
    private final ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();

    /**
     * Triangular ShapeDrawables used for the triangle that points from the flyout to the bubble
     * stack (a chat-bubble effect).
     */
    private final ShapeDrawable mLeftTriangleShape;
    private final ShapeDrawable mRightTriangleShape;

    /** Whether the flyout arrow is on the left (pointing left) or right (pointing right). */
    private boolean mArrowPointingLeft = true;

    /** Color of the 'new' dot that the flyout will transform into. */
    private int mDotColor;

    /** The outline of the triangle, used for elevation shadows. */
    private final Outline mTriangleOutline = new Outline();

    /** The bounds of the flyout background, kept up to date as it transitions to the 'new' dot. */
    private final RectF mBgRect = new RectF();

    /**
     * Percent progress in the transition from flyout to 'new' dot. These two values are the inverse
     * of each other (if we're 40% transitioned to the dot, we're 60% flyout), but it makes the code
     * much more readable.
     */
    private float mPercentTransitionedToDot = 1f;
    private float mPercentStillFlyout = 0f;

    /**
     * The difference in values between the flyout and the dot. These differences are gradually
     * added over the course of the animation to transform the flyout into the 'new' dot.
     */
    private float mFlyoutToDotWidthDelta = 0f;
    private float mFlyoutToDotHeightDelta = 0f;
    private float mFlyoutToDotCornerRadiusDelta;

    /** The translation values when the flyout is completely transitioned into the dot. */
    private float mTranslationXWhenDot = 0f;
    private float mTranslationYWhenDot = 0f;

    /**
     * The current translation values applied to the flyout background as it transitions into the
     * 'new' dot.
     */
    private float mBgTranslationX;
    private float mBgTranslationY;

    /** The flyout's X translation when at rest (not animating or dragging). */
    private float mRestingTranslationX = 0f;

    /** Callback to run when the flyout is hidden. */
    private Runnable mOnHide;

    public BubbleFlyoutView(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.bubble_flyout, this, true);

        mFlyoutTextContainer = findViewById(R.id.bubble_flyout_text_container);
        mFlyoutText = mFlyoutTextContainer.findViewById(R.id.bubble_flyout_text);

        final Resources res = getResources();
        mFlyoutPadding = res.getDimensionPixelSize(R.dimen.bubble_flyout_padding_x);
        mFlyoutSpaceFromBubble = res.getDimensionPixelSize(R.dimen.bubble_flyout_space_from_bubble);
        mPointerSize = res.getDimensionPixelSize(R.dimen.bubble_flyout_pointer_size);
        mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
        mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
        mFlyoutElevation = res.getDimensionPixelSize(R.dimen.bubble_flyout_elevation);
        mNewDotOffsetFromBubbleBounds = BadgeRenderer.getDotCenterOffset(context);
        mNewDotRadius = BadgeRenderer.getDotRadius(mNewDotOffsetFromBubbleBounds);
        mNewDotSize = mNewDotRadius * 2f;

        final TypedArray ta = mContext.obtainStyledAttributes(
                new int[] {
                        android.R.attr.colorBackgroundFloating,
                        android.R.attr.dialogCornerRadius});
        mFloatingBackgroundColor = ta.getColor(0, Color.WHITE);
        mCornerRadius = ta.getDimensionPixelSize(1, 0);
        mFlyoutToDotCornerRadiusDelta = mNewDotRadius - mCornerRadius;
        ta.recycle();

        // Add padding for the pointer on either side, onDraw will draw it in this space.
        setPadding(mPointerSize, 0, mPointerSize, 0);
        setWillNotDraw(false);
        setClipChildren(false);
        setTranslationZ(mFlyoutElevation);
        setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                BubbleFlyoutView.this.getOutline(outline);
            }
        });

        mBgPaint.setColor(mFloatingBackgroundColor);

        mLeftTriangleShape =
                new ShapeDrawable(TriangleShape.createHorizontal(
                        mPointerSize, mPointerSize, true /* isPointingLeft */));
        mLeftTriangleShape.setBounds(0, 0, mPointerSize, mPointerSize);
        mLeftTriangleShape.getPaint().setColor(mFloatingBackgroundColor);

        mRightTriangleShape =
                new ShapeDrawable(TriangleShape.createHorizontal(
                        mPointerSize, mPointerSize, false /* isPointingLeft */));
        mRightTriangleShape.setBounds(0, 0, mPointerSize, mPointerSize);
        mRightTriangleShape.getPaint().setColor(mFloatingBackgroundColor);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        renderBackground(canvas);
        invalidateOutline();
        super.onDraw(canvas);
    }

    /** Configures the flyout and animates it in. */
    void showFlyout(
            CharSequence updateMessage, PointF stackPos, float parentWidth,
            boolean arrowPointingLeft, int dotColor, Runnable onHide) {
        mArrowPointingLeft = arrowPointingLeft;
        mDotColor = dotColor;
        mOnHide = onHide;

        setCollapsePercent(0f);
        setAlpha(0f);
        setVisibility(VISIBLE);

        // Set the flyout TextView's max width in terms of percent, and then subtract out the
        // padding so that the entire flyout view will be the desired width (rather than the
        // TextView being the desired width + extra padding).
        mFlyoutText.setMaxWidth(
                (int) (parentWidth * FLYOUT_MAX_WIDTH_PERCENT) - mFlyoutPadding * 2);
        mFlyoutText.setText(updateMessage);

        // Wait for the TextView to lay out so we know its line count.
        post(() -> {
            // Multi line flyouts get top-aligned to the bubble.
            if (mFlyoutText.getLineCount() > 1) {
                setTranslationY(stackPos.y);
            } else {
                // Single line flyouts are vertically centered with respect to the bubble.
                setTranslationY(
                        stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f);
            }

            // Calculate the translation required to position the flyout next to the bubble stack,
            // with the desired padding.
            mRestingTranslationX = mArrowPointingLeft
                    ? stackPos.x + mBubbleSize + mFlyoutSpaceFromBubble
                    : stackPos.x - getWidth() - mFlyoutSpaceFromBubble;

            // Translate towards the stack slightly.
            setTranslationX(
                    mRestingTranslationX + (arrowPointingLeft ? -mBubbleSize : mBubbleSize));

            // Fade in the entire flyout and spring it to its normal position.
            animate().alpha(1f);
            mFlyoutSpring.animateToFinalPosition(mRestingTranslationX);

            // Calculate the difference in size between the flyout and the 'dot' so that we can
            // transform into the dot later.
            mFlyoutToDotWidthDelta = getWidth() - mNewDotSize;
            mFlyoutToDotHeightDelta = getHeight() - mNewDotSize;

            // Calculate the translation values needed to be in the correct 'new dot' position.
            final float distanceFromFlyoutLeftToDotCenterX =
                    mFlyoutSpaceFromBubble + mNewDotOffsetFromBubbleBounds / 2;
            if (mArrowPointingLeft) {
                mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX - mNewDotRadius;
            } else {
                mTranslationXWhenDot =
                        getWidth() + distanceFromFlyoutLeftToDotCenterX - mNewDotRadius;
            }

            mTranslationYWhenDot =
                    getHeight() / 2f
                            - mNewDotRadius
                            - mBubbleSize / 2f
                            + mNewDotOffsetFromBubbleBounds / 2;
        });
    }

    /**
     * Hides the flyout and runs the optional callback passed into showFlyout. The flyout has been
     * animated into the 'new' dot by the time we call this, so no animations are needed.
     */
    void hideFlyout() {
        if (mOnHide != null) {
            mOnHide.run();
            mOnHide = null;
        }

        setVisibility(GONE);
    }

    /** Sets the percentage that the flyout should be collapsed into dot form. */
    void setCollapsePercent(float percentCollapsed) {
        mPercentTransitionedToDot = Math.max(0f, Math.min(percentCollapsed, 1f));
        mPercentStillFlyout = (1f - mPercentTransitionedToDot);

        // Move and fade out the text.
        mFlyoutText.setTranslationX(
                (mArrowPointingLeft ? -getWidth() : getWidth()) * mPercentTransitionedToDot);
        mFlyoutText.setAlpha(clampPercentage(
                (mPercentStillFlyout - (1f - BubbleStackView.FLYOUT_DRAG_PERCENT_DISMISS))
                        / BubbleStackView.FLYOUT_DRAG_PERCENT_DISMISS));

        // Reduce the elevation towards that of the topmost bubble.
        setTranslationZ(
                mFlyoutElevation
                        - (mFlyoutElevation - mBubbleElevation) * mPercentTransitionedToDot);
        invalidate();
    }

    /** Return the flyout's resting X translation (translation when not dragging or animating). */
    float getRestingTranslationX() {
        return mRestingTranslationX;
    }

    /** Clamps a float to between 0 and 1. */
    private float clampPercentage(float percent) {
        return Math.min(1f, Math.max(0f, percent));
    }

    /**
     * Renders the background, which is either the rounded 'chat bubble' flyout, or some state
     * between that and the 'new' dot over the bubbles.
     */
    private void renderBackground(Canvas canvas) {
        // Calculate the width, height, and corner radius of the flyout given the current collapsed
        // percentage.
        final float width = getWidth() - (mFlyoutToDotWidthDelta * mPercentTransitionedToDot);
        final float height = getHeight() - (mFlyoutToDotHeightDelta * mPercentTransitionedToDot);
        final float cornerRadius = mCornerRadius
                - (mFlyoutToDotCornerRadiusDelta * mPercentTransitionedToDot);

        // Translate the flyout background towards the collapsed 'dot' state.
        mBgTranslationX = mTranslationXWhenDot * mPercentTransitionedToDot;
        mBgTranslationY = mTranslationYWhenDot * mPercentTransitionedToDot;

        // Set the bounds of the rounded rectangle that serves as either the flyout background or
        // the collapsed 'dot'. These bounds will also be used to provide the outline for elevation
        // shadows. In the expanded flyout state, the left and right bounds leave space for the
        // pointer triangle - as the flyout collapses, this space is reduced since the triangle
        // retracts into the flyout.
        mBgRect.set(
                mPointerSize * mPercentStillFlyout /* left */,
                0 /* top */,
                width - mPointerSize * mPercentStillFlyout /* right */,
                height /* bottom */);

        mBgPaint.setColor(
                (int) mArgbEvaluator.evaluate(
                        mPercentTransitionedToDot, mFloatingBackgroundColor, mDotColor));

        canvas.save();
        canvas.translate(mBgTranslationX, mBgTranslationY);
        renderPointerTriangle(canvas, width, height);
        canvas.drawRoundRect(mBgRect, cornerRadius, cornerRadius, mBgPaint);
        canvas.restore();
    }

    /** Renders the 'pointer' triangle that points from the flyout to the bubble stack. */
    private void renderPointerTriangle(
            Canvas canvas, float currentFlyoutWidth, float currentFlyoutHeight) {
        canvas.save();

        // Translation to apply for the 'retraction' effect as the flyout collapses.
        final float retractionTranslationX =
                (mArrowPointingLeft ? 1 : -1) * (mPercentTransitionedToDot * mPointerSize * 2f);

        // Place the arrow either at the left side, or the far right, depending on whether the
        // flyout is on the left or right side.
        final float arrowTranslationX =
                mArrowPointingLeft
                        ? retractionTranslationX
                        : currentFlyoutWidth - mPointerSize + retractionTranslationX;

        // Vertically center the arrow at all times.
        final float arrowTranslationY = currentFlyoutHeight / 2f - mPointerSize / 2f;

        // Draw the appropriate direction of arrow.
        final ShapeDrawable relevantTriangle =
                mArrowPointingLeft ? mLeftTriangleShape : mRightTriangleShape;
        canvas.translate(arrowTranslationX, arrowTranslationY);
        relevantTriangle.setAlpha((int) (255f * mPercentStillFlyout));
        relevantTriangle.draw(canvas);

        // Save the triangle's outline for use in the outline provider, offsetting it to reflect its
        // current position.
        relevantTriangle.getOutline(mTriangleOutline);
        mTriangleOutline.offset((int) arrowTranslationX, (int) arrowTranslationY);

        canvas.restore();
    }

    /** Builds an outline that includes the transformed flyout background and triangle. */
    private void getOutline(Outline outline) {
        if (!mTriangleOutline.isEmpty()) {
            // Draw the rect into the outline as a path so we can merge the triangle path into it.
            final Path rectPath = new Path();
            rectPath.addRoundRect(mBgRect, mCornerRadius, mCornerRadius, Path.Direction.CW);
            outline.setConvexPath(rectPath);

            // Get rid of the triangle path once it has disappeared behind the flyout.
            if (mPercentStillFlyout > 0.5f) {
                outline.mPath.addPath(mTriangleOutline.mPath);
            }

            // Translate the outline to match the background's position.
            final Matrix outlineMatrix = new Matrix();
            outlineMatrix.postTranslate(getLeft() + mBgTranslationX, getTop() + mBgTranslationY);

            // At the very end, retract the outline into the bubble so the shadow will be pulled
            // into the flyout-dot as it (visually) becomes part of the bubble. We can't do this by
            // animating translationZ to zero since then it'll go under the bubbles, which have
            // elevation.
            if (mPercentTransitionedToDot > 0.98f) {
                final float percentBetween99and100 = (mPercentTransitionedToDot - 0.98f) / .02f;
                final float percentShadowVisible = 1f - percentBetween99and100;

                // Keep it centered.
                outlineMatrix.postTranslate(
                        mNewDotRadius * percentBetween99and100,
                        mNewDotRadius * percentBetween99and100);
                outlineMatrix.preScale(percentShadowVisible, percentShadowVisible);
            }

            outline.mPath.transform(outlineMatrix);
        }
    }
}
