/*
 * 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.iceberg;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import org.apache.iceberg.exceptions.ValidationException;
import org.apache.iceberg.expressions.BoundReference;
import org.apache.iceberg.expressions.BoundTerm;
import org.apache.iceberg.expressions.BoundTransform;
import org.apache.iceberg.expressions.Expressions;
import org.apache.iceberg.expressions.Term;
import org.apache.iceberg.expressions.UnboundTerm;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
import org.apache.iceberg.relocated.com.google.common.collect.Lists;
import org.apache.iceberg.transforms.Transform;
import org.apache.iceberg.transforms.Transforms;
import org.apache.iceberg.types.Type;
import org.apache.iceberg.types.Types;

/**
 * A sort order that defines how data and delete files should be ordered in a table.
 */
public class SortOrder implements Serializable {
  private static final SortOrder UNSORTED_ORDER = new SortOrder(new Schema(), 0, Collections.emptyList());

  private final Schema schema;
  private final int orderId;
  private final SortField[] fields;

  private transient volatile List<SortField> fieldList;

  private SortOrder(Schema schema, int orderId, List<SortField> fields) {
    this.schema = schema;
    this.orderId = orderId;
    this.fields = fields.toArray(new SortField[0]);
  }

  /**
   * Returns the {@link Schema} for this sort order
   */
  public Schema schema() {
    return schema;
  }

  /**
   * Returns the ID of this sort order
   */
  public int orderId() {
    return orderId;
  }

  /**
   * Returns the list of {@link SortField sort fields} for this sort order
   */
  public List<SortField> fields() {
    return lazyFieldList();
  }

  /**
   * Returns true if the sort order is unsorted
   */
  public boolean isUnsorted() {
    return fields.length < 1;
  }

  /**
   * Checks whether this order satisfies another order.
   *
   * @param anotherSortOrder a different sort order
   * @return true if this order satisfies the given order
   */
  public boolean satisfies(SortOrder anotherSortOrder) {
    // any ordering satisfies an unsorted ordering
    if (anotherSortOrder.isUnsorted()) {
      return true;
    }

    // this ordering cannot satisfy an ordering with more sort fields
    if (anotherSortOrder.fields.length > fields.length) {
      return false;
    }

    // this ordering has either more or the same number of sort fields
    return IntStream.range(0, anotherSortOrder.fields.length)
        .allMatch(index -> fields[index].satisfies(anotherSortOrder.fields[index]));
  }

  /**
   * Checks whether this order is equivalent to another order while ignoring the order id.
   *
   * @param anotherSortOrder a different sort order
   * @return true if this order is equivalent to the given order
   */
  public boolean sameOrder(SortOrder anotherSortOrder) {
    return Arrays.equals(fields, anotherSortOrder.fields);
  }

  private List<SortField> lazyFieldList() {
    if (fieldList == null) {
      synchronized (this) {
        if (fieldList == null) {
          this.fieldList = ImmutableList.copyOf(fields);
        }
      }
    }
    return fieldList;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for (SortField field : fields) {
      sb.append("\n");
      sb.append("  ").append(field);
    }
    if (fields.length > 0) {
      sb.append("\n");
    }
    sb.append("]");
    return sb.toString();
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    } else if (other == null || getClass() != other.getClass()) {
      return false;
    }

    SortOrder that = (SortOrder) other;
    return orderId == that.orderId && sameOrder(that);
  }

  @Override
  public int hashCode() {
    return 31 * Integer.hashCode(orderId) + Arrays.hashCode(fields);
  }

  /**
   * Returns a sort order for unsorted tables.
   *
   * @return an unsorted order
   */
  public static SortOrder unsorted() {
    return UNSORTED_ORDER;
  }

  /**
   * Creates a new {@link Builder sort order builder} for the given {@link Schema}.
   *
   * @param schema a schema
   * @return a sort order builder for the given schema
   */
  public static Builder builderFor(Schema schema) {
    return new Builder(schema);
  }

  /**
   * A builder used to create valid {@link SortOrder sort orders}.
   * <p>
   * Call {@link #builderFor(Schema)} to create a new builder.
   */
  public static class Builder implements SortOrderBuilder<Builder> {
    private final Schema schema;
    private final List<SortField> fields = Lists.newArrayList();
    // default ID to 1 as 0 is reserved for unsorted order
    private int orderId = 1;
    private boolean caseSensitive = true;

    private Builder(Schema schema) {
      this.schema = schema;
    }

    /**
     * Add an expression term to the sort, ascending with the given null order.
     *
     * @param term an expression term
     * @param nullOrder a null order (first or last)
     * @return this for method chaining
     */
    @Override
    public Builder asc(Term term, NullOrder nullOrder) {
      return addSortField(term, SortDirection.ASC, nullOrder);
    }

    /**
     * Add an expression term to the sort, ascending with the given null order.
     *
     * @param term an expression term
     * @param nullOrder a null order (first or last)
     * @return this for method chaining
     */
    @Override
    public Builder desc(Term term, NullOrder nullOrder) {
      return addSortField(term, SortDirection.DESC, nullOrder);
    }

    public Builder sortBy(String name, SortDirection direction, NullOrder nullOrder) {
      return addSortField(Expressions.ref(name), direction, nullOrder);
    }

    public Builder sortBy(Term term, SortDirection direction, NullOrder nullOrder) {
      return addSortField(term, direction, nullOrder);
    }


    public Builder withOrderId(int newOrderId) {
      this.orderId = newOrderId;
      return this;
    }

    public Builder caseSensitive(boolean sortCaseSensitive) {
      this.caseSensitive = sortCaseSensitive;
      return this;
    }

    Builder addSortField(Term term, SortDirection direction, NullOrder nullOrder) {
      Preconditions.checkArgument(term instanceof UnboundTerm, "Term must be unbound");
      // ValidationException is thrown by bind if binding fails so we assume that boundTerm is correct
      BoundTerm<?> boundTerm = ((UnboundTerm<?>) term).bind(schema.asStruct(), caseSensitive);
      int sourceId = boundTerm.ref().fieldId();
      SortField sortField = new SortField(toTransform(boundTerm), sourceId, direction, nullOrder);
      fields.add(sortField);
      return this;
    }

    Builder addSortField(String transformAsString, int sourceId, SortDirection direction, NullOrder nullOrder) {
      Types.NestedField column = schema.findField(sourceId);
      Preconditions.checkNotNull(column, "Cannot find source column: %s", sourceId);
      Transform<?, ?> transform = Transforms.fromString(column.type(), transformAsString);
      SortField sortField = new SortField(transform, sourceId, direction, nullOrder);
      fields.add(sortField);
      return this;
    }

    public SortOrder build() {
      if (orderId == 0 && fields.size() != 0) {
        throw new IllegalArgumentException("Sort order ID 0 is reserved for unsorted order");
      }
      if (fields.size() == 0 && orderId != 0) {
        throw new IllegalArgumentException("Unsorted order ID must be 0");
      }

      SortOrder sortOrder = new SortOrder(schema, orderId, fields);
      checkCompatibility(sortOrder, schema);
      return sortOrder;
    }

    private Transform<?, ?> toTransform(BoundTerm<?> term) {
      if (term instanceof BoundReference) {
        return Transforms.identity(term.type());
      } else if (term instanceof BoundTransform) {
        return ((BoundTransform<?, ?>) term).transform();
      } else {
        throw new ValidationException("Invalid term: %s, expected either a bound reference or transform", term);
      }
    }
  }

  static void checkCompatibility(SortOrder sortOrder, Schema schema) {
    for (SortField field : sortOrder.fields) {
      Type sourceType = schema.findType(field.sourceId());
      ValidationException.check(
          sourceType != null,
          "Cannot find source column for sort field: %s", field);
      ValidationException.check(
          sourceType.isPrimitiveType(),
          "Cannot sort by non-primitive source field: %s", sourceType);
      ValidationException.check(
          field.transform().canTransform(sourceType),
          "Invalid source type %s for transform: %s",
          sourceType, field.transform());
    }
  }
}
