/*
 * 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.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.apache.druid.java.util.common.IAE;
import org.apache.druid.segment.RowAdapter;
import org.apache.druid.segment.column.ColumnHolder;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.segment.column.ValueType;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.ToLongFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Represents an inline datasource, where the rows are embedded within the DataSource object itself.
 *
 * The rows are backed by an Iterable, which can be lazy or not. Lazy datasources will only be iterated if someone calls
 * {@link #getRows()} and iterates the result, or until someone calls {@link #getRowsAsList()}.
 */
public class InlineDataSource implements DataSource
{
  private final Iterable<Object[]> rows;
  private final RowSignature signature;

  private InlineDataSource(
      final Iterable<Object[]> rows,
      final RowSignature signature
  )
  {
    this.rows = Preconditions.checkNotNull(rows, "'rows' must be nonnull");
    this.signature = Preconditions.checkNotNull(signature, "'signature' must be nonnull");
  }

  /**
   * Factory method for Jackson. Used for inline datasources that were originally encoded as JSON. Private because
   * non-Jackson callers should use {@link #fromIterable}.
   */
  @JsonCreator
  private static InlineDataSource fromJson(
      @JsonProperty("columnNames") List<String> columnNames,
      @JsonProperty("columnTypes") List<ValueType> columnTypes,
      @JsonProperty("rows") List<Object[]> rows
  )
  {
    Preconditions.checkNotNull(columnNames, "'columnNames' must be nonnull");

    if (columnTypes != null && columnNames.size() != columnTypes.size()) {
      throw new IAE("columnNames and columnTypes must be the same length");
    }

    final RowSignature.Builder builder = RowSignature.builder();

    for (int i = 0; i < columnNames.size(); i++) {
      final String name = columnNames.get(i);
      final ValueType type = columnTypes != null ? columnTypes.get(i) : null;
      builder.add(name, type);
    }

    return new InlineDataSource(rows, builder.build());
  }

  /**
   * Creates an inline datasource from an Iterable. The Iterable will not be iterated until someone calls
   * {@link #getRows()} and iterates the result, or until someone calls {@link #getRowsAsList()}.
   *
   * @param rows      rows, each of the same length as {@code signature.size()}
   * @param signature row signature
   */
  public static InlineDataSource fromIterable(
      final Iterable<Object[]> rows,
      final RowSignature signature
  )
  {
    return new InlineDataSource(rows, signature);
  }

  @Override
  public Set<String> getTableNames()
  {
    return Collections.emptySet();
  }

  @JsonProperty
  public List<String> getColumnNames()
  {
    return signature.getColumnNames();
  }

  @Nullable
  @JsonProperty
  @JsonInclude(JsonInclude.Include.NON_NULL)
  public List<ValueType> getColumnTypes()
  {
    if (IntStream.range(0, signature.size()).noneMatch(i -> signature.getColumnType(i).isPresent())) {
      // All types are null; return null for columnTypes so it doesn't show up in serialized JSON.
      return null;
    } else {
      return IntStream.range(0, signature.size())
                      .mapToObj(i -> signature.getColumnType(i).orElse(null))
                      .collect(Collectors.toList());
    }
  }

  /**
   * Returns rows as a list. If the original Iterable behind this datasource was a List, this method will return it
   * as-is, without copying it. Otherwise, this method will walk the iterable and copy it into a List before returning.
   */
  @JsonProperty("rows")
  public List<Object[]> getRowsAsList()
  {
    return rows instanceof List ? ((List<Object[]>) rows) : Lists.newArrayList(rows);
  }

  /**
   * Returns rows as an Iterable.
   */
  @JsonIgnore
  public Iterable<Object[]> getRows()
  {
    return rows;
  }

  @Override
  public List<DataSource> getChildren()
  {
    return Collections.emptyList();
  }

  @Override
  public DataSource withChildren(List<DataSource> children)
  {
    if (!children.isEmpty()) {
      throw new IAE("Cannot accept children");
    }

    return this;
  }

  @Override
  public boolean isCacheable(boolean isBroker)
  {
    return false;
  }

  @Override
  public boolean isGlobal()
  {
    return true;
  }

  @Override
  public boolean isConcrete()
  {
    return true;
  }

  /**
   * Returns the row signature (map of column name to type) for this inline datasource. Note that types may
   * be null, meaning we know we have a column with a certain name, but we don't know what its type is.
   */
  public RowSignature getRowSignature()
  {
    return signature;
  }

  public RowAdapter<Object[]> rowAdapter()
  {
    return new RowAdapter<Object[]>()
    {
      @Override
      public ToLongFunction<Object[]> timestampFunction()
      {
        final int columnNumber = signature.indexOf(ColumnHolder.TIME_COLUMN_NAME);

        if (columnNumber >= 0) {
          return row -> (long) row[columnNumber];
        } else {
          return row -> 0L;
        }
      }

      @Override
      public Function<Object[], Object> columnFunction(String columnName)
      {
        final int columnNumber = signature.indexOf(columnName);

        if (columnNumber >= 0) {
          return row -> row[columnNumber];
        } else {
          return row -> null;
        }
      }
    };
  }

  @Override
  public boolean equals(Object o)
  {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    InlineDataSource that = (InlineDataSource) o;
    return rowsEqual(rows, that.rows) &&
           Objects.equals(signature, that.signature);
  }

  @Override
  public int hashCode()
  {
    return Objects.hash(rowsHashCode(rows), signature);
  }

  @Override
  public String toString()
  {
    // Don't include 'rows' in stringification, because it might be long and/or lazy.
    return "InlineDataSource{" +
           "signature=" + signature +
           '}';
  }

  /**
   * A very zealous equality checker for "rows" that respects deep equality of arrays, but nevertheless refrains
   * from materializing things needlessly. Useful for unit tests that want to compare equality of different
   * InlineDataSource instances.
   */
  private static boolean rowsEqual(final Iterable<Object[]> rowsA, final Iterable<Object[]> rowsB)
  {
    if (rowsA instanceof List && rowsB instanceof List) {
      final List<Object[]> listA = (List<Object[]>) rowsA;
      final List<Object[]> listB = (List<Object[]>) rowsB;

      if (listA.size() != listB.size()) {
        return false;
      }

      for (int i = 0; i < listA.size(); i++) {
        final Object[] rowA = listA.get(i);
        final Object[] rowB = listB.get(i);

        if (!Arrays.equals(rowA, rowB)) {
          return false;
        }
      }

      return true;
    } else {
      return Objects.equals(rowsA, rowsB);
    }
  }

  /**
   * A very zealous hash code computer for "rows" that is compatible with {@link #rowsEqual}.
   */
  private static int rowsHashCode(final Iterable<Object[]> rows)
  {
    if (rows instanceof List) {
      final List<Object[]> list = (List<Object[]>) rows;

      int code = 1;
      for (final Object[] row : list) {
        code = 31 * code + Arrays.hashCode(row);
      }

      return code;
    } else {
      return Objects.hash(rows);
    }
  }
}
