/*
 * 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 Licen
 */


package com.android.systemui.statusbar.notification.stack;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.SwipeHelper;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;

class NotificationSwipeHelper extends SwipeHelper
        implements NotificationSwipeActionHelper {
    @VisibleForTesting
    protected static final long COVER_MENU_DELAY = 4000;
    private static final String TAG = "NotificationSwipeHelper";
    private final Runnable mFalsingCheck;
    private View mTranslatingParentView;
    private View mMenuExposedView;
    private final NotificationCallback mCallback;
    private final NotificationMenuRowPlugin.OnMenuEventListener mMenuListener;

    private static final long SWIPE_MENU_TIMING = 200;

    private NotificationMenuRowPlugin mCurrMenuRow;

    public NotificationSwipeHelper(int swipeDirection, NotificationCallback callback,
            Context context, NotificationMenuRowPlugin.OnMenuEventListener menuListener) {
        super(swipeDirection, callback, context);
        mMenuListener = menuListener;
        mCallback = callback;
        mFalsingCheck = new Runnable() {
            @Override
            public void run() {
                resetExposedMenuView(true /* animate */, true /* force */);
            }
        };
    }

    public View getTranslatingParentView() {
        return mTranslatingParentView;
    }

    public void clearTranslatingParentView() { setTranslatingParentView(null); }

    @VisibleForTesting
    protected void setTranslatingParentView(View view) { mTranslatingParentView = view; };

    public void setExposedMenuView(View view) {
        mMenuExposedView = view;
    }

    public void clearExposedMenuView() { setExposedMenuView(null); }

    public void clearCurrentMenuRow() { setCurrentMenuRow(null); }

    public View getExposedMenuView() {
        return mMenuExposedView;
    }

    public void setCurrentMenuRow(NotificationMenuRowPlugin menuRow) {
        mCurrMenuRow = menuRow;
    }

    public NotificationMenuRowPlugin getCurrentMenuRow() {  return mCurrMenuRow; }

    @VisibleForTesting
    protected Handler getHandler() { return mHandler; }

    @VisibleForTesting
    protected Runnable getFalsingCheck() { return mFalsingCheck; };

    @Override
    public void onDownUpdate(View currView, MotionEvent ev) {
        mTranslatingParentView = currView;
        NotificationMenuRowPlugin menuRow = getCurrentMenuRow();
        if (menuRow != null) {
            menuRow.onTouchStart();
        }
        clearCurrentMenuRow();
        getHandler().removeCallbacks(getFalsingCheck());

        // Slide back any notifications that might be showing a menu
        resetExposedMenuView(true /* animate */, false /* force */);

        if (currView instanceof ExpandableNotificationRow) {
            initializeRow((ExpandableNotificationRow) currView);
        }
    }

    @VisibleForTesting
    protected void initializeRow(ExpandableNotificationRow row) {
        if (row.getEntry().hasFinishedInitialization()) {
            mCurrMenuRow = row.createMenu();
            mCurrMenuRow.setMenuClickListener(mMenuListener);
            mCurrMenuRow.onTouchStart();
        }
    }

    private boolean swipedEnoughToShowMenu(NotificationMenuRowPlugin menuRow) {
        return !swipedFarEnough() && menuRow.isSwipedEnoughToShowMenu();
    }

    @Override
    public void onMoveUpdate(View view, MotionEvent ev, float translation, float delta) {
        getHandler().removeCallbacks(getFalsingCheck());
        NotificationMenuRowPlugin menuRow = getCurrentMenuRow();
        if (menuRow != null) {
            menuRow.onTouchMove(delta);
        }
    }

    @Override
    public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
            float translation) {
        NotificationMenuRowPlugin menuRow = getCurrentMenuRow();
        if (menuRow != null) {
            menuRow.onTouchEnd();
            handleMenuRowSwipe(ev, animView, velocity, menuRow);
            return true;
        }
        return false;
    }

    @VisibleForTesting
    protected void handleMenuRowSwipe(MotionEvent ev, View animView, float velocity,
            NotificationMenuRowPlugin menuRow) {
        if (!menuRow.shouldShowMenu()) {
            // If the menu should not be shown, then there is no need to check if the a swipe
            // should result in a snapping to the menu. As a result, just check if the swipe
            // was enough to dismiss the notification.
            if (isDismissGesture(ev)) {
                dismiss(animView, velocity);
            } else {
                snapClosed(animView, velocity);
                menuRow.onSnapClosed();
            }
            return;
        }

        if (menuRow.isSnappedAndOnSameSide()) {
            // Menu was snapped to previously and we're on the same side
            handleSwipeFromOpenState(ev, animView, velocity, menuRow);
        } else {
            // Menu has not been snapped, or was snapped previously but is now on
            // the opposite side.
            handleSwipeFromClosedState(ev, animView, velocity, menuRow);
        }
    }

    private void handleSwipeFromClosedState(MotionEvent ev, View animView, float velocity,
            NotificationMenuRowPlugin menuRow) {
        boolean isDismissGesture = isDismissGesture(ev);
        final boolean gestureTowardsMenu = menuRow.isTowardsMenu(velocity);
        final boolean gestureFastEnough = getEscapeVelocity() <= Math.abs(velocity);

        final double timeForGesture = ev.getEventTime() - ev.getDownTime();
        final boolean showMenuForSlowOnGoing = !menuRow.canBeDismissed()
                && timeForGesture >= SWIPE_MENU_TIMING;

        boolean isNonDismissGestureTowardsMenu = gestureTowardsMenu && !isDismissGesture;
        boolean isSlowSwipe = !gestureFastEnough || showMenuForSlowOnGoing;
        boolean slowSwipedFarEnough = swipedEnoughToShowMenu(menuRow) && isSlowSwipe;
        boolean isFastNonDismissGesture =
                gestureFastEnough && !gestureTowardsMenu && !isDismissGesture;
        boolean isMenuRevealingGestureAwayFromMenu = slowSwipedFarEnough || isFastNonDismissGesture;
        int menuSnapTarget = menuRow.getMenuSnapTarget();
        boolean isNonFalseMenuRevealingGesture =
                !isFalseGesture(ev) && isMenuRevealingGestureAwayFromMenu;
        if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
                && menuSnapTarget != 0) {
            // Menu has not been snapped to previously and this is menu revealing gesture
            snapOpen(animView, menuSnapTarget, velocity);
            menuRow.onSnapOpen();
        } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
            dismiss(animView, velocity);
            menuRow.onDismiss();
        } else {
            snapClosed(animView, velocity);
            menuRow.onSnapClosed();
        }
    }

    private void handleSwipeFromOpenState(MotionEvent ev, View animView, float velocity,
            NotificationMenuRowPlugin menuRow) {
        boolean isDismissGesture = isDismissGesture(ev);

        final boolean withinSnapMenuThreshold =
                menuRow.isWithinSnapMenuThreshold();

        if (withinSnapMenuThreshold && !isDismissGesture) {
            // Haven't moved enough to unsnap from the menu
            menuRow.onSnapOpen();
            snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
        } else if (isDismissGesture && !menuRow.shouldSnapBack()) {
            // Only dismiss if we're not moving towards the menu
            dismiss(animView, velocity);
            menuRow.onDismiss();
        } else {
            snapClosed(animView, velocity);
            menuRow.onSnapClosed();
        }
    }

    @Override
    public void dismissChild(final View view, float velocity,
            boolean useAccelerateInterpolator) {
        superDismissChild(view, velocity, useAccelerateInterpolator);
        if (mCallback.isExpanded()) {
            // We don't want to quick-dismiss when it's a heads up as this might lead to closing
            // of the panel early.
            mCallback.handleChildViewDismissed(view);
        }
        mCallback.onDismiss();
        handleMenuCoveredOrDismissed();
    }

    @VisibleForTesting
    protected void superDismissChild(final View view, float velocity, boolean useAccelerateInterpolator) {
        super.dismissChild(view, velocity, useAccelerateInterpolator);
    }

    @VisibleForTesting
    protected void superSnapChild(final View animView, final float targetLeft, float velocity) {
        super.snapChild(animView, targetLeft, velocity);
    }

    @Override
    public void snapChild(final View animView, final float targetLeft, float velocity) {
        superSnapChild(animView, targetLeft, velocity);
        mCallback.onDragCancelled(animView);
        if (targetLeft == 0) {
            handleMenuCoveredOrDismissed();
        }
    }

    @Override
    public void snooze(StatusBarNotification sbn, SnoozeOption snoozeOption) {
        mCallback.onSnooze(sbn, snoozeOption);
    }

    @VisibleForTesting
    protected void handleMenuCoveredOrDismissed() {
        View exposedMenuView = getExposedMenuView();
        if (exposedMenuView != null && exposedMenuView == mTranslatingParentView) {
            clearExposedMenuView();
        }
    }

    @VisibleForTesting
    protected Animator superGetViewTranslationAnimator(View v, float target,
            ValueAnimator.AnimatorUpdateListener listener) {
        return super.getViewTranslationAnimator(v, target, listener);
    }

    @Override
    public Animator getViewTranslationAnimator(View v, float target,
            ValueAnimator.AnimatorUpdateListener listener) {
        if (v instanceof ExpandableNotificationRow) {
            return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
        } else {
            return superGetViewTranslationAnimator(v, target, listener);
        }
    }

    @Override
    public void setTranslation(View v, float translate) {
        if (v instanceof ExpandableNotificationRow) {
            ((ExpandableNotificationRow) v).setTranslation(translate);
        } else {
            Log.wtf(TAG, "setTranslation should only be called on an ExpandableNotificationRow.");
        }
    }

    @Override
    public float getTranslation(View v) {
        if (v instanceof ExpandableNotificationRow) {
            return ((ExpandableNotificationRow) v).getTranslation();
        }
        else {
            Log.wtf(TAG, "getTranslation should only be called on an ExpandableNotificationRow.");
            return 0f;
        }
    }

    @Override
    public boolean swipedFastEnough(float translation, float viewSize) {
        return swipedFastEnough();
    }

    @Override
    @VisibleForTesting
    protected boolean swipedFastEnough() {
        return super.swipedFastEnough();
    }

    @Override
    public boolean swipedFarEnough(float translation, float viewSize) {
        return swipedFarEnough();
    }

    @Override
    @VisibleForTesting
    protected boolean swipedFarEnough() {
        return super.swipedFarEnough();
    }

    @Override
    public void dismiss(View animView, float velocity) {
        dismissChild(animView, velocity,
                !swipedFastEnough() /* useAccelerateInterpolator */);
    }

    @Override
    public void snapOpen(View animView, int targetLeft, float velocity) {
        snapChild(animView, targetLeft, velocity);
    }

    @VisibleForTesting
    protected void snapClosed(View animView, float velocity) {
        snapChild(animView, 0, velocity);
    }

    @Override
    @VisibleForTesting
    protected float getEscapeVelocity() {
        return super.getEscapeVelocity();
    }

    @Override
    public float getMinDismissVelocity() {
        return getEscapeVelocity();
    }

    public void onMenuShown(View animView) {
        setExposedMenuView(getTranslatingParentView());
        mCallback.onDragCancelled(animView);
        Handler handler = getHandler();

        // If we're on the lockscreen we want to false this.
        if (mCallback.isAntiFalsingNeeded()) {
            handler.removeCallbacks(getFalsingCheck());
            handler.postDelayed(getFalsingCheck(), COVER_MENU_DELAY);
        }
    }

    @VisibleForTesting
    protected boolean shouldResetMenu(boolean force) {
        if (mMenuExposedView == null
                || (!force && mMenuExposedView == mTranslatingParentView)) {
            // If no menu is showing or it's showing for this view we do nothing.
            return false;
        }
        return true;
    }

    public void resetExposedMenuView(boolean animate, boolean force) {
        if (!shouldResetMenu(force)) {
            return;
        }
        final View prevMenuExposedView = getExposedMenuView();
        if (animate) {
            Animator anim = getViewTranslationAnimator(prevMenuExposedView,
                    0 /* leftTarget */, null /* updateListener */);
            if (anim != null) {
                anim.start();
            }
        } else if (prevMenuExposedView instanceof ExpandableNotificationRow) {
            ExpandableNotificationRow row = (ExpandableNotificationRow) prevMenuExposedView;
            if (!row.isRemoved()) {
                row.resetTranslation();
            }
        }
        clearExposedMenuView();
    }

    public static boolean isTouchInView(MotionEvent ev, View view) {
        if (view == null) {
            return false;
        }
        final int height = (view instanceof ExpandableView)
                ? ((ExpandableView) view).getActualHeight()
                : view.getHeight();
        final int rx = (int) ev.getRawX();
        final int ry = (int) ev.getRawY();
        int[] temp = new int[2];
        view.getLocationOnScreen(temp);
        final int x = temp[0];
        final int y = temp[1];
        Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
        boolean ret = rect.contains(rx, ry);
        return ret;
    }

    public interface NotificationCallback extends SwipeHelper.Callback{
        boolean isExpanded();

        void handleChildViewDismissed(View view);

        void onSnooze(StatusBarNotification sbn, SnoozeOption snoozeOption);

        void onDismiss();
    }
}
