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

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.util.MathUtils;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;

import androidx.core.graphics.ColorUtils;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;

import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.statusbar.VibratorHelper;

public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPlugin {

    private static final String TAG = "NavigationBarEdgePanel";

    private static final long COLOR_ANIMATION_DURATION_MS = 120;
    private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 80;
    private static final long DISAPPEAR_ARROW_ANIMATION_DURATION_MS = 100;

    /**
     * The time required since the first vibration effect to automatically trigger a click
     */
    private static final int GESTURE_DURATION_FOR_CLICK_MS = 400;

    /**
     * The size of the protection of the arrow in px. Only used if this is not background protected
     */
    private static final int PROTECTION_WIDTH_PX = 2;

    /**
     * The basic translation in dp where the arrow resides
     */
    private static final int BASE_TRANSLATION_DP = 32;

    /**
     * The length of the arrow leg measured from the center to the end
     */
    private static final int ARROW_LENGTH_DP = 18;

    /**
     * The angle measured from the xAxis, where the leg is when the arrow rests
     */
    private static final int ARROW_ANGLE_WHEN_EXTENDED_DEGREES = 56;

    /**
     * The angle that is added per 1000 px speed to the angle of the leg
     */
    private static final int ARROW_ANGLE_ADDED_PER_1000_SPEED = 4;

    /**
     * The maximum angle offset allowed due to speed
     */
    private static final int ARROW_MAX_ANGLE_SPEED_OFFSET_DEGREES = 4;

    /**
     * The thickness of the arrow. Adjusted to match the home handle (approximately)
     */
    private static final float ARROW_THICKNESS_DP = 2.5f;

    /**
     * The amount of rubber banding we do for the vertical translation
     */
    private static final int RUBBER_BAND_AMOUNT = 15;

    /**
     * The interpolator used to rubberband
     */
    private static final Interpolator RUBBER_BAND_INTERPOLATOR
            = new PathInterpolator(1.0f / 5.0f, 1.0f, 1.0f, 1.0f);

    /**
     * The amount of rubber banding we do for the translation before base translation
     */
    private static final int RUBBER_BAND_AMOUNT_APPEAR = 4;

    /**
     * The interpolator used to rubberband the appearing of the arrow.
     */
    private static final Interpolator RUBBER_BAND_INTERPOLATOR_APPEAR
            = new PathInterpolator(1.0f / RUBBER_BAND_AMOUNT_APPEAR, 1.0f, 1.0f, 1.0f);

    private final WindowManager mWindowManager;
    private final VibratorHelper mVibratorHelper;

    /**
     * The paint the arrow is drawn with
     */
    private final Paint mPaint = new Paint();
    /**
     * The paint the arrow protection is drawn with
     */
    private final Paint mProtectionPaint;

    private final float mDensity;
    private final float mBaseTranslation;
    private final float mArrowLength;
    private final float mArrowThickness;

    /**
     * The minimum delta needed in movement for the arrow to change direction / stop triggering back
     */
    private final float mMinDeltaForSwitch;
    // The closest to y = 0 that the arrow will be displayed.
    private int mMinArrowPosition;
    // The amount the arrow is shifted to avoid the finger.
    private int mFingerOffset;

    private final float mSwipeThreshold;
    private final Path mArrowPath = new Path();
    private final Point mDisplaySize = new Point();

    private final SpringAnimation mAngleAnimation;
    private final SpringAnimation mTranslationAnimation;
    private final SpringAnimation mVerticalTranslationAnimation;
    private final SpringForce mAngleAppearForce;
    private final SpringForce mAngleDisappearForce;
    private final ValueAnimator mArrowColorAnimator;
    private final ValueAnimator mArrowDisappearAnimation;
    private final SpringForce mRegularTranslationSpring;
    private final SpringForce mTriggerBackSpring;

    private VelocityTracker mVelocityTracker;
    private boolean mIsDark = false;
    private boolean mShowProtection = false;
    private int mProtectionColorLight;
    private int mArrowPaddingEnd;
    private int mArrowColorLight;
    private int mProtectionColorDark;
    private int mArrowColorDark;
    private int mProtectionColor;
    private int mArrowColor;
    private RegionSamplingHelper mRegionSamplingHelper;
    private final Rect mSamplingRect = new Rect();
    private WindowManager.LayoutParams mLayoutParams;
    private int mLeftInset;
    private int mRightInset;

    /**
     * True if the panel is currently on the left of the screen
     */
    private boolean mIsLeftPanel;

    private float mStartX;
    private float mStartY;
    private float mCurrentAngle;
    /**
     * The current translation of the arrow
     */
    private float mCurrentTranslation;
    /**
     * Where the arrow will be in the resting position.
     */
    private float mDesiredTranslation;

    private boolean mDragSlopPassed;
    private boolean mArrowsPointLeft;
    private float mMaxTranslation;
    private boolean mTriggerBack;
    private float mPreviousTouchTranslation;
    private float mTotalTouchDelta;
    private float mVerticalTranslation;
    private float mDesiredVerticalTranslation;
    private float mDesiredAngle;
    private float mAngleOffset;
    private int mArrowStartColor;
    private int mCurrentArrowColor;
    private float mDisappearAmount;
    private long mVibrationTime;
    private int mScreenSize;

    private DynamicAnimation.OnAnimationEndListener mSetGoneEndListener
            = new DynamicAnimation.OnAnimationEndListener() {
        @Override
        public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
                float velocity) {
            animation.removeEndListener(this);
            if (!canceled) {
                setVisibility(GONE);
            }
        }
    };
    private static final FloatPropertyCompat<NavigationBarEdgePanel> CURRENT_ANGLE =
            new FloatPropertyCompat<NavigationBarEdgePanel>("currentAngle") {
        @Override
        public void setValue(NavigationBarEdgePanel object, float value) {
            object.setCurrentAngle(value);
        }

        @Override
        public float getValue(NavigationBarEdgePanel object) {
            return object.getCurrentAngle();
        }
    };

    private static final FloatPropertyCompat<NavigationBarEdgePanel> CURRENT_TRANSLATION =
            new FloatPropertyCompat<NavigationBarEdgePanel>("currentTranslation") {

                @Override
                public void setValue(NavigationBarEdgePanel object, float value) {
                    object.setCurrentTranslation(value);
                }

                @Override
                public float getValue(NavigationBarEdgePanel object) {
                    return object.getCurrentTranslation();
                }
            };
    private static final FloatPropertyCompat<NavigationBarEdgePanel> CURRENT_VERTICAL_TRANSLATION =
            new FloatPropertyCompat<NavigationBarEdgePanel>("verticalTranslation") {

                @Override
                public void setValue(NavigationBarEdgePanel object, float value) {
                    object.setVerticalTranslation(value);
                }

                @Override
                public float getValue(NavigationBarEdgePanel object) {
                    return object.getVerticalTranslation();
                }
            };
    private BackCallback mBackCallback;

    public NavigationBarEdgePanel(Context context) {
        super(context);

        mWindowManager = context.getSystemService(WindowManager.class);
        mVibratorHelper = Dependency.get(VibratorHelper.class);

        mDensity = context.getResources().getDisplayMetrics().density;

        mBaseTranslation = dp(BASE_TRANSLATION_DP);
        mArrowLength = dp(ARROW_LENGTH_DP);
        mArrowThickness = dp(ARROW_THICKNESS_DP);
        mMinDeltaForSwitch = dp(32);

        mPaint.setStrokeWidth(mArrowThickness);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);

        mArrowColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
        mArrowColorAnimator.setDuration(COLOR_ANIMATION_DURATION_MS);
        mArrowColorAnimator.addUpdateListener(animation -> {
            int newColor = ColorUtils.blendARGB(
                    mArrowStartColor, mArrowColor, animation.getAnimatedFraction());
            setCurrentArrowColor(newColor);
        });

        mArrowDisappearAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
        mArrowDisappearAnimation.setDuration(DISAPPEAR_ARROW_ANIMATION_DURATION_MS);
        mArrowDisappearAnimation.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
        mArrowDisappearAnimation.addUpdateListener(animation -> {
            mDisappearAmount = (float) animation.getAnimatedValue();
            invalidate();
        });

        mAngleAnimation =
                new SpringAnimation(this, CURRENT_ANGLE);
        mAngleAppearForce = new SpringForce()
                .setStiffness(500)
                .setDampingRatio(0.5f);
        mAngleDisappearForce = new SpringForce()
                .setStiffness(SpringForce.STIFFNESS_MEDIUM)
                .setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY)
                .setFinalPosition(90);
        mAngleAnimation.setSpring(mAngleAppearForce).setMaxValue(90);

        mTranslationAnimation =
                new SpringAnimation(this, CURRENT_TRANSLATION);
        mRegularTranslationSpring = new SpringForce()
                .setStiffness(SpringForce.STIFFNESS_MEDIUM)
                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);
        mTriggerBackSpring = new SpringForce()
                .setStiffness(450)
                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);
        mTranslationAnimation.setSpring(mRegularTranslationSpring);
        mVerticalTranslationAnimation =
                new SpringAnimation(this, CURRENT_VERTICAL_TRANSLATION);
        mVerticalTranslationAnimation.setSpring(
                new SpringForce()
                        .setStiffness(SpringForce.STIFFNESS_MEDIUM)
                        .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));

        mProtectionPaint = new Paint(mPaint);
        mProtectionPaint.setStrokeWidth(mArrowThickness + PROTECTION_WIDTH_PX);
        loadDimens();

        loadColors(context);
        updateArrowDirection();

        mSwipeThreshold = context.getResources()
                .getDimension(R.dimen.navigation_edge_action_drag_threshold);
        setVisibility(GONE);

        mRegionSamplingHelper = new RegionSamplingHelper(this,
                new RegionSamplingHelper.SamplingCallback() {
                    @Override
                    public void onRegionDarknessChanged(boolean isRegionDark) {
                        setIsDark(!isRegionDark, true /* animate */);
                    }

                    @Override
                    public Rect getSampledRegion(View sampledView) {
                        return mSamplingRect;
                    }
                });
        mRegionSamplingHelper.setWindowVisible(true);
    }

    @Override
    public void onDestroy() {
        mWindowManager.removeView(this);
        mRegionSamplingHelper.stop();
        mRegionSamplingHelper = null;
    }

    @Override
    public boolean hasOverlappingRendering() {
        return false;
    }

    private void setIsDark(boolean isDark, boolean animate) {
        mIsDark = isDark;
        updateIsDark(animate);
    }

    private void setShowProtection(boolean showProtection) {
        mShowProtection = showProtection;
        invalidate();
    }

    @Override
    public void setIsLeftPanel(boolean isLeftPanel) {
        mIsLeftPanel = isLeftPanel;
        mLayoutParams.gravity = mIsLeftPanel
                ? (Gravity.LEFT | Gravity.TOP)
                : (Gravity.RIGHT | Gravity.TOP);
    }

    @Override
    public void setInsets(int leftInset, int rightInset) {
        mLeftInset = leftInset;
        mRightInset = rightInset;
    }

    @Override
    public void setDisplaySize(Point displaySize) {
        mDisplaySize.set(displaySize.x, displaySize.y);
        mScreenSize = Math.min(mDisplaySize.x, mDisplaySize.y);
    }

    @Override
    public void setBackCallback(BackCallback callback) {
        mBackCallback = callback;
    }

    @Override
    public void setLayoutParams(WindowManager.LayoutParams layoutParams) {
        mLayoutParams = layoutParams;
        mWindowManager.addView(this, mLayoutParams);
    }

    /**
     * Adjusts the sampling rect to conform to the actual visible bounding box of the arrow.
     */
    private void adjustSamplingRectToBoundingBox() {
        float translation = mDesiredTranslation;
        if (!mTriggerBack) {
            // Let's take the resting position and bounds as the sampling rect, since we are not
            // visible right now
            translation = mBaseTranslation;
            if (mIsLeftPanel && mArrowsPointLeft
                    || (!mIsLeftPanel && !mArrowsPointLeft)) {
                // If we're on the left we should move less, because the arrow is facing the other
                // direction
                translation -= getStaticArrowWidth();
            }
        }
        float left = translation - mArrowThickness / 2.0f;
        left = mIsLeftPanel ? left : mSamplingRect.width() - left;

        // Let's calculate the position of the end based on the angle
        float width = getStaticArrowWidth();
        float height = polarToCartY(ARROW_ANGLE_WHEN_EXTENDED_DEGREES) * mArrowLength * 2.0f;
        if (!mArrowsPointLeft) {
            left -= width;
        }

        float top = (getHeight() * 0.5f) + mDesiredVerticalTranslation - height / 2.0f;
        mSamplingRect.offset((int) left, (int) top);
        mSamplingRect.set(mSamplingRect.left, mSamplingRect.top,
                (int) (mSamplingRect.left + width),
                (int) (mSamplingRect.top + height));
        mRegionSamplingHelper.updateSamplingRect();
    }

    @Override
    public void onMotionEvent(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mDragSlopPassed = false;
                resetOnDown();
                mStartX = event.getX();
                mStartY = event.getY();
                setVisibility(VISIBLE);
                updatePosition(event.getY());
                mRegionSamplingHelper.start(mSamplingRect);
                mWindowManager.updateViewLayout(this, mLayoutParams);
                break;
            case MotionEvent.ACTION_MOVE:
                handleMoveEvent(event);
                break;
            case MotionEvent.ACTION_UP:
                if (mTriggerBack) {
                    triggerBack();
                } else {
                    cancelBack();
                }
                mRegionSamplingHelper.stop();
                mVelocityTracker.recycle();
                mVelocityTracker = null;
                break;
            case MotionEvent.ACTION_CANCEL:
                cancelBack();
                mRegionSamplingHelper.stop();
                mVelocityTracker.recycle();
                mVelocityTracker = null;
                break;
        }
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        updateArrowDirection();
        loadDimens();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float pointerPosition = mCurrentTranslation - mArrowThickness / 2.0f;
        canvas.save();
        canvas.translate(
                mIsLeftPanel ? pointerPosition : getWidth() - pointerPosition,
                (getHeight() * 0.5f) + mVerticalTranslation);

        // Let's calculate the position of the end based on the angle
        float x = (polarToCartX(mCurrentAngle) * mArrowLength);
        float y = (polarToCartY(mCurrentAngle) * mArrowLength);
        Path arrowPath = calculatePath(x,y);
        if (mShowProtection) {
            canvas.drawPath(arrowPath, mProtectionPaint);
        }

        canvas.drawPath(arrowPath, mPaint);
        canvas.restore();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        mMaxTranslation = getWidth() - mArrowPaddingEnd;
    }

    private void loadDimens() {
        Resources res = getResources();
        mArrowPaddingEnd = res.getDimensionPixelSize(R.dimen.navigation_edge_panel_padding);
        mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
        mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
    }

    private void updateArrowDirection() {
        // Both panels arrow point the same way
        mArrowsPointLeft = getLayoutDirection() == LAYOUT_DIRECTION_LTR;
        invalidate();
    }

    private void loadColors(Context context) {
        final int dualToneDarkTheme = Utils.getThemeAttr(context, R.attr.darkIconTheme);
        final int dualToneLightTheme = Utils.getThemeAttr(context, R.attr.lightIconTheme);
        Context lightContext = new ContextThemeWrapper(context, dualToneLightTheme);
        Context darkContext = new ContextThemeWrapper(context, dualToneDarkTheme);
        mArrowColorLight = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
        mArrowColorDark = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);
        mProtectionColorDark = mArrowColorLight;
        mProtectionColorLight = mArrowColorDark;
        updateIsDark(false /* animate */);
    }

    private void updateIsDark(boolean animate) {
        // TODO: Maybe animate protection as well
        mProtectionColor = mIsDark ? mProtectionColorDark : mProtectionColorLight;
        mProtectionPaint.setColor(mProtectionColor);
        mArrowColor = mIsDark ? mArrowColorDark : mArrowColorLight;
        mArrowColorAnimator.cancel();
        if (!animate) {
            setCurrentArrowColor(mArrowColor);
        } else {
            mArrowStartColor = mCurrentArrowColor;
            mArrowColorAnimator.start();
        }
    }

    private void setCurrentArrowColor(int color) {
        mCurrentArrowColor = color;
        mPaint.setColor(color);
        invalidate();
    }

    private float getStaticArrowWidth() {
        return polarToCartX(ARROW_ANGLE_WHEN_EXTENDED_DEGREES) * mArrowLength;
    }

    private float polarToCartX(float angleInDegrees) {
        return (float) Math.cos(Math.toRadians(angleInDegrees));
    }

    private float polarToCartY(float angleInDegrees) {
        return (float) Math.sin(Math.toRadians(angleInDegrees));
    }

    private Path calculatePath(float x, float y) {
        if (!mArrowsPointLeft) {
            x = -x;
        }
        float extent = MathUtils.lerp(1.0f, 0.75f, mDisappearAmount);
        x = x * extent;
        y = y * extent;
        mArrowPath.reset();
        mArrowPath.moveTo(x, y);
        mArrowPath.lineTo(0, 0);
        mArrowPath.lineTo(x, -y);
        return mArrowPath;
    }

    private float getCurrentAngle() {
        return mCurrentAngle;
    }

    private float getCurrentTranslation() {
        return mCurrentTranslation;
    }

    private void triggerBack() {
        mBackCallback.triggerBack();

        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.computeCurrentVelocity(1000);
        // Only do the extra translation if we're not already flinging
        boolean isSlow = Math.abs(mVelocityTracker.getXVelocity()) < 500;
        if (isSlow
                || SystemClock.uptimeMillis() - mVibrationTime >= GESTURE_DURATION_FOR_CLICK_MS) {
            mVibratorHelper.vibrate(VibrationEffect.EFFECT_CLICK);
        }

        // Let's also snap the angle a bit
        if (mAngleOffset > -4) {
            mAngleOffset = Math.max(-8, mAngleOffset - 8);
            updateAngle(true /* animated */);
        }

        // Finally, after the translation, animate back and disappear the arrow
        Runnable translationEnd = () -> {
            // let's snap it back
            mAngleOffset = Math.max(0, mAngleOffset + 8);
            updateAngle(true /* animated */);

            mTranslationAnimation.setSpring(mTriggerBackSpring);
            // Translate the arrow back a bit to make for a nice transition
            setDesiredTranslation(mDesiredTranslation - dp(32), true /* animated */);
            animate().alpha(0f).setDuration(DISAPPEAR_FADE_ANIMATION_DURATION_MS)
                    .withEndAction(() -> setVisibility(GONE));
            mArrowDisappearAnimation.start();
        };
        if (mTranslationAnimation.isRunning()) {
            mTranslationAnimation.addEndListener(new DynamicAnimation.OnAnimationEndListener() {
                @Override
                public void onAnimationEnd(DynamicAnimation animation, boolean canceled,
                        float value,
                        float velocity) {
                    animation.removeEndListener(this);
                    if (!canceled) {
                        translationEnd.run();
                    }
                }
            });
        } else {
            translationEnd.run();
        }
    }

    private void cancelBack() {
        mBackCallback.cancelBack();

        if (mTranslationAnimation.isRunning()) {
            mTranslationAnimation.addEndListener(mSetGoneEndListener);
        } else {
            setVisibility(GONE);
        }
    }

    private void resetOnDown() {
        animate().cancel();
        mAngleAnimation.cancel();
        mTranslationAnimation.cancel();
        mVerticalTranslationAnimation.cancel();
        mArrowDisappearAnimation.cancel();
        mAngleOffset = 0;
        mTranslationAnimation.setSpring(mRegularTranslationSpring);
        // Reset the arrow to the side
        setTriggerBack(false /* triggerBack */, false /* animated */);
        setDesiredTranslation(0, false /* animated */);
        setCurrentTranslation(0);
        updateAngle(false /* animate */);
        mPreviousTouchTranslation = 0;
        mTotalTouchDelta = 0;
        mVibrationTime = 0;
        setDesiredVerticalTransition(0, false /* animated */);
    }

    private void handleMoveEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        float touchTranslation = MathUtils.abs(x - mStartX);
        float yOffset = y - mStartY;
        float delta = touchTranslation - mPreviousTouchTranslation;
        if (Math.abs(delta) > 0) {
            if (Math.signum(delta) == Math.signum(mTotalTouchDelta)) {
                mTotalTouchDelta += delta;
            } else {
                mTotalTouchDelta = delta;
            }
        }
        mPreviousTouchTranslation = touchTranslation;

        // Apply a haptic on drag slop passed
        if (!mDragSlopPassed && touchTranslation > mSwipeThreshold) {
            mDragSlopPassed = true;
            mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
            mVibrationTime = SystemClock.uptimeMillis();

            // Let's show the arrow and animate it in!
            mDisappearAmount = 0.0f;
            setAlpha(1f);
            // And animate it go to back by default!
            setTriggerBack(true /* triggerBack */, true /* animated */);
        }

        // Let's make sure we only go to the baseextend and apply rubberbanding afterwards
        if (touchTranslation > mBaseTranslation) {
            float diff = touchTranslation - mBaseTranslation;
            float progress = MathUtils.saturate(diff / (mScreenSize - mBaseTranslation));
            progress = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
                    * (mMaxTranslation - mBaseTranslation);
            touchTranslation = mBaseTranslation + progress;
        } else {
            float diff = mBaseTranslation - touchTranslation;
            float progress = MathUtils.saturate(diff / mBaseTranslation);
            progress = RUBBER_BAND_INTERPOLATOR_APPEAR.getInterpolation(progress)
                    * (mBaseTranslation / RUBBER_BAND_AMOUNT_APPEAR);
            touchTranslation = mBaseTranslation - progress;
        }
        // By default we just assume the current direction is kept
        boolean triggerBack = mTriggerBack;

        //  First lets see if we had continuous motion in one direction for a while
        if (Math.abs(mTotalTouchDelta) > mMinDeltaForSwitch) {
            triggerBack = mTotalTouchDelta > 0;
        }

        // Then, let's see if our velocity tells us to change direction
        mVelocityTracker.computeCurrentVelocity(1000);
        float xVelocity = mVelocityTracker.getXVelocity();
        float yVelocity = mVelocityTracker.getYVelocity();
        float velocity = MathUtils.mag(xVelocity, yVelocity);
        mAngleOffset = Math.min(velocity / 1000 * ARROW_ANGLE_ADDED_PER_1000_SPEED,
                ARROW_MAX_ANGLE_SPEED_OFFSET_DEGREES) * Math.signum(xVelocity);
        if (mIsLeftPanel && mArrowsPointLeft || !mIsLeftPanel && !mArrowsPointLeft) {
            mAngleOffset *= -1;
        }

        // Last if the direction in Y is bigger than X * 2 we also abort
        if (Math.abs(yOffset) > Math.abs(x - mStartX) * 2) {
            triggerBack = false;
        }
        setTriggerBack(triggerBack, true /* animated */);

        if (!mTriggerBack) {
            touchTranslation = 0;
        } else if (mIsLeftPanel && mArrowsPointLeft
                || (!mIsLeftPanel && !mArrowsPointLeft)) {
            // If we're on the left we should move less, because the arrow is facing the other
            // direction
            touchTranslation -= getStaticArrowWidth();
        }
        setDesiredTranslation(touchTranslation, true /* animated */);
        updateAngle(true /* animated */);

        float maxYOffset = getHeight() / 2.0f - mArrowLength;
        float progress = MathUtils.constrain(
                Math.abs(yOffset) / (maxYOffset * RUBBER_BAND_AMOUNT),
                0, 1);
        float verticalTranslation = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
                * maxYOffset * Math.signum(yOffset);
        setDesiredVerticalTransition(verticalTranslation, true /* animated */);
        updateSamplingRect();
    }

    private void updatePosition(float touchY) {
        float position = touchY - mFingerOffset;
        position = Math.max(position, mMinArrowPosition);
        position -= mLayoutParams.height / 2.0f;
        mLayoutParams.y = MathUtils.constrain((int) position, 0, mDisplaySize.y);
        updateSamplingRect();
    }

    private void updateSamplingRect() {
        int top = mLayoutParams.y;
        int left = mIsLeftPanel ? mLeftInset : mDisplaySize.x - mRightInset - mLayoutParams.width;
        int right = left + mLayoutParams.width;
        int bottom = top + mLayoutParams.height;
        mSamplingRect.set(left, top, right, bottom);
        adjustSamplingRectToBoundingBox();
    }

    private void setDesiredVerticalTransition(float verticalTranslation, boolean animated) {
        if (mDesiredVerticalTranslation != verticalTranslation) {
            mDesiredVerticalTranslation = verticalTranslation;
            if (!animated) {
                setVerticalTranslation(verticalTranslation);
            } else {
                mVerticalTranslationAnimation.animateToFinalPosition(verticalTranslation);
            }
            invalidate();
        }
    }

    private void setVerticalTranslation(float verticalTranslation) {
        mVerticalTranslation = verticalTranslation;
        invalidate();
    }

    private float getVerticalTranslation() {
        return mVerticalTranslation;
    }

    private void setDesiredTranslation(float desiredTranslation, boolean animated) {
        if (mDesiredTranslation != desiredTranslation) {
            mDesiredTranslation = desiredTranslation;
            if (!animated) {
                setCurrentTranslation(desiredTranslation);
            } else {
                mTranslationAnimation.animateToFinalPosition(desiredTranslation);
            }
        }
    }

    private void setCurrentTranslation(float currentTranslation) {
        mCurrentTranslation = currentTranslation;
        invalidate();
    }

    private void setTriggerBack(boolean triggerBack, boolean animated) {
        if (mTriggerBack != triggerBack) {
            mTriggerBack = triggerBack;
            mAngleAnimation.cancel();
            updateAngle(animated);
            // Whenever the trigger back state changes the existing translation animation should be
            // cancelled
            mTranslationAnimation.cancel();
        }
    }

    private void updateAngle(boolean animated) {
        float newAngle = mTriggerBack ? ARROW_ANGLE_WHEN_EXTENDED_DEGREES + mAngleOffset : 90;
        if (newAngle != mDesiredAngle) {
            if (!animated) {
                setCurrentAngle(newAngle);
            } else {
                mAngleAnimation.setSpring(mTriggerBack ? mAngleAppearForce : mAngleDisappearForce);
                mAngleAnimation.animateToFinalPosition(newAngle);
            }
            mDesiredAngle = newAngle;
        }
    }

    private void setCurrentAngle(float currentAngle) {
        mCurrentAngle = currentAngle;
        invalidate();
    }

    private float dp(float dp) {
        return mDensity * dp;
    }
}
