/*
 * Copyright (C) 2021 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.car.telemetry.publisher;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;

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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

import static java.util.concurrent.TimeUnit.MICROSECONDS;

import android.car.test.mocks.AbstractExtendedMockitoTestCase;
import android.content.Context;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
import android.net.NetworkStats;
import android.os.IBinder;
import android.os.Looper;
import android.os.ServiceManager;
import android.os.SystemClock;

import com.android.car.telemetry.TelemetryProto;
import com.android.car.telemetry.TelemetryProto.ConnectivityPublisher.OemType;
import com.android.car.telemetry.TelemetryProto.ConnectivityPublisher.Transport;
import com.android.car.telemetry.databroker.DataBroker;
import com.android.car.telemetry.databroker.DataSubscriber;
import com.android.car.test.FakeHandlerWrapper;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.List;

@RunWith(MockitoJUnitRunner.class)
public class ConnectivityPublisherTest extends AbstractExtendedMockitoTestCase {
    private static final TelemetryProto.Publisher PUBLISHER_PARAMS_WIFI =
            TelemetryProto.Publisher.newBuilder()
                    .setConnectivity(
                            TelemetryProto.ConnectivityPublisher.newBuilder()
                                    .setTransport(Transport.TRANSPORT_WIFI)
                                    .setOemType(OemType.OEM_NONE))
                    .build();
    private static final TelemetryProto.Publisher PUBLISHER_PARAMS_CELL =
            TelemetryProto.Publisher.newBuilder()
                    .setConnectivity(
                            TelemetryProto.ConnectivityPublisher.newBuilder()
                                    .setTransport(Transport.TRANSPORT_CELLULAR)
                                    .setOemType(OemType.OEM_MANAGED))
                    .build();
    private static final TelemetryProto.Subscriber SUBSCRIBER_WIFI =
            TelemetryProto.Subscriber.newBuilder()
                    .setHandler("handler_fn_wifi")
                    .setPublisher(PUBLISHER_PARAMS_WIFI)
                    .build();
    private static final TelemetryProto.Subscriber SUBSCRIBER_CELL =
            TelemetryProto.Subscriber.newBuilder()
                    .setHandler("handler_fn_2")
                    .setPublisher(PUBLISHER_PARAMS_CELL)
                    .build();
    private static final TelemetryProto.MetricsConfig METRICS_CONFIG =
            TelemetryProto.MetricsConfig.newBuilder()
                    .setName("myconfig")
                    .setVersion(1)
                    .addSubscribers(SUBSCRIBER_WIFI)
                    .addSubscribers(SUBSCRIBER_CELL)
                    .build();

    /** See {@code ConnectivityPublisher#pullInitialNetstats()}. */
    private static final int BASELINE_PULL_COUNT = 8;

    private final NetworkStats mNetworkStatsEmpty =
            new NetworkStats(/* elapsedRealtime= */ 0, /* initialSize= */ 0);

    @Mock private IBinder mMockBinder;
    @Mock private Context mMockContext;
    @Mock private INetworkStatsService mMockNetworkStatsService;
    @Mock private INetworkStatsSession mMockNetworkStatsSession;
    @Mock private DataBroker mMockDataBroker;

    private final FakeHandlerWrapper mFakeHandlerWrapper =
            new FakeHandlerWrapper(Looper.getMainLooper(), FakeHandlerWrapper.Mode.QUEUEING);

    private ConnectivityPublisher mPublisher; // subject

    private DataSubscriber mDataSubscriberWifi;
    private DataSubscriber mDataSubscriberCell;

    @Override
    protected void onSessionBuilder(CustomMockitoSessionBuilder builder) {
        builder.spyStatic(ServiceManager.class);
    }

    @Before
    public void setUp() throws Exception {
        mPublisher = createRestartedPublisher();
        when(mMockBinder.queryLocalInterface(anyString())).thenReturn(mMockNetworkStatsService);
        doReturn(mMockBinder).when(() -> ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
        when(mMockNetworkStatsService.openSessionForUsageStats(anyInt(), any()))
                .thenReturn(mMockNetworkStatsSession);
        mDataSubscriberWifi = new DataSubscriber(mMockDataBroker, METRICS_CONFIG, SUBSCRIBER_WIFI);
        mDataSubscriberCell = new DataSubscriber(mMockDataBroker, METRICS_CONFIG, SUBSCRIBER_CELL);
    }

    /** Emulates a restart by creating a new ConnectivityPublisher. */
    private ConnectivityPublisher createRestartedPublisher() throws Exception {
        return new ConnectivityPublisher(
                this::onPublisherFailure,
                mMockNetworkStatsService,
                mFakeHandlerWrapper.getMockHandler(),
                mMockContext);
    }

    @Test
    public void testAddDataSubscriber_storesIt_andStartsPeriodicPull() throws Exception {
        mPublisher.addDataSubscriber(mDataSubscriberWifi);

        assertThat(mPublisher.hasDataSubscriber(mDataSubscriberWifi)).isTrue();
        // One for initial pull, second one for this addDataSubscriber.
        assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(2);
    }

    @Test
    public void testRemoveDataSubscriber_removesIt() throws Exception {
        mPublisher.addDataSubscriber(mDataSubscriberWifi);

        mPublisher.removeDataSubscriber(mDataSubscriberWifi);

        assertThat(mPublisher.hasDataSubscriber(mDataSubscriberWifi)).isFalse();
        // Only initial pull left, because we removed the last subscriber.
        assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(1);
    }

    @Test
    public void testRemoveDataSubscriber_givenWrongSubscriber_doesNothing() throws Exception {
        mPublisher.addDataSubscriber(mDataSubscriberWifi);

        mPublisher.removeDataSubscriber(mDataSubscriberCell);

        assertThat(mPublisher.hasDataSubscriber(mDataSubscriberWifi)).isTrue();
        // One for initial pull, second one for this addDataSubscriber.
        assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(2);
    }

    @Test
    public void testRemoveAllDataSubscribers_removesAll_andStopsPeriodicPull() throws Exception {
        mPublisher.addDataSubscriber(mDataSubscriberWifi);
        mPublisher.addDataSubscriber(mDataSubscriberCell);

        mPublisher.removeAllDataSubscribers();

        assertThat(mPublisher.hasDataSubscriber(mDataSubscriberWifi)).isFalse();
        // Only initial pull left, because we removed the subscribers.
        assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(1);
    }

    @Test
    public void testPullsFromNetworkStatsService() throws Exception {
        when(mMockNetworkStatsSession.getSummaryForAllUid(
                        any(), anyLong(), anyLong(), anyBoolean()))
                .thenReturn(mNetworkStatsEmpty);
        mPublisher.addDataSubscriber(mDataSubscriberWifi);

        mFakeHandlerWrapper.dispatchQueuedMessages();

        verify(mMockNetworkStatsService, times(BASELINE_PULL_COUNT + 1))
                .openSessionForUsageStats(anyInt(), any());
        ArgumentCaptor<Long> startCaptor = ArgumentCaptor.forClass(Long.class);
        verify(mMockNetworkStatsSession, times(BASELINE_PULL_COUNT + 1))
                .getSummaryForAllUid(any(), startCaptor.capture(), anyLong(), anyBoolean());
        final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); // including sleep
        final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
        // Make sure that "start" time is earlier than the boot time.
        assertThat(startCaptor.getValue()).isLessThan(currentTimeInMillis - elapsedMillisSinceBoot);
    }

    @Test
    public void testSchedulesNextPeriodicPullInHandler() throws Exception {
        when(mMockNetworkStatsSession.getSummaryForAllUid(
                        any(), anyLong(), anyLong(), anyBoolean()))
                .thenReturn(mNetworkStatsEmpty);
        mPublisher.addDataSubscriber(mDataSubscriberWifi);

        mFakeHandlerWrapper.dispatchQueuedMessages(); // Current pull.

        assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(1); // Next pull.
    }

    private void onPublisherFailure(
            AbstractPublisher publisher,
            List<TelemetryProto.MetricsConfig> affectedConfigs,
            Throwable error) {}
}
