/*
 * 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.server.notification;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
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.NotificationHistory;
import android.app.NotificationHistory.HistoricalNotification;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Handler;
import android.util.AtomicFile;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.server.UiServiceTestCase;

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

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Set;

@RunWith(AndroidJUnit4.class)
public class NotificationHistoryDatabaseTest extends UiServiceTestCase {

    File mRootDir;
    @Mock
    Handler mFileWriteHandler;
    @Mock
    Context mContext;

    NotificationHistoryDatabase mDataBase;

    private HistoricalNotification getHistoricalNotification(int index) {
        return getHistoricalNotification("package" + index, index);
    }

    private HistoricalNotification getHistoricalNotification(String packageName, int index) {
        String expectedChannelName = "channelName" + index;
        String expectedChannelId = "channelId" + index;
        int expectedUid = 1123456 + index;
        int expectedUserId = 11 + index;
        long expectedPostTime = 987654321 + index;
        String expectedTitle = "title" + index;
        String expectedText = "text" + index;
        Icon expectedIcon = Icon.createWithResource(InstrumentationRegistry.getContext(),
                index);

        return new HistoricalNotification.Builder()
                .setPackage(packageName)
                .setChannelName(expectedChannelName)
                .setChannelId(expectedChannelId)
                .setUid(expectedUid)
                .setUserId(expectedUserId)
                .setPostedTimeMs(expectedPostTime)
                .setTitle(expectedTitle)
                .setText(expectedText)
                .setIcon(expectedIcon)
                .build();
    }

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mContext.getUser()).thenReturn(getContext().getUser());
        when(mContext.getPackageName()).thenReturn(getContext().getPackageName());

        mRootDir = new File(mContext.getFilesDir(), "NotificationHistoryDatabaseTest");

        mDataBase = new NotificationHistoryDatabase(mFileWriteHandler, mRootDir);
        mDataBase.init();
    }

    @Test
    public void testPrune() throws Exception {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTimeInMillis(10);
        int retainDays = 1;

        List<AtomicFile> expectedFiles = new ArrayList<>();

        // add 5 files with a creation date of "today"
        for (long i = cal.getTimeInMillis(); i >= 5; i--) {
            File file = mock(File.class);
            when(file.getName()).thenReturn(String.valueOf(i));
            when(file.getAbsolutePath()).thenReturn(String.valueOf(i));
            AtomicFile af = new AtomicFile(file);
            expectedFiles.add(af);
            mDataBase.mHistoryFiles.addLast(af);
        }

        cal.add(Calendar.DATE, -1 * retainDays);
        // Add 5 more files more than retainDays old
        for (int i = 5; i >= 0; i--) {
            File file = mock(File.class);
            when(file.getName()).thenReturn(String.valueOf(cal.getTimeInMillis() - i));
            when(file.getAbsolutePath()).thenReturn(String.valueOf(cal.getTimeInMillis() - i));
            AtomicFile af = new AtomicFile(file);
            mDataBase.mHistoryFiles.addLast(af);
        }

        // back to today; trim everything a day + old
        cal.add(Calendar.DATE, 1 * retainDays);
        mDataBase.prune(retainDays, cal.getTimeInMillis());

        assertThat(mDataBase.mHistoryFiles).containsExactlyElementsIn(expectedFiles);
    }

    @Test
    public void testPrune_badFileName_noCrash() {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTimeInMillis(10);
        int retainDays = 1;

        List<AtomicFile> expectedFiles = new ArrayList<>();

        // add 5 files with a creation date of "today", but the file names are bad
        for (long i = cal.getTimeInMillis(); i >= 5; i--) {
            File file = mock(File.class);
            when(file.getName()).thenReturn(i + ".bak");
            when(file.getAbsolutePath()).thenReturn(i + ".bak");
            AtomicFile af = new AtomicFile(file);
            mDataBase.mHistoryFiles.addLast(af);
        }

        // trim everything a day+ old
        cal.add(Calendar.DATE, 1 * retainDays);
        mDataBase.prune(retainDays, cal.getTimeInMillis());

        assertThat(mDataBase.mHistoryFiles).containsExactlyElementsIn(expectedFiles);
    }

    @Test
    public void testOnPackageRemove_posts() {
        mDataBase.onPackageRemoved("test");
        verify(mFileWriteHandler, times(1)).post(any());
    }

    @Test
    public void testForceWriteToDisk() {
        mDataBase.forceWriteToDisk();
        verify(mFileWriteHandler, times(1)).post(any());
    }

    @Test
    public void testForceWriteToDisk_bypassesExistingWrites() {
        when(mFileWriteHandler.hasCallbacks(any())).thenReturn(true);
        mDataBase.forceWriteToDisk();
        verify(mFileWriteHandler, times(1)).post(any());
    }

    @Test
    public void testAddNotification() {
        HistoricalNotification n = getHistoricalNotification(1);
        HistoricalNotification n2 = getHistoricalNotification(2);

        mDataBase.addNotification(n);
        assertThat(mDataBase.mBuffer.getNotificationsToWrite()).contains(n);
        verify(mFileWriteHandler, times(1)).postDelayed(any(), anyLong());

        // second add should not trigger another write
        mDataBase.addNotification(n2);
        assertThat(mDataBase.mBuffer.getNotificationsToWrite()).contains(n2);
        verify(mFileWriteHandler, times(1)).postDelayed(any(), anyLong());
    }

    @Test
    public void testAddNotification_newestFirst() {
        HistoricalNotification n = getHistoricalNotification(1);
        HistoricalNotification n2 = getHistoricalNotification(2);

        mDataBase.addNotification(n);

        // second add should not trigger another write
        mDataBase.addNotification(n2);

        assertThat(mDataBase.mBuffer.getNotificationsToWrite().get(0)).isEqualTo(n2);
        assertThat(mDataBase.mBuffer.getNotificationsToWrite().get(1)).isEqualTo(n);
    }

    @Test
    public void testReadNotificationHistory_readsAllFiles() throws Exception {
        for (long i = 10; i >= 5; i--) {
            AtomicFile af = mock(AtomicFile.class);
            mDataBase.mHistoryFiles.addLast(af);
        }

        mDataBase.readNotificationHistory();

        for (AtomicFile file : mDataBase.mHistoryFiles) {
            verify(file, times(1)).openRead();
        }
    }

    @Test
    public void testReadNotificationHistory_readsBuffer() throws Exception {
        HistoricalNotification hn = getHistoricalNotification(1);
        mDataBase.addNotification(hn);

        NotificationHistory nh = mDataBase.readNotificationHistory();

        assertThat(nh.getNotificationsToWrite()).contains(hn);
    }

    @Test
    public void testReadNotificationHistory_withNumFilterDoesNotReadExtraFiles() throws Exception {
        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        AtomicFile af2 = mock(AtomicFile.class);
        when(af2.getBaseFile()).thenReturn(new File(mRootDir, "af2"));
        mDataBase.mHistoryFiles.addLast(af2);

        mDataBase.readNotificationHistory(null, null, 0);

        verify(af, times(1)).openRead();
        verify(af2, never()).openRead();
    }

    @Test
    public void testRemoveNotificationRunnable() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        NotificationHistoryDatabase.RemoveNotificationRunnable rnr =
                mDataBase.new RemoveNotificationRunnable("pkg", 123);
        rnr.setNotificationHistory(nh);

        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        when(nh.removeNotificationFromWrite("pkg", 123)).thenReturn(true);

        mDataBase.mBuffer = mock(NotificationHistory.class);

        rnr.run();

        verify(mDataBase.mBuffer).removeNotificationFromWrite("pkg", 123);
        verify(af).openRead();
        verify(nh).removeNotificationFromWrite("pkg", 123);
        verify(af).startWrite();
    }

    @Test
    public void testRemoveNotificationRunnable_noChanges() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        NotificationHistoryDatabase.RemoveNotificationRunnable rnr =
                mDataBase.new RemoveNotificationRunnable("pkg", 123);
        rnr.setNotificationHistory(nh);

        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        when(nh.removeNotificationFromWrite("pkg", 123)).thenReturn(false);

        mDataBase.mBuffer = mock(NotificationHistory.class);

        rnr.run();

        verify(mDataBase.mBuffer).removeNotificationFromWrite("pkg", 123);
        verify(af).openRead();
        verify(nh).removeNotificationFromWrite("pkg", 123);
        verify(af, never()).startWrite();
    }

    @Test
    public void testRemoveConversationRunnable() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        NotificationHistoryDatabase.RemoveConversationRunnable rcr =
                mDataBase.new RemoveConversationRunnable("pkg", Set.of("convo", "another"));
        rcr.setNotificationHistory(nh);

        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        when(nh.removeConversationsFromWrite("pkg", Set.of("convo", "another"))).thenReturn(true);

        mDataBase.mBuffer = mock(NotificationHistory.class);

        rcr.run();

        verify(mDataBase.mBuffer).removeConversationsFromWrite("pkg",Set.of("convo", "another"));
        verify(af).openRead();
        verify(nh).removeConversationsFromWrite("pkg",Set.of("convo", "another"));
        verify(af).startWrite();
    }

    @Test
    public void testRemoveConversationRunnable_noChanges() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        NotificationHistoryDatabase.RemoveConversationRunnable rcr =
                mDataBase.new RemoveConversationRunnable("pkg", Set.of("convo"));
        rcr.setNotificationHistory(nh);

        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        when(nh.removeConversationsFromWrite("pkg", Set.of("convo"))).thenReturn(false);

        mDataBase.mBuffer = mock(NotificationHistory.class);

        rcr.run();

        verify(mDataBase.mBuffer).removeConversationsFromWrite("pkg", Set.of("convo"));
        verify(af).openRead();
        verify(nh).removeConversationsFromWrite("pkg", Set.of("convo"));
        verify(af, never()).startWrite();
    }

    @Test
    public void testRemoveChannelRunnable() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        NotificationHistoryDatabase.RemoveChannelRunnable rcr =
                mDataBase.new RemoveChannelRunnable("pkg", "channel");
        rcr.setNotificationHistory(nh);

        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        when(nh.removeChannelFromWrite("pkg", "channel")).thenReturn(true);

        mDataBase.mBuffer = mock(NotificationHistory.class);

        rcr.run();

        verify(mDataBase.mBuffer).removeChannelFromWrite("pkg", "channel");
        verify(af).openRead();
        verify(nh).removeChannelFromWrite("pkg", "channel");
        verify(af).startWrite();
    }

    @Test
    public void testRemoveChannelRunnable_noChanges() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        NotificationHistoryDatabase.RemoveChannelRunnable rcr =
                mDataBase.new RemoveChannelRunnable("pkg", "channel");
        rcr.setNotificationHistory(nh);

        AtomicFile af = mock(AtomicFile.class);
        when(af.getBaseFile()).thenReturn(new File(mRootDir, "af"));
        mDataBase.mHistoryFiles.addLast(af);

        when(nh.removeChannelFromWrite("pkg", "channel")).thenReturn(false);

        mDataBase.mBuffer = mock(NotificationHistory.class);

        rcr.run();

        verify(mDataBase.mBuffer).removeChannelFromWrite("pkg", "channel");
        verify(af).openRead();
        verify(nh).removeChannelFromWrite("pkg", "channel");
        verify(af, never()).startWrite();
    }

    @Test
    public void testWriteBufferRunnable() throws Exception {
        NotificationHistory nh = mock(NotificationHistory.class);
        when(nh.getPooledStringsToWrite()).thenReturn(new String[]{});
        when(nh.getNotificationsToWrite()).thenReturn(new ArrayList<>());
        NotificationHistoryDatabase.WriteBufferRunnable wbr =
                mDataBase.new WriteBufferRunnable();

        mDataBase.mBuffer = nh;
        AtomicFile af = mock(AtomicFile.class);
        File file = mock(File.class);
        when(file.getName()).thenReturn("5");
        when(af.getBaseFile()).thenReturn(file);

        wbr.run(af);

        assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(1);
        assertThat(mDataBase.mBuffer).isNotEqualTo(nh);
    }

    @Test
    public void testRemoveFilePathFromHistory_hasMatch() {
        for (int i = 0; i < 5; i++) {
            AtomicFile af = mock(AtomicFile.class);
            when(af.getBaseFile()).thenReturn(new File(mRootDir, "af" + i));
            mDataBase.mHistoryFiles.addLast(af);
        }
        // Baseline size of history files
        assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(5);

        // Remove only file number 3
        String filePathToRemove = new File(mRootDir, "af3").getAbsolutePath();
        mDataBase.removeFilePathFromHistory(filePathToRemove);
        assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(4);
    }

    @Test
    public void testRemoveFilePathFromHistory_noMatch() {
        for (int i = 0; i < 5; i++) {
            AtomicFile af = mock(AtomicFile.class);
            when(af.getBaseFile()).thenReturn(new File(mRootDir, "af" + i));
            mDataBase.mHistoryFiles.addLast(af);
        }
        // Baseline size of history files
        assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(5);

        // Attempt to remove a filename that doesn't exist, expect nothing to break or change
        String filePathToRemove = new File(mRootDir, "af.thisfileisfake").getAbsolutePath();
        mDataBase.removeFilePathFromHistory(filePathToRemove);
        assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(5);
    }
}
