/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.druid.query;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.segment.RowAdapter;
import org.apache.druid.segment.TestHelper;
import org.apache.druid.segment.column.ColumnHolder;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.segment.column.ValueType;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

public class InlineDataSourceTest
{
  @Rule
  public ExpectedException expectedException = ExpectedException.none();

  private final AtomicLong iterationCounter = new AtomicLong();

  // raw arrays, e.g. double[]{1.0, 2.0} on round trip get deserialized into List<Double>, so just model that
  private final List<Object[]> rows = ImmutableList.of(
      new Object[]{DateTimes.of("2000").getMillis(), "foo", 0d, ImmutableMap.of("n", "0"), ImmutableList.of(1.0, 2.0)},
      new Object[]{DateTimes.of("2000").getMillis(), "bar", 1d, ImmutableMap.of("n", "1"), ImmutableList.of(2.0, 4.0)},
      new Object[]{DateTimes.of("2000").getMillis(), "baz", 2d, ImmutableMap.of("n", "2"), ImmutableList.of(3.0, 6.0)}
  );

  private final Iterable<Object[]> rowsIterable = () -> {
    iterationCounter.incrementAndGet();
    return rows.iterator();
  };

  private final List<String> expectedColumnNames = ImmutableList.of(
      ColumnHolder.TIME_COLUMN_NAME,
      "str",
      "double",
      "complex",
      "double_array"
  );

  private final List<ValueType> expectedColumnTypes = ImmutableList.of(
      ValueType.LONG,
      ValueType.STRING,
      ValueType.DOUBLE,
      ValueType.COMPLEX,
      ValueType.DOUBLE_ARRAY
  );

  private final RowSignature expectedRowSignature;

  private final InlineDataSource listDataSource;

  private final InlineDataSource iterableDataSource;

  public InlineDataSourceTest()
  {
    final RowSignature.Builder builder = RowSignature.builder();

    for (int i = 0; i < expectedColumnNames.size(); i++) {
      builder.add(expectedColumnNames.get(i), expectedColumnTypes.get(i));
    }

    expectedRowSignature = builder.build();
    listDataSource = InlineDataSource.fromIterable(rows, expectedRowSignature);
    iterableDataSource = InlineDataSource.fromIterable(rowsIterable, expectedRowSignature);
  }

  @Test
  public void test_getTableNames()
  {
    Assert.assertEquals(Collections.emptySet(), listDataSource.getTableNames());
    Assert.assertEquals(Collections.emptySet(), iterableDataSource.getTableNames());
  }

  @Test
  public void test_getColumnNames()
  {
    Assert.assertEquals(expectedColumnNames, listDataSource.getColumnNames());
    Assert.assertEquals(expectedColumnNames, iterableDataSource.getColumnNames());
  }

  @Test
  public void test_getColumnTypes()
  {
    Assert.assertEquals(expectedColumnTypes, listDataSource.getColumnTypes());
    Assert.assertEquals(expectedColumnTypes, iterableDataSource.getColumnTypes());
  }

  @Test
  public void test_getChildren()
  {
    Assert.assertEquals(Collections.emptyList(), listDataSource.getChildren());
    Assert.assertEquals(Collections.emptyList(), iterableDataSource.getChildren());
  }

  @Test
  public void test_getRowSignature()
  {
    Assert.assertEquals(
        RowSignature.builder()
                    .add(ColumnHolder.TIME_COLUMN_NAME, ValueType.LONG)
                    .add("str", ValueType.STRING)
                    .add("double", ValueType.DOUBLE)
                    .add("complex", ValueType.COMPLEX)
                    .add("double_array", ValueType.DOUBLE_ARRAY)
                    .build(),
        listDataSource.getRowSignature()
    );
  }

  @Test
  public void test_isCacheable()
  {
    Assert.assertFalse(listDataSource.isCacheable(true));
    Assert.assertFalse(listDataSource.isCacheable(false));
  }

  @Test
  public void test_isGlobal()
  {
    Assert.assertTrue(listDataSource.isGlobal());
  }

  @Test
  public void test_isConcrete()
  {
    Assert.assertTrue(listDataSource.isConcrete());
  }

  @Test
  public void test_rowAdapter()
  {
    final RowAdapter<Object[]> adapter = listDataSource.rowAdapter();
    final Object[] row = rows.get(1);

    Assert.assertEquals(DateTimes.of("2000").getMillis(), adapter.timestampFunction().applyAsLong(row));
    Assert.assertEquals("bar", adapter.columnFunction("str").apply(row));
    Assert.assertEquals(1d, adapter.columnFunction("double").apply(row));
    Assert.assertEquals(ImmutableMap.of("n", "1"), adapter.columnFunction("complex").apply(row));
    Assert.assertEquals(ImmutableList.of(2.0, 4.0), adapter.columnFunction("double_array").apply(row));
  }

  @Test
  public void test_getRows_list()
  {
    Assert.assertSame(this.rows, listDataSource.getRowsAsList());
  }

  @Test
  public void test_getRows_iterable()
  {
    final Iterable<Object[]> iterable = iterableDataSource.getRows();
    Assert.assertNotSame(this.rows, iterable);

    // No iteration yet.
    Assert.assertEquals(0, iterationCounter.get());

    assertRowsEqual(this.rows, ImmutableList.copyOf(iterable));

    // OK, now we've iterated.
    Assert.assertEquals(1, iterationCounter.get());

    // Read again, we should iterate again.
    //noinspection MismatchedQueryAndUpdateOfCollection
    final List<Object[]> ignored = Lists.newArrayList(iterable);
    Assert.assertEquals(2, iterationCounter.get());
  }

  @Test
  public void test_getRowsAsList_list()
  {
    Assert.assertSame(this.rows, listDataSource.getRowsAsList());
  }

  @Test
  public void test_getRowsAsList_iterable()
  {
    final List<Object[]> list = iterableDataSource.getRowsAsList();

    Assert.assertEquals(1, iterationCounter.get());
    assertRowsEqual(this.rows, list);

    // Read again, we should *not* iterate again (in contrast to "test_getRows_iterable").
    //noinspection MismatchedQueryAndUpdateOfCollection
    final List<Object[]> ignored = Lists.newArrayList(list);
    Assert.assertEquals(1, iterationCounter.get());
  }

  @Test
  public void test_withChildren_empty()
  {
    Assert.assertSame(listDataSource, listDataSource.withChildren(Collections.emptyList()));
  }

  @Test
  public void test_withChildren_nonEmpty()
  {
    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage("Cannot accept children");

    // Workaround so "withChildren" isn't flagged as unused in the DataSource interface.
    ((DataSource) listDataSource).withChildren(ImmutableList.of(new TableDataSource("foo")));
  }

  @Test
  public void test_equals()
  {
    EqualsVerifier.forClass(InlineDataSource.class)
                  .usingGetClass()
                  .withNonnullFields("rows", "signature")
                  .verify();
  }

  @Test
  public void test_toString_iterable()
  {
    // Verify that toString does not iterate the rows.
    final String ignored = iterableDataSource.toString();
    Assert.assertEquals(0, iterationCounter.get());
  }

  @Test
  public void test_serde_list() throws Exception
  {
    final ObjectMapper jsonMapper = TestHelper.makeJsonMapper();
    final InlineDataSource deserialized = (InlineDataSource) jsonMapper.readValue(
        jsonMapper.writeValueAsString(listDataSource),
        DataSource.class
    );

    Assert.assertEquals(listDataSource.getColumnNames(), deserialized.getColumnNames());
    Assert.assertEquals(listDataSource.getColumnTypes(), deserialized.getColumnTypes());
    Assert.assertEquals(listDataSource.getRowSignature(), deserialized.getRowSignature());
    assertRowsEqual(listDataSource.getRows(), deserialized.getRows());
  }

  @Test
  public void test_serde_iterable() throws Exception
  {
    final ObjectMapper jsonMapper = TestHelper.makeJsonMapper();
    final InlineDataSource deserialized = (InlineDataSource) jsonMapper.readValue(
        jsonMapper.writeValueAsString(iterableDataSource),
        DataSource.class
    );

    // Lazy iterables turn into Lists upon serialization.
    Assert.assertEquals(listDataSource.getColumnNames(), deserialized.getColumnNames());
    Assert.assertEquals(listDataSource.getColumnTypes(), deserialized.getColumnTypes());
    Assert.assertEquals(listDataSource.getRowSignature(), deserialized.getRowSignature());
    assertRowsEqual(listDataSource.getRows(), deserialized.getRows());

    // Should have iterated once.
    Assert.assertEquals(1, iterationCounter.get());
  }

  @Test
  public void test_serde_untyped() throws Exception
  {
    // Create a row signature with no types set.
    final RowSignature.Builder builder = RowSignature.builder();
    for (String columnName : expectedRowSignature.getColumnNames()) {
      builder.add(columnName, null);
    }

    final RowSignature untypedSignature = builder.build();
    final InlineDataSource untypedDataSource = InlineDataSource.fromIterable(rows, untypedSignature);

    final ObjectMapper jsonMapper = TestHelper.makeJsonMapper();
    final InlineDataSource deserialized = (InlineDataSource) jsonMapper.readValue(
        jsonMapper.writeValueAsString(untypedDataSource),
        DataSource.class
    );

    Assert.assertEquals(untypedDataSource.getColumnNames(), deserialized.getColumnNames());
    Assert.assertEquals(untypedDataSource.getColumnTypes(), deserialized.getColumnTypes());
    Assert.assertEquals(untypedDataSource.getRowSignature(), deserialized.getRowSignature());
    Assert.assertNull(deserialized.getColumnTypes());
    assertRowsEqual(listDataSource.getRows(), deserialized.getRows());
  }

  /**
   * This method exists because "equals" on two equivalent Object[] won't return true, so we need to check
   * for equality deeply.
   */
  private static void assertRowsEqual(final Iterable<Object[]> expectedRows, final Iterable<Object[]> actualRows)
  {
    if (expectedRows instanceof List && actualRows instanceof List) {
      // Only check equality deeply when both rows1 and rows2 are Lists, i.e., non-lazy.
      final List<Object[]> expectedRowsList = (List<Object[]>) expectedRows;
      final List<Object[]> actualRowsList = (List<Object[]>) actualRows;

      final int sz = expectedRowsList.size();
      Assert.assertEquals("number of rows", sz, actualRowsList.size());

      // Super slow for LinkedLists, but we don't expect those to be used here.
      // (They're generally forbidden in Druid except for special cases.)
      for (int i = 0; i < sz; i++) {
        Assert.assertArrayEquals("row #" + i, expectedRowsList.get(i), actualRowsList.get(i));
      }
    } else {
      // If they're not both Lists, we don't want to iterate them during equality checks, so do a non-deep check.
      // This might still return true if whatever class they are has another way of checking equality. But, usually we
      // expect this to return false.
      Assert.assertEquals("rows", expectedRows, actualRows);
    }
  }

}
