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

import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;

import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
import android.view.View;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;

import javax.inject.Inject;
import javax.inject.Named;

/** A controller to control all auto-hide things. */
public class AutoHideController implements CommandQueue.Callbacks {
    private static final String TAG = "AutoHideController";

    private final IWindowManager mWindowManagerService;

    private final Handler mHandler;
    private final NotificationRemoteInputManager mRemoteInputManager;
    private final CommandQueue mCommandQueue;
    private StatusBar mStatusBar;
    private NavigationBarFragment mNavigationBar;

    @VisibleForTesting
    int mDisplayId;
    @VisibleForTesting
    int mSystemUiVisibility;
    // last value sent to window manager
    private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;

    private boolean mAutoHideSuspended;

    private static final long AUTOHIDE_TIMEOUT_MS = 2250;

    private final Runnable mAutoHide = () -> {
        int requested = mSystemUiVisibility & ~getTransientMask();
        if (mSystemUiVisibility != requested) {
            notifySystemUiVisibilityChanged(requested);
        }
    };

    @Inject
    public AutoHideController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
        mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
        mCommandQueue.addCallback(this);
        mHandler = handler;
        mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
        mWindowManagerService = Dependency.get(IWindowManager.class);

        mDisplayId = context.getDisplayId();
    }

    @Override
    public void onDisplayRemoved(int displayId) {
        if (displayId == mDisplayId) {
            mCommandQueue.removeCallback(this);
        }
    }

    void setStatusBar(StatusBar statusBar) {
        mStatusBar = statusBar;
    }

    void setNavigationBar(NavigationBarFragment navigationBar) {
        mNavigationBar = navigationBar;
    }

    @Override
    public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
            int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
            boolean navbarColorManagedByIme) {
        if (displayId != mDisplayId) {
            return;
        }
        int oldVal = mSystemUiVisibility;
        int newVal = (oldVal & ~mask) | (vis & mask);
        int diff = newVal ^ oldVal;

        if (diff != 0) {
            mSystemUiVisibility = newVal;

            // ready to unhide
            if (hasStatusBar() && (vis & View.STATUS_BAR_UNHIDE) != 0) {
                mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
            }

            if (hasNavigationBar() && (vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
                mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
            }

            // Re-send setSystemUiVisibility to update un-hide status.
            if (mSystemUiVisibility != newVal) {
                mCommandQueue.setSystemUiVisibility(mDisplayId, mSystemUiVisibility,
                        fullscreenStackVis, dockedStackVis, mask, fullscreenStackBounds,
                        dockedStackBounds, navbarColorManagedByIme);
            }

            notifySystemUiVisibilityChanged(mSystemUiVisibility);
        }
    }

    @VisibleForTesting
    void notifySystemUiVisibilityChanged(int vis) {
        try {
            if (mLastDispatchedSystemUiVisibility != vis) {
                mWindowManagerService.statusBarVisibilityChanged(mDisplayId, vis);
                mLastDispatchedSystemUiVisibility = vis;
            }
        } catch (RemoteException ex) {
            Log.w(TAG, "Cannot get WindowManager");
        }
    }

    void resumeSuspendedAutoHide() {
        if (mAutoHideSuspended) {
            scheduleAutoHide();
            Runnable checkBarModesRunnable = getCheckBarModesRunnable();
            if (checkBarModesRunnable != null) {
                mHandler.postDelayed(checkBarModesRunnable, 500); // longer than home -> launcher
            }
        }
    }

    void suspendAutoHide() {
        mHandler.removeCallbacks(mAutoHide);
        Runnable checkBarModesRunnable = getCheckBarModesRunnable();
        if (checkBarModesRunnable != null) {
            mHandler.removeCallbacks(checkBarModesRunnable);
        }
        mAutoHideSuspended = (mSystemUiVisibility & getTransientMask()) != 0;
    }

    void touchAutoHide() {
        // update transient bar auto hide
        if ((hasStatusBar() && mStatusBar.getStatusBarMode() == MODE_SEMI_TRANSPARENT)
                || hasNavigationBar() && mNavigationBar.isSemiTransparent()) {
            scheduleAutoHide();
        } else {
            cancelAutoHide();
        }
    }

    private Runnable getCheckBarModesRunnable() {
        if (hasStatusBar()) {
            return () -> mStatusBar.checkBarModes();
        } else if (hasNavigationBar()) {
            return () -> mNavigationBar.checkNavBarModes();
        } else {
            return null;
        }
    }

    private void cancelAutoHide() {
        mAutoHideSuspended = false;
        mHandler.removeCallbacks(mAutoHide);
    }

    private void scheduleAutoHide() {
        cancelAutoHide();
        mHandler.postDelayed(mAutoHide, AUTOHIDE_TIMEOUT_MS);
    }

    void checkUserAutoHide(MotionEvent event) {
        boolean shouldAutoHide =
                (mSystemUiVisibility & getTransientMask()) != 0  // a transient bar is revealed.
                && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
                && event.getX() == 0 && event.getY() == 0;
        if (hasStatusBar()) {
            // a touch outside both bars
            shouldAutoHide &= !mRemoteInputManager.getController().isRemoteInputActive();
        }
        if (shouldAutoHide) {
            userAutoHide();
        }
    }

    private void userAutoHide() {
        cancelAutoHide();
        mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
    }

    private int getTransientMask() {
        int mask = 0;
        if (hasStatusBar()) {
            mask |= View.STATUS_BAR_TRANSIENT;
        }
        if (hasNavigationBar()) {
            mask |= View.NAVIGATION_BAR_TRANSIENT;
        }
        return mask;
    }

    boolean hasNavigationBar() {
        return mNavigationBar != null;
    }

    @VisibleForTesting
    boolean hasStatusBar() {
        return mStatusBar != null;
    }
}
