/**
 * 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 android.ext.services.notification;

import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;

import static junit.framework.Assert.assertEquals;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Application;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.content.ContentResolver;
import android.content.Intent;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.Adjustment;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.test.ServiceTestCase;
import android.testing.TestableContext;
import android.util.AtomicFile;

import androidx.test.InstrumentationRegistry;

import com.android.internal.util.FastXmlSerializer;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;

public class AssistantTest extends ServiceTestCase<Assistant> {

    private static final String PKG1 = "pkg1";
    private static final int UID1 = 1;
    private static final NotificationChannel P1C1 =
            new NotificationChannel("one", "", IMPORTANCE_LOW);
    private static final NotificationChannel P1C2 =
            new NotificationChannel("p1c2", "", IMPORTANCE_DEFAULT);
    private static final NotificationChannel P1C3 =
            new NotificationChannel("p1c3", "", IMPORTANCE_MIN);
    private static final String PKG2 = "pkg2";

    private static final int UID2 = 2;
    private static final NotificationChannel P2C1 =
            new NotificationChannel("one", "", IMPORTANCE_LOW);

    @Mock INotificationManager mNoMan;
    @Mock AtomicFile mFile;

    Assistant mAssistant;
    Application mApplication;

    @Rule
    public final TestableContext mContext =
            new TestableContext(InstrumentationRegistry.getContext(), null);

    public AssistantTest() {
        super(Assistant.class);
    }

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        Intent startIntent =
                new Intent("android.service.notification.NotificationAssistantService");
        startIntent.setPackage("android.ext.services");

        // To bypass real calls to global settings values, set the Settings values here.
        Settings.Global.putFloat(mContext.getContentResolver(),
                Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT, 0.8f);
        Settings.Global.putInt(mContext.getContentResolver(),
                Settings.Global.BLOCKING_HELPER_STREAK_LIMIT, 2);
        mApplication = (Application) InstrumentationRegistry.getInstrumentation().
                getTargetContext().getApplicationContext();
        // Force the test to use the correct application instead of trying to use a mock application
        setApplication(mApplication);
        bindService(startIntent);
        mAssistant = getService();
        mAssistant.setNoMan(mNoMan);
        mAssistant.setFile(mFile);
        when(mFile.startWrite()).thenReturn(mock(FileOutputStream.class));
    }

    private StatusBarNotification generateSbn(String pkg, int uid, NotificationChannel channel,
            String tag, String groupKey) {
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setContentTitle("foo")
                .setGroup(groupKey)
                .build();

        StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, 0, tag, uid, uid, n,
                UserHandle.SYSTEM, null, 0);

        return sbn;
    }

    private Ranking generateRanking(StatusBarNotification sbn, NotificationChannel channel) {
        Ranking mockRanking = mock(Ranking.class);
        when(mockRanking.getChannel()).thenReturn(channel);
        when(mockRanking.getImportance()).thenReturn(channel.getImportance());
        when(mockRanking.getKey()).thenReturn(sbn.getKey());
        when(mockRanking.getOverrideGroupKey()).thenReturn(null);
        return mockRanking;
    }

    private void almostBlockChannel(String pkg, int uid, NotificationChannel channel) {
        for (int i = 0; i < ChannelImpressions.DEFAULT_STREAK_LIMIT; i++) {
            dismissBadNotification(pkg, uid, channel, String.valueOf(i));
        }
    }

    private void dismissBadNotification(String pkg, int uid, NotificationChannel channel,
            String tag) {
        StatusBarNotification sbn = generateSbn(pkg, uid, channel, tag, null);
        mAssistant.setFakeRanking(generateRanking(sbn, channel));
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
        mAssistant.setFakeRanking(mock(Ranking.class));
        NotificationStats stats = new NotificationStats();
        stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
        stats.setSeen();
        mAssistant.onNotificationRemoved(
                sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);
    }

    @Test
    public void testNoAdjustmentForInitialPost() throws Exception {
        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, null, null);

        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);
        dismissBadNotification(PKG1, UID1, P1C1, "trigger!");

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        ArgumentCaptor<Adjustment> captor = ArgumentCaptor.forClass(Adjustment.class);
        verify(mNoMan, times(1)).applyAdjustmentFromAssistant(any(), captor.capture());
        assertEquals(sbn.getKey(), captor.getValue().getKey());
        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
                captor.getValue().getSignals().getInt(Adjustment.KEY_USER_SENTIMENT));
    }

    @Test
    public void testMinCannotTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C3);
        dismissBadNotification(PKG1, UID1, P1C3, "trigger!");

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C3, "new one!", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P1C3));
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testGroupChildCanTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", "I HAVE A GROUP");
        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        NotificationStats stats = new NotificationStats();
        stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
        stats.setSeen();
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
        mAssistant.onNotificationRemoved(
                sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);

        sbn = generateSbn(PKG1, UID1, P1C1, "new one!", "group");
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        ArgumentCaptor<Adjustment> captor = ArgumentCaptor.forClass(Adjustment.class);
        verify(mNoMan, times(1)).applyAdjustmentFromAssistant(any(), captor.capture());
        assertEquals(sbn.getKey(), captor.getValue().getKey());
        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
                captor.getValue().getSignals().getInt(Adjustment.KEY_USER_SENTIMENT));
    }

    @Test
    public void testGroupSummaryCannotTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", "I HAVE A GROUP");
        sbn.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        NotificationStats stats = new NotificationStats();
        stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
        stats.setSeen();
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
        mAssistant.onNotificationRemoved(
                sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);

        sbn = generateSbn(PKG1, UID1, P1C1, "new one!", "group");
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testAodCannotTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        NotificationStats stats = new NotificationStats();
        stats.setDismissalSurface(NotificationStats.DISMISSAL_AOD);
        stats.setSeen();
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
        mAssistant.onNotificationRemoved(
                sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);

        sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testInteractedCannotTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);
        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        NotificationStats stats = new NotificationStats();
        stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
        stats.setSeen();
        stats.setExpanded();
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
        mAssistant.onNotificationRemoved(
                sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);

        sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testAppDismissedCannotTriggerAdjustment() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
        NotificationStats stats = new NotificationStats();
        stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
        stats.setSeen();
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
        mAssistant.onNotificationRemoved(
                sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_APP_CANCEL);

        sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testAppSeparation() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);
        dismissBadNotification(PKG1, UID1, P1C1, "trigger!");

        StatusBarNotification sbn = generateSbn(PKG2, UID2, P2C1, "new app!", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P2C1));
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testChannelSeparation() throws Exception {
        almostBlockChannel(PKG1, UID1, P1C1);
        dismissBadNotification(PKG1, UID1, P1C1, "trigger!");

        StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C2, "new app!", null);
        mAssistant.setFakeRanking(generateRanking(sbn, P1C2));
        mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));

        verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
    }

    @Test
    public void testReadXml() throws Exception {
        String key1 = mAssistant.getKey("pkg1", 1, "channel1");
        int streak1 = 2;
        int views1 = 5;
        int dismiss1 = 9;

        int streak1a = 3;
        int views1a = 10;
        int dismiss1a = 99;
        String key1a = mAssistant.getKey("pkg1", 1, "channel1a");

        int streak2 = 7;
        int views2 = 77;
        int dismiss2 = 777;
        String key2 = mAssistant.getKey("pkg2", 2, "channel2");

        String xml = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
                + "<assistant version=\"1\">\n"
                + "<impression-set key=\"" + key1 + "\" "
                + "dismisses=\"" + dismiss1 + "\" views=\"" + views1
                + "\" streak=\"" + streak1 + "\"/>\n"
                + "<impression-set key=\"" + key1a + "\" "
                + "dismisses=\"" + dismiss1a + "\" views=\"" + views1a
                + "\" streak=\"" + streak1a + "\"/>\n"
                + "<impression-set key=\"" + key2 + "\" "
                + "dismisses=\"" + dismiss2 + "\" views=\"" + views2
                + "\" streak=\"" + streak2 + "\"/>\n"
                + "</assistant>\n";
        mAssistant.readXml(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())));

        ChannelImpressions c1 = mAssistant.getImpressions(key1);
        assertEquals(2, c1.getStreak());
        assertEquals(5, c1.getViews());
        assertEquals(9, c1.getDismissals());

        ChannelImpressions c1a = mAssistant.getImpressions(key1a);
        assertEquals(3, c1a.getStreak());
        assertEquals(10, c1a.getViews());
        assertEquals(99, c1a.getDismissals());

        ChannelImpressions c2 = mAssistant.getImpressions(key2);
        assertEquals(7, c2.getStreak());
        assertEquals(77, c2.getViews());
        assertEquals(777, c2.getDismissals());
    }

    @Test
    public void testRoundTripXml() throws Exception {
        String key1 = mAssistant.getKey("pkg1", 1, "channel1");
        ChannelImpressions ci1 = new ChannelImpressions();
        String key2 = mAssistant.getKey("pkg1", 1, "channel2");
        ChannelImpressions ci2 = new ChannelImpressions();
        for (int i = 0; i < 3; i++) {
            ci2.incrementViews();
            ci2.incrementDismissals();
        }
        ChannelImpressions ci3 = new ChannelImpressions();
        String key3 = mAssistant.getKey("pkg3", 3, "channel2");
        for (int i = 0; i < 9; i++) {
            ci3.incrementViews();
            if (i % 3 == 0) {
                ci3.incrementDismissals();
            }
        }

        mAssistant.insertImpressions(key1, ci1);
        mAssistant.insertImpressions(key2, ci2);
        mAssistant.insertImpressions(key3, ci3);

        XmlSerializer serializer = new FastXmlSerializer();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
        mAssistant.writeXml(serializer);

        Assistant assistant = new Assistant();
        assistant.readXml(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())));

        assertEquals(ci1, assistant.getImpressions(key1));
        assertEquals(ci2, assistant.getImpressions(key2));
        assertEquals(ci3, assistant.getImpressions(key3));
    }

    @Test
    public void testSettingsProviderUpdate() {
        ContentResolver resolver = mApplication.getContentResolver();

        // Set up channels
        String key = mAssistant.getKey("pkg1", 1, "channel1");
        ChannelImpressions ci = new ChannelImpressions();
        for (int i = 0; i < 3; i++) {
            ci.incrementViews();
            if (i % 2 == 0) {
                ci.incrementDismissals();
            }
        }

        mAssistant.insertImpressions(key, ci);

        // With default values, the blocking helper shouldn't be triggered.
        assertEquals(false, ci.shouldTriggerBlock());

        // Update settings values.
        float newDismissToViewRatioLimit = 0f;
        int newStreakLimit = 0;
        Settings.Global.putFloat(resolver,
                Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT,
                newDismissToViewRatioLimit);
        Settings.Global.putInt(resolver,
                Settings.Global.BLOCKING_HELPER_STREAK_LIMIT, newStreakLimit);

        // Notify for the settings values we updated.
        resolver.notifyChange(
                Settings.Global.getUriFor(Settings.Global.BLOCKING_HELPER_STREAK_LIMIT), null);
        resolver.notifyChange(
                Settings.Global.getUriFor(
                        Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT),
                null);

        // With the new threshold, the blocking helper should be triggered.
        assertEquals(true, ci.shouldTriggerBlock());
    }
}
