/*
 * Copyright (C) 2017 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;

import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import androidx.test.filters.SmallTest;

import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.util.Assert;

import com.google.android.collect.Lists;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import java.util.List;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
    @Mock private NotificationPresenter mPresenter;
    @Mock private NotificationData mNotificationData;
    @Spy private FakeListContainer mListContainer = new FakeListContainer();

    // Dependency mocks:
    @Mock private NotificationEntryManager mEntryManager;
    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
    @Mock private NotificationGroupManager mGroupManager;
    @Mock private VisualStabilityManager mVisualStabilityManager;
    @Mock private ShadeController mShadeController;

    private TestableLooper mTestableLooper;
    private Handler mHandler;
    private NotificationViewHierarchyManager mViewHierarchyManager;
    private NotificationTestHelper mHelper;
    private boolean mMadeReentrantCall = false;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mTestableLooper = TestableLooper.get(this);
        Assert.sMainLooper = mTestableLooper.getLooper();
        mHandler = Handler.createAsync(mTestableLooper.getLooper());

        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
        mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
                mLockscreenUserManager);
        mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager);
        mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
        mDependency.injectTestDependency(ShadeController.class, mShadeController);

        mHelper = new NotificationTestHelper(mContext);

        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);

        mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
                mHandler, mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
                mock(StatusBarStateControllerImpl.class), mEntryManager,
                () -> mShadeController,
                mock(KeyguardBypassController.class),
                mock(BubbleController.class),
                mock(DynamicPrivacyController.class));
        Dependency.get(InitController.class).executePostInitTasks();
        mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
    }

    private NotificationEntry createEntry() throws Exception {
        ExpandableNotificationRow row = mHelper.createRow();
        NotificationEntry entry = new NotificationEntry(row.getStatusBarNotification());
        entry.setRow(row);
        return entry;
    }

    @Test
    public void testNotificationsBecomingBundled() throws Exception {
        // Tests 3 top level notifications becoming a single bundled notification with |entry0| as
        // the summary.
        NotificationEntry entry0 = createEntry();
        NotificationEntry entry1 = createEntry();
        NotificationEntry entry2 = createEntry();

        // Set up the prior state to look like three top level notifications.
        mListContainer.addContainerView(entry0.getRow());
        mListContainer.addContainerView(entry1.getRow());
        mListContainer.addContainerView(entry2.getRow());
        when(mNotificationData.getActiveNotifications()).thenReturn(
                Lists.newArrayList(entry0, entry1, entry2));

        // Set up group manager to report that they should be bundled now.
        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(true);
        when(mGroupManager.isChildInGroupWithSummary(entry2.notification)).thenReturn(true);
        when(mGroupManager.getGroupSummary(entry1.notification)).thenReturn(entry0);
        when(mGroupManager.getGroupSummary(entry2.notification)).thenReturn(entry0);

        // Run updateNotifications - the view hierarchy should be reorganized.
        mViewHierarchyManager.updateNotificationViews();

        verify(mListContainer).notifyGroupChildAdded(entry1.getRow());
        verify(mListContainer).notifyGroupChildAdded(entry2.getRow());
        assertTrue(Lists.newArrayList(entry0.getRow()).equals(mListContainer.mRows));
    }

    @Test
    public void testNotificationsBecomingUnbundled() throws Exception {
        // Tests a bundled notification becoming three top level notifications.
        NotificationEntry entry0 = createEntry();
        NotificationEntry entry1 = createEntry();
        NotificationEntry entry2 = createEntry();
        entry0.getRow().addChildNotification(entry1.getRow());
        entry0.getRow().addChildNotification(entry2.getRow());

        // Set up the prior state to look like one top level notification.
        mListContainer.addContainerView(entry0.getRow());
        when(mNotificationData.getActiveNotifications()).thenReturn(
                Lists.newArrayList(entry0, entry1, entry2));

        // Set up group manager to report that they should not be bundled now.
        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(false);
        when(mGroupManager.isChildInGroupWithSummary(entry2.notification)).thenReturn(false);

        // Run updateNotifications - the view hierarchy should be reorganized.
        mViewHierarchyManager.updateNotificationViews();

        verify(mListContainer).notifyGroupChildRemoved(
                entry1.getRow(), entry0.getRow().getChildrenContainer());
        verify(mListContainer).notifyGroupChildRemoved(
                entry2.getRow(), entry0.getRow().getChildrenContainer());
        assertTrue(
                Lists.newArrayList(entry0.getRow(), entry1.getRow(), entry2.getRow())
                        .equals(mListContainer.mRows));
    }

    @Test
    public void testNotificationsBecomingSuppressed() throws Exception {
        // Tests two top level notifications becoming a suppressed summary and a child.
        NotificationEntry entry0 = createEntry();
        NotificationEntry entry1 = createEntry();
        entry0.getRow().addChildNotification(entry1.getRow());

        // Set up the prior state to look like a top level notification.
        mListContainer.addContainerView(entry0.getRow());
        when(mNotificationData.getActiveNotifications()).thenReturn(
                Lists.newArrayList(entry0, entry1));

        // Set up group manager to report a suppressed summary now.
        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(false);
        when(mGroupManager.isSummaryOfSuppressedGroup(entry0.notification)).thenReturn(true);

        // Run updateNotifications - the view hierarchy should be reorganized.
        mViewHierarchyManager.updateNotificationViews();

        verify(mListContainer).notifyGroupChildRemoved(
                entry1.getRow(), entry0.getRow().getChildrenContainer());
        assertTrue(Lists.newArrayList(entry0.getRow(), entry1.getRow()).equals(mListContainer.mRows));
        assertEquals(View.GONE, entry0.getRow().getVisibility());
        assertEquals(View.VISIBLE, entry1.getRow().getVisibility());
    }

    @Test
    public void testUpdateNotificationViews_appOps() throws Exception {
        NotificationEntry entry0 = createEntry();
        entry0.setRow(spy(entry0.getRow()));
        when(mNotificationData.getActiveNotifications()).thenReturn(
                Lists.newArrayList(entry0));
        mListContainer.addContainerView(entry0.getRow());

        mViewHierarchyManager.updateNotificationViews();

        verify(entry0.getRow(), times(1)).showAppOpsIcons(any());
    }

    @Test
    public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() {
        // GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews()
        mMadeReentrantCall = false;
        doAnswer((invocation) -> {
            if (!mMadeReentrantCall) {
                mMadeReentrantCall = true;
                mViewHierarchyManager.onDynamicPrivacyChanged();
            }
            return null;
        }).when(mListContainer).setMaxDisplayedNotifications(anyInt());

        // WHEN we call updateNotificationViews()
        mViewHierarchyManager.updateNotificationViews();

        // THEN onNotificationViewUpdateFinished() is only called once
        verify(mListContainer).onNotificationViewUpdateFinished();

        // WHEN we drain the looper
        mTestableLooper.processAllMessages();

        // THEN updateNotificationViews() is called a second time (for the reentrant call)
        verify(mListContainer, times(2)).onNotificationViewUpdateFinished();
    }

    @Test
    public void testMultipleReentrantCallsToOnDynamicPrivacyChangedOnlyPostOnce() {
        // GIVEN a ListContainer that will make many re-entrant calls to updateNotificationViews()
        mMadeReentrantCall = false;
        doAnswer((invocation) -> {
            if (!mMadeReentrantCall) {
                mMadeReentrantCall = true;
                mViewHierarchyManager.onDynamicPrivacyChanged();
                mViewHierarchyManager.onDynamicPrivacyChanged();
                mViewHierarchyManager.onDynamicPrivacyChanged();
                mViewHierarchyManager.onDynamicPrivacyChanged();
            }
            return null;
        }).when(mListContainer).setMaxDisplayedNotifications(anyInt());

        // WHEN we call updateNotificationViews() and drain the looper
        mViewHierarchyManager.updateNotificationViews();
        verify(mListContainer).onNotificationViewUpdateFinished();
        clearInvocations(mListContainer);
        mTestableLooper.processAllMessages();

        // THEN updateNotificationViews() is called only one more time
        verify(mListContainer).onNotificationViewUpdateFinished();
    }

    private class FakeListContainer implements NotificationListContainer {
        final LinearLayout mLayout = new LinearLayout(mContext);
        final List<View> mRows = Lists.newArrayList();
        private boolean mMakeReentrantCallDuringSetMaxDisplayedNotifications;

        @Override
        public void setChildTransferInProgress(boolean childTransferInProgress) {}

        @Override
        public void changeViewPosition(ExpandableView child, int newIndex) {
            mRows.remove(child);
            mRows.add(newIndex, child);
        }

        @Override
        public void notifyGroupChildAdded(ExpandableView row) {}

        @Override
        public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {}

        @Override
        public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {}

        @Override
        public void generateChildOrderChangedEvent() {}

        @Override
        public void onReset(ExpandableView view) {}

        @Override
        public int getContainerChildCount() {
            return mRows.size();
        }

        @Override
        public View getContainerChildAt(int i) {
            return mRows.get(i);
        }

        @Override
        public void removeContainerView(View v) {
            mLayout.removeView(v);
            mRows.remove(v);
        }

        @Override
        public void addContainerView(View v) {
            mLayout.addView(v);
            mRows.add(v);
        }

        @Override
        public void setMaxDisplayedNotifications(int maxNotifications) {
            if (mMakeReentrantCallDuringSetMaxDisplayedNotifications) {
                mViewHierarchyManager.onDynamicPrivacyChanged();
            }
        }

        @Override
        public ViewGroup getViewParentForNotification(NotificationEntry entry) {
            return null;
        }

        @Override
        public void onHeightChanged(ExpandableView view, boolean animate) {}

        @Override
        public void resetExposedMenuView(boolean animate, boolean force) {}

        @Override
        public NotificationSwipeActionHelper getSwipeActionHelper() {
            return null;
        }

        @Override
        public void cleanUpViewStateForEntry(NotificationEntry entry) { }

        @Override
        public boolean isInVisibleLocation(NotificationEntry entry) {
            return true;
        }

        @Override
        public void setChildLocationsChangedListener(
                NotificationLogger.OnChildLocationsChangedListener listener) {}

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

        @Override
        public void onNotificationViewUpdateFinished() { }
    }
}
