// Copyright (C) 2013 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.index;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.common.base.CharMatcher;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.exceptions.StorageException;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Optional;

/**
 * Definition of a field stored in the secondary index.
 *
 * @param <I> input type from which documents are created and search results are returned.
 * @param <T> type that should be extracted from the input object when converting to an index
 *     document.
 */
public final class FieldDef<I, T> {
  public static FieldDef.Builder<String> exact(String name) {
    return new FieldDef.Builder<>(FieldType.EXACT, name);
  }

  public static FieldDef.Builder<String> fullText(String name) {
    return new FieldDef.Builder<>(FieldType.FULL_TEXT, name);
  }

  public static FieldDef.Builder<Integer> intRange(String name) {
    return new FieldDef.Builder<>(FieldType.INTEGER_RANGE, name).stored();
  }

  public static FieldDef.Builder<Integer> integer(String name) {
    return new FieldDef.Builder<>(FieldType.INTEGER, name);
  }

  public static FieldDef.Builder<String> prefix(String name) {
    return new FieldDef.Builder<>(FieldType.PREFIX, name);
  }

  public static FieldDef.Builder<byte[]> storedOnly(String name) {
    return new FieldDef.Builder<>(FieldType.STORED_ONLY, name).stored();
  }

  public static FieldDef.Builder<Timestamp> timestamp(String name) {
    return new FieldDef.Builder<>(FieldType.TIMESTAMP, name);
  }

  @FunctionalInterface
  public interface Getter<I, T> {
    @Nullable
    T get(I input) throws IOException;
  }

  @FunctionalInterface
  public interface Setter<I, T> {
    void set(I object, T value);
  }

  public static class Builder<T> {
    private final FieldType<T> type;
    private final String name;
    private boolean stored;

    public Builder(FieldType<T> type, String name) {
      this.type = requireNonNull(type);
      this.name = requireNonNull(name);
    }

    public Builder<T> stored() {
      this.stored = true;
      return this;
    }

    public <I> FieldDef<I, T> build(Getter<I, T> getter) {
      return new FieldDef<>(name, type, stored, false, getter, null);
    }

    public <I> FieldDef<I, T> build(Getter<I, T> getter, Setter<I, T> setter) {
      return new FieldDef<>(name, type, stored, false, getter, setter);
    }

    public <I> FieldDef<I, Iterable<T>> buildRepeatable(Getter<I, Iterable<T>> getter) {
      return new FieldDef<>(name, type, stored, true, getter, null);
    }

    public <I> FieldDef<I, Iterable<T>> buildRepeatable(
        Getter<I, Iterable<T>> getter, Setter<I, Iterable<T>> setter) {
      return new FieldDef<>(name, type, stored, true, getter, setter);
    }
  }

  private final String name;
  private final FieldType<?> type;
  /** Allow reading the actual data from the index. */
  private final boolean stored;

  private final boolean repeatable;
  private final Getter<I, T> getter;
  private final Optional<Setter<I, T>> setter;

  private FieldDef(
      String name,
      FieldType<?> type,
      boolean stored,
      boolean repeatable,
      Getter<I, T> getter,
      @Nullable Setter<I, T> setter) {
    checkArgument(
        !(repeatable && type == FieldType.INTEGER_RANGE),
        "Range queries against repeated fields are unsupported");
    this.name = checkName(name);
    this.type = requireNonNull(type);
    this.stored = stored;
    this.repeatable = repeatable;
    this.getter = requireNonNull(getter);
    this.setter = Optional.ofNullable(setter);
  }

  private static String checkName(String name) {
    CharMatcher m = CharMatcher.anyOf("abcdefghijklmnopqrstuvwxyz0123456789_");
    checkArgument(name != null && m.matchesAllOf(name), "illegal field name: %s", name);
    return name;
  }

  /** Returns name of the field. */
  public String getName() {
    return name;
  }

  /** Returns type of the field; for repeatable fields, the inner type, not the iterable type. */
  public FieldType<?> getType() {
    return type;
  }

  /** Returns whether the field should be stored in the index. */
  public boolean isStored() {
    return stored;
  }

  /**
   * Get the field contents from the input object.
   *
   * @param input input object.
   * @return the field value(s) to index.
   */
  @Nullable
  public T get(I input) {
    try {
      return getter.get(input);
    } catch (IOException e) {
      throw new StorageException(e);
    }
  }

  /**
   * Set the field contents back to an object. Used to reconstruct fields from indexed values. No-op
   * if the field can't be reconstructed.
   *
   * @param object input object.
   * @param doc indexed document
   * @return {@code true} if the field was set, {@code false} otherwise
   */
  @SuppressWarnings("unchecked")
  public boolean setIfPossible(I object, StoredValue doc) {
    if (!setter.isPresent()) {
      return false;
    }

    if (FieldType.STRING_TYPES.stream().anyMatch(t -> t.getName().equals(getType().getName()))) {
      setter.get().set(object, (T) (isRepeatable() ? doc.asStrings() : doc.asString()));
      return true;
    } else if (FieldType.INTEGER_TYPES.stream()
        .anyMatch(t -> t.getName().equals(getType().getName()))) {
      setter.get().set(object, (T) (isRepeatable() ? doc.asIntegers() : doc.asInteger()));
      return true;
    } else if (FieldType.LONG.getName().equals(getType().getName())) {
      setter.get().set(object, (T) (isRepeatable() ? doc.asLongs() : doc.asLong()));
      return true;
    } else if (FieldType.STORED_ONLY.getName().equals(getType().getName())) {
      setter.get().set(object, (T) (isRepeatable() ? doc.asByteArrays() : doc.asByteArray()));
      return true;
    } else if (FieldType.TIMESTAMP.getName().equals(getType().getName())) {
      checkState(!isRepeatable(), "can't repeat timestamp values");
      setter.get().set(object, (T) doc.asTimestamp());
      return true;
    }
    return false;
  }

  /** Returns whether the field is repeatable. */
  public boolean isRepeatable() {
    return repeatable;
  }
}
