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

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.app.Notification;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.metrics.LogMaker;
import android.os.UserHandle;

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

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

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

@RunWith(AndroidJUnit4.class)
@SmallTest
public class StatusBarNotificationTest {

    private final Context mMockContext = mock(Context.class);
    @Mock
    private PackageManager mPm;

    private static final String PKG = "com.example.o";
    private static final int UID = 9583;
    private static final int ID = 1;
    private static final String TAG = "tag1";
    private static final String CHANNEL_ID = "channel";
    private static final String CHANNEL_ID_LONG =
            "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there";
    private static final String GROUP_ID_1 = "group1";
    private static final String GROUP_ID_2 = "group2";
    private static final String GROUP_ID_LONG =
            "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/";
    private static final android.os.UserHandle USER =
            UserHandle.of(ActivityManager.getCurrentUser());

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

        when(mMockContext.getResources()).thenReturn(
                InstrumentationRegistry.getContext().getResources());
        when(mMockContext.getPackageManager()).thenReturn(mPm);
        when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
    }

    @Test
    public void testLogMaker() {
        final LogMaker logMaker = getNotification(PKG, GROUP_ID_1, CHANNEL_ID).getLogMaker();
        assertEquals(CHANNEL_ID,
                (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID));
        assertEquals(PKG, logMaker.getPackageName());
        assertEquals(ID, logMaker.getTaggedData(MetricsEvent.NOTIFICATION_ID));
        assertEquals(TAG, logMaker.getTaggedData(MetricsEvent.NOTIFICATION_TAG));
        assertEquals(GROUP_ID_1,
                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
        assertEquals(0,
                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY));
        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CATEGORY));
    }

    @Test
    public void testLogMakerWithCategory() {
        Notification.Builder builder = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID)
                        .setCategory(Notification.CATEGORY_MESSAGE);
        final LogMaker logMaker = getNotification(PKG, builder).getLogMaker();
        assertEquals(Notification.CATEGORY_MESSAGE,
                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CATEGORY));
    }

    @Test
    public void testLogMakerNoChannel() {
        final LogMaker logMaker = getNotification(PKG, GROUP_ID_1, null).getLogMaker();

        assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID));
    }

    @Test
    public void testLogMakerLongChannel() {
        final LogMaker logMaker = getNotification(PKG, null, CHANNEL_ID_LONG).getLogMaker();
        final String loggedId = (String) logMaker
                .getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID);
        assertEquals(StatusBarNotification.MAX_LOG_TAG_LENGTH, loggedId.length());
        assertEquals(CHANNEL_ID_LONG.substring(0, 10), loggedId.substring(0, 10));
    }

    @Test
    public void testLogMakerNoGroup() {
        final LogMaker logMaker = getNotification(PKG, null, CHANNEL_ID).getLogMaker();

        assertNull(
                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
    }

    @Test
    public void testLogMakerLongGroup() {
        final LogMaker logMaker = getNotification(PKG, GROUP_ID_LONG, CHANNEL_ID)
                .getLogMaker();

        final String loggedId = (String)
                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID);
        assertEquals(StatusBarNotification.MAX_LOG_TAG_LENGTH, loggedId.length());
        assertEquals(GROUP_ID_LONG.substring(0, 10), loggedId.substring(0, 10));
    }

    @Test
    public void testLogMakerOverrideGroup() {
        StatusBarNotification sbn = getNotification(PKG, GROUP_ID_1, CHANNEL_ID);
        assertEquals(GROUP_ID_1,
                sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));

        sbn.setOverrideGroupKey(GROUP_ID_2);
        assertEquals(GROUP_ID_2,
                sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));

        sbn.setOverrideGroupKey(null);
        assertEquals(GROUP_ID_1,
                sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
    }

    private StatusBarNotification getNotification(String pkg, String group, String channelId) {
        return getNotification(pkg, getNotificationBuilder(group, channelId));
    }

    private Notification.Builder getNotificationBuilder(String group, String channelId) {
        final Notification.Builder builder = new Notification.Builder(mMockContext, channelId)
                .setContentTitle("foo")
                .setSmallIcon(android.R.drawable.sym_def_app_icon);

        if (group != null) {
            builder.setGroup(group);
        }
        return builder;
    }

    private StatusBarNotification getNotification(String pkg, Notification.Builder builder) {

        return new StatusBarNotification(
                pkg, pkg, ID, TAG, UID, UID, builder.build(), USER, null, UID);
    }

}
