// Copyright (C) 2022 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.google.gerrit.server.index;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.gerrit.entities.converter.ChangeProtoConverter;
import com.google.gerrit.index.IndexedField;
import com.google.gerrit.index.SchemaFieldDefs.Getter;
import com.google.gerrit.index.SchemaFieldDefs.Setter;
import com.google.gerrit.index.StoredValue;
import com.google.gerrit.index.testing.FakeStoredValue;
import com.google.gerrit.proto.Entities;
import com.google.gerrit.proto.Entities.Change;
import com.google.gerrit.proto.Entities.Change_Id;
import com.google.gerrit.proto.Protos;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.Map.Entry;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

/** Tests for {@link com.google.gerrit.index.IndexedField} */
@SuppressWarnings("serial")
@RunWith(Theories.class)
public class IndexedFieldTest {

  /** Test input object for {@link IndexedField} */
  static class TestIndexedData {

    private Object testField;

    public Object getTestField() {
      return testField;
    }

    public void setTestField(Object testField) {
      this.testField = testField;
    }
  }

  private static class TestIndexedDataSetter<T> implements Setter<TestIndexedData, T> {
    @Override
    public void set(TestIndexedData testIndexedData, T value) {
      testIndexedData.setTestField(value);
    }
  }

  @SuppressWarnings("unchecked")
  private static class TestIndexedDataGetter<T> implements Getter<TestIndexedData, T> {
    @Override
    public T get(TestIndexedData input) throws IOException {
      return (T) input.getTestField();
    }
  }

  public static <T> TestIndexedDataSetter<T> setter() {
    return new TestIndexedDataSetter<>();
  }

  public static <T> TestIndexedDataGetter<T> getter() {
    return new TestIndexedDataGetter<>();
  }

  static final IndexedField<TestIndexedData, Integer> INTEGER_FIELD =
      IndexedField.<TestIndexedData>integerBuilder("TestField").build(getter(), setter());

  static final IndexedField<TestIndexedData, Integer>.SearchSpec INTEGER_FIELD_SPEC =
      INTEGER_FIELD.integer("test");

  static final IndexedField<TestIndexedData, Iterable<Integer>> ITERABLE_INTEGER_FIELD =
      IndexedField.<TestIndexedData>iterableIntegerBuilder("TestField").build(getter(), setter());

  static final IndexedField<TestIndexedData, Iterable<Integer>>.SearchSpec
      ITERABLE_INTEGER_FIELD_SPEC = ITERABLE_INTEGER_FIELD.integer("test");

  static final IndexedField<TestIndexedData, Iterable<String>> ITERABLE_STRING_FIELD =
      IndexedField.<TestIndexedData>iterableStringBuilder("TestField").build(getter(), setter());

  static final IndexedField<TestIndexedData, Long> LONG_FIELD =
      IndexedField.<TestIndexedData>longBuilder("TestField").build(getter(), setter());

  static final IndexedField<TestIndexedData, Long>.SearchSpec LONG_FIELD_SPEC =
      LONG_FIELD.longSearch("test");

  static final IndexedField<TestIndexedData, Timestamp> TIMESTAMP_FIELD =
      IndexedField.<TestIndexedData>timestampBuilder("TestField").build(getter(), setter());

  static final IndexedField<TestIndexedData, Timestamp>.SearchSpec TIMESTAMP_FIELD_SPEC =
      TIMESTAMP_FIELD.timestamp("test");

  static final IndexedField<TestIndexedData, Iterable<String>>.SearchSpec
      ITERABLE_STRING_FIELD_SPEC = ITERABLE_STRING_FIELD.fullText("test");

  static final IndexedField<TestIndexedData, String> STRING_FIELD =
      IndexedField.<TestIndexedData>stringBuilder("TestField").build(getter(), setter());

  static final IndexedField<TestIndexedData, String>.SearchSpec STRING_FIELD_SPEC =
      STRING_FIELD.fullText("test");

  static final IndexedField<TestIndexedData, Iterable<byte[]>> ITERABLE_STORED_BYTE_FIELD =
      IndexedField.<TestIndexedData>iterableByteArrayBuilder("TestField")
          .stored()
          .build(getter(), setter());

  static final IndexedField<TestIndexedData, Iterable<byte[]>>.SearchSpec
      ITERABLE_STORED_BYTE_SPEC = ITERABLE_STORED_BYTE_FIELD.storedOnly("test");

  static final IndexedField<TestIndexedData, byte[]> STORED_BYTE_FIELD =
      IndexedField.<TestIndexedData>byteArrayBuilder("TestField")
          .stored()
          .build(getter(), setter());

  static final IndexedField<TestIndexedData, byte[]>.SearchSpec STORED_BYTE_SPEC =
      STORED_BYTE_FIELD.storedOnly("test");

  static final IndexedField<TestIndexedData, Entities.Change> STORED_PROTO_FIELD =
      IndexedField.<TestIndexedData, Entities.Change>builder(
              "TestChange", new TypeToken<Entities.Change>() {})
          .stored()
          .build(getter(), setter(), ChangeProtoConverter.INSTANCE);

  static final IndexedField<TestIndexedData, Entities.Change>.SearchSpec STORED_PROTO_FIELD_SPEC =
      STORED_PROTO_FIELD.storedOnly("test_change");

  static final IndexedField<TestIndexedData, Iterable<Entities.Change>>
      ITERABLE_STORED_PROTO_FIELD =
          IndexedField.<TestIndexedData, Iterable<Entities.Change>>builder(
                  "TestChange", new TypeToken<Iterable<Entities.Change>>() {})
              .stored()
              .build(getter(), setter(), ChangeProtoConverter.INSTANCE);

  static final IndexedField<TestIndexedData, Iterable<Entities.Change>>.SearchSpec
      ITERABLE_PROTO_FIELD_SPEC = ITERABLE_STORED_PROTO_FIELD.storedOnly("test_change");

  @DataPoints("nonProtoTypes")
  public static final ImmutableList<
          Entry<IndexedField<TestIndexedData, ?>.SearchSpec, Serializable>>
      fieldToStoredValue =
          new ImmutableMap.Builder<IndexedField<TestIndexedData, ?>.SearchSpec, Serializable>()
              .put(INTEGER_FIELD_SPEC, 123456)
              .put(ITERABLE_INTEGER_FIELD_SPEC, ImmutableList.of(123456, 654321))
              .put(LONG_FIELD_SPEC, 123456L)
              .put(TIMESTAMP_FIELD_SPEC, new Timestamp(1234567L))
              .put(STRING_FIELD_SPEC, "123456")
              .put(ITERABLE_STRING_FIELD_SPEC, ImmutableList.of("123456"))
              .put(
                  ITERABLE_STORED_BYTE_SPEC,
                  ImmutableList.of("123456".getBytes(StandardCharsets.UTF_8)))
              .put(STORED_BYTE_SPEC, "123456".getBytes(StandardCharsets.UTF_8))
              .build()
              .entrySet()
              .asList();

  @DataPoints("protoTypes")
  public static final ImmutableList<
          Entry<IndexedField<TestIndexedData, ?>.SearchSpec, Serializable>>
      protoFieldToStoredValue =
          ImmutableMap.<IndexedField<TestIndexedData, ?>.SearchSpec, Serializable>of(
                  STORED_PROTO_FIELD_SPEC,
                  createChangeProto(12345),
                  ITERABLE_PROTO_FIELD_SPEC,
                  ImmutableList.of(createChangeProto(12345), createChangeProto(54321)))
              .entrySet()
              .asList();

  @Theory
  public void testSetIfPossible(
      @FromDataPoints("nonProtoTypes")
          Entry<IndexedField<TestIndexedData, StoredValue>.SearchSpec, StoredValue>
              fieldToStoredValue) {
    Object docValue = fieldToStoredValue.getValue();
    IndexedField<TestIndexedData, StoredValue>.SearchSpec searchSpec = fieldToStoredValue.getKey();
    StoredValue storedValue = new FakeStoredValue(fieldToStoredValue.getValue());
    TestIndexedData testIndexedData = new TestIndexedData();
    searchSpec.setIfPossible(testIndexedData, storedValue);
    assertThat(testIndexedData.getTestField()).isEqualTo(docValue);
  }

  @Test
  public void testSetIfPossible_protoFromBytes() {
    Entities.Change changeProto = createChangeProto(12345);
    StoredValue storedValue = new FakeStoredValue(Protos.toByteArray(changeProto));
    TestIndexedData testIndexedData = new TestIndexedData();
    STORED_PROTO_FIELD_SPEC.setIfPossible(testIndexedData, storedValue);
    assertThat(testIndexedData.getTestField()).isEqualTo(changeProto);
  }

  @Test
  public void testSetIfPossible_iterableProtoFromIterableBytes() {
    ImmutableList<Entities.Change> changeProtos =
        ImmutableList.of(createChangeProto(12345), createChangeProto(54321));
    StoredValue storedValue =
        new FakeStoredValue(
            changeProtos.stream()
                .map(proto -> Protos.toByteArray(proto))
                .collect(toImmutableList()));
    TestIndexedData testIndexedData = new TestIndexedData();
    ITERABLE_STORED_PROTO_FIELD.setIfPossible(testIndexedData, storedValue);
    assertThat(testIndexedData.getTestField()).isEqualTo(changeProtos);
  }

  @Theory
  public void testSetIfPossible_fromProto(
      @FromDataPoints("protoTypes")
          Entry<IndexedField<TestIndexedData, StoredValue>.SearchSpec, StoredValue>
              fieldToStoredValue) {
    Object docValue = fieldToStoredValue.getValue();
    IndexedField<TestIndexedData, StoredValue>.SearchSpec searchSpec = fieldToStoredValue.getKey();
    StoredValue storedValue = new FakeStoredValue(fieldToStoredValue.getValue(), /*isProto=*/ true);
    TestIndexedData testIndexedData = new TestIndexedData();
    searchSpec.setIfPossible(testIndexedData, storedValue);
    assertThat(testIndexedData.getTestField()).isEqualTo(docValue);
  }

  @Test
  public void test_isProtoType() {
    assertThat(STORED_PROTO_FIELD.isProtoType()).isTrue();

    assertThat(ITERABLE_STORED_PROTO_FIELD.isProtoType()).isFalse();
    assertThat(INTEGER_FIELD.isProtoType()).isFalse();
    assertThat(ITERABLE_STRING_FIELD.isProtoType()).isFalse();
    assertThat(STORED_BYTE_FIELD.isProtoType()).isFalse();
    assertThat(ITERABLE_STORED_BYTE_FIELD.isProtoType()).isFalse();
  }

  @Test
  public void test_isProtoIterableType() {

    assertThat(ITERABLE_STORED_PROTO_FIELD.isProtoIterableType()).isTrue();

    assertThat(STORED_PROTO_FIELD.isProtoIterableType()).isFalse();
    assertThat(INTEGER_FIELD.isProtoIterableType()).isFalse();
    assertThat(ITERABLE_STRING_FIELD.isProtoIterableType()).isFalse();
    assertThat(STORED_BYTE_FIELD.isProtoIterableType()).isFalse();
    assertThat(ITERABLE_STORED_BYTE_FIELD.isProtoType()).isFalse();
  }

  private static Change createChangeProto(int id) {
    return Entities.Change.newBuilder()
        .setChangeId(Change_Id.newBuilder().setId(id).build())
        .build();
  }
}
