// Copyright 2018 The Feed Authors.
//
// 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.google.android.libraries.feed.mocknetworkclient;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import com.google.android.libraries.feed.common.Result;
import com.google.android.libraries.feed.common.concurrent.MainThreadRunner;
import com.google.android.libraries.feed.common.concurrent.testing.FakeMainThreadRunner;
import com.google.android.libraries.feed.common.concurrent.testing.FakeTaskQueue;
import com.google.android.libraries.feed.common.concurrent.testing.FakeThreadUtils;
import com.google.android.libraries.feed.common.functional.Consumer;
import com.google.android.libraries.feed.common.protoextensions.FeedExtensionRegistry;
import com.google.android.libraries.feed.common.time.TimingUtils;
import com.google.android.libraries.feed.common.time.testing.FakeClock;
import com.google.android.libraries.feed.feedrequestmanager.FeedRequestManager;
import com.google.android.libraries.feed.host.config.ApplicationInfo;
import com.google.android.libraries.feed.host.config.Configuration;
import com.google.android.libraries.feed.host.network.HttpRequest;
import com.google.android.libraries.feed.host.network.HttpRequest.HttpMethod;
import com.google.android.libraries.feed.host.network.HttpResponse;
import com.google.android.libraries.feed.host.scheduler.SchedulerApi;
import com.google.android.libraries.feed.host.stream.TooltipSupportedApi;
import com.google.android.libraries.feed.internalapi.actionmanager.ActionReader;
import com.google.android.libraries.feed.internalapi.protocoladapter.ProtocolAdapter;
import com.google.android.libraries.feed.testing.conformance.network.NetworkClientConformanceTest;
import com.google.android.libraries.feed.testing.host.logging.FakeBasicLoggingApi;
import com.google.common.truth.extensions.proto.LiteProtoTruth;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.search.now.feed.client.StreamDataProto.StreamToken;
import com.google.search.now.wire.feed.ConsistencyTokenProto.ConsistencyToken;
import com.google.search.now.wire.feed.ResponseProto.Response;
import com.google.search.now.wire.feed.ResponseProto.Response.ResponseVersion;
import com.google.search.now.wire.feed.mockserver.MockServerProto.ConditionalResponse;
import com.google.search.now.wire.feed.mockserver.MockServerProto.MockServer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;

/** Tests of the {@link MockServerNetworkClient} class. */
@RunWith(RobolectricTestRunner.class)
public class MockServerNetworkClientTest extends NetworkClientConformanceTest {
  private final Configuration configuration = new Configuration.Builder().build();
  private final FakeClock fakeClock = new FakeClock();
  private final FakeThreadUtils fakeThreadUtils = FakeThreadUtils.withThreadChecks();
  private final FeedExtensionRegistry extensionRegistry = new FeedExtensionRegistry(ArrayList::new);
  private final TimingUtils timingUtils = new TimingUtils();

  @Mock private ActionReader actionReader;
  @Mock private ProtocolAdapter protocolAdapter;
  @Mock private SchedulerApi scheduler;
  @Mock private TooltipSupportedApi tooltipSupportedApi;
  @Captor private ArgumentCaptor<Response> responseCaptor;
  private ApplicationInfo applicationInfo;
  private Context context;
  private FakeBasicLoggingApi basicLoggingApi;
  private MainThreadRunner mainThreadRunner;

  @Override
  protected Uri getValidUri(@HttpMethod String method) {
    // The URI does not matter - mockNetworkClient will default to an empty response
    return new Uri.Builder().path("foo").appendPath(method).build();
  }

  @Before
  public void setUp() throws Exception {
    initMocks(this);
    context = Robolectric.buildActivity(Activity.class).get();
    applicationInfo = new ApplicationInfo.Builder(context).setVersionString("0").build();
    mainThreadRunner = FakeMainThreadRunner.runTasksImmediately();

    MockServer mockServer = MockServer.getDefaultInstance();
    networkClient = new MockServerNetworkClient(context, mockServer, /* responseDelayMillis= */ 0L);

    when(actionReader.getDismissActionsWithSemanticProperties())
        .thenReturn(Result.success(Collections.emptyList()));

    basicLoggingApi = new FakeBasicLoggingApi();
  }

  @Test
  public void testSend() {
    MockServer.Builder mockServerBuilder = MockServer.newBuilder();
    Response initialResponse =
        Response.newBuilder().setResponseVersion(ResponseVersion.FEED_RESPONSE).build();
    mockServerBuilder.setInitialResponse(initialResponse);
    MockServerNetworkClient networkClient =
        new MockServerNetworkClient(
            context, mockServerBuilder.build(), /* responseDelayMillis= */ 0L);
    Consumer<HttpResponse> responseConsumer =
        input -> {
          try {
            CodedInputStream inputStream = CodedInputStream.newInstance(input.getResponseBody());
            int length = inputStream.readRawVarint32();
            assertThat(inputStream.readRawBytes(length)).isEqualTo(initialResponse.toByteArray());
            assertThat(input.getResponseCode()).isEqualTo(200);
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        };
    networkClient.send(
        new HttpRequest(Uri.EMPTY, HttpMethod.POST, Collections.emptyList(), new byte[] {}),
        responseConsumer);
  }

  @Test
  public void testSend_oneTimeResponse() {
    MockServer.Builder mockServerBuilder = MockServer.newBuilder();
    Response initialResponse =
        Response.newBuilder().setResponseVersion(ResponseVersion.FEED_RESPONSE).build();
    mockServerBuilder.setInitialResponse(initialResponse);
    MockServerNetworkClient networkClient =
        new MockServerNetworkClient(
            context, mockServerBuilder.build(), /* responseDelayMillis= */ 0L);
    Consumer<HttpResponse> responseConsumer =
        input -> {
          try {
            CodedInputStream inputStream = CodedInputStream.newInstance(input.getResponseBody());
            int length = inputStream.readRawVarint32();
            assertThat(inputStream.readRawBytes(length)).isEqualTo(initialResponse.toByteArray());
            assertThat(input.getResponseCode()).isEqualTo(200);
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        };
    networkClient.send(
        new HttpRequest(Uri.EMPTY, HttpMethod.POST, Collections.emptyList(), new byte[] {}),
        responseConsumer);
  }

  @Test
  public void testPaging() {
    MockServer.Builder mockServerBuilder = MockServer.newBuilder();
    Response response =
        Response.newBuilder().setResponseVersion(ResponseVersion.FEED_RESPONSE).build();
    ByteString token = ByteString.copyFromUtf8("fooToken");
    StreamToken streamToken = StreamToken.newBuilder().setNextPageToken(token).build();
    ConditionalResponse.Builder conditionalResponseBuilder = ConditionalResponse.newBuilder();
    conditionalResponseBuilder.setContinuationToken(token).setResponse(response);
    mockServerBuilder.addConditionalResponses(conditionalResponseBuilder.build());
    MockServerNetworkClient networkClient =
        new MockServerNetworkClient(
            context, mockServerBuilder.build(), /* responseDelayMillis= */ 0L);
    FeedRequestManager feedRequestManager =
        new FeedRequestManager(
            configuration,
            networkClient,
            protocolAdapter,
            extensionRegistry,
            scheduler,
            getTaskQueue(),
            timingUtils,
            fakeThreadUtils,
            actionReader,
            context,
            applicationInfo,
            mainThreadRunner,
            basicLoggingApi,
            tooltipSupportedApi);
    when(protocolAdapter.createModel(any(Response.class)))
        .thenReturn(Result.success(new ArrayList<>()));

    fakeThreadUtils.enforceMainThread(false);
    feedRequestManager.loadMore(
        streamToken,
        ConsistencyToken.getDefaultInstance(),
        result -> {
          assertThat(result.isSuccessful()).isTrue();
          assertThat(result.getValue()).hasSize(0);
        });

    verify(protocolAdapter).createModel(responseCaptor.capture());
    LiteProtoTruth.assertThat(responseCaptor.getValue()).isEqualTo(response);
  }

  @Test
  public void testPaging_noMatch() {
    MockServer.Builder mockServerBuilder = MockServer.newBuilder();
    Response response =
        Response.newBuilder().setResponseVersion(ResponseVersion.FEED_RESPONSE).build();
    // Create a MockServerConfig without a matching token.
    ConditionalResponse.Builder conditionalResponseBuilder = ConditionalResponse.newBuilder();
    conditionalResponseBuilder.setResponse(response);
    mockServerBuilder.addConditionalResponses(conditionalResponseBuilder.build());
    MockServerNetworkClient networkClient =
        new MockServerNetworkClient(
            context, mockServerBuilder.build(), /* responseDelayMillis= */ 0L);
    FeedRequestManager feedRequestManager =
        new FeedRequestManager(
            configuration,
            networkClient,
            protocolAdapter,
            extensionRegistry,
            scheduler,
            getTaskQueue(),
            timingUtils,
            fakeThreadUtils,
            actionReader,
            context,
            applicationInfo,
            mainThreadRunner,
            basicLoggingApi,
            tooltipSupportedApi);
    when(protocolAdapter.createModel(any(Response.class)))
        .thenReturn(Result.success(new ArrayList<>()));

    fakeThreadUtils.enforceMainThread(false);
    ByteString token = ByteString.copyFromUtf8("fooToken");
    StreamToken streamToken = StreamToken.newBuilder().setNextPageToken(token).build();
    feedRequestManager.loadMore(
        streamToken,
        ConsistencyToken.getDefaultInstance(),
        result -> {
          assertThat(result.isSuccessful()).isTrue();
          assertThat(result.getValue()).hasSize(0);
        });

    verify(protocolAdapter).createModel(responseCaptor.capture());
    LiteProtoTruth.assertThat(responseCaptor.getValue()).isEqualToDefaultInstance();
  }

  private FakeTaskQueue getTaskQueue() {
    FakeTaskQueue taskQueue = new FakeTaskQueue(fakeClock, fakeThreadUtils);
    taskQueue.initialize(() -> {});
    return taskQueue;
  }
}
