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


import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set;
import org.apache.iceberg.relocated.com.google.common.base.Joiner;
import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
import org.apache.iceberg.relocated.com.google.common.base.Throwables;
import org.apache.iceberg.relocated.com.google.common.collect.Sets;


public class DynFields {

  private DynFields() {
  }

  /**
   * Convenience wrapper class around {@link java.lang.reflect.Field}.
   *
   * Allows callers to invoke the wrapped method with all Exceptions wrapped by
   * RuntimeException, or with a single Exception catch block.
   */
  public static class UnboundField<T> {
    private final Field field;
    private final String name;

    private UnboundField(Field field, String name) {
      this.field = field;
      this.name = name;
    }

    @SuppressWarnings("unchecked")
    public T get(Object target) {
      try {
        return (T) field.get(target);
      } catch (IllegalAccessException e) {
        throw Throwables.propagate(e);
      }
    }

    public void set(Object target, T value) {
      try {
        field.set(target, value);
      } catch (IllegalAccessException e) {
        throw Throwables.propagate(e);
      }
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("class", field.getDeclaringClass().toString())
          .add("name", name)
          .add("type", field.getType())
          .toString();
    }

    /**
     * Returns this method as a BoundMethod for the given receiver.
     *
     * @param target an Object on which to get or set this field
     * @return a {@link BoundField} for this field and the target
     * @throws IllegalStateException if the method is static
     * @throws IllegalArgumentException if the receiver's class is incompatible
     */
    public BoundField<T> bind(Object target) {
      Preconditions.checkState(!isStatic() || this == AlwaysNull.INSTANCE,
          "Cannot bind static field %s", name);
      Preconditions.checkArgument(
          field.getDeclaringClass().isAssignableFrom(target.getClass()),
          "Cannot bind field %s to instance of %s",
              name,
              target.getClass());

      return new BoundField<>(this, target);
    }

    /**
     * Returns this field as a StaticField.
     *
     * @return a {@link StaticField} for this field
     * @throws IllegalStateException if the method is not static
     */
    public StaticField<T> asStatic() {
      Preconditions.checkState(isStatic(), "Field %s is not static", name);
      return new StaticField<>(this);
    }

    /**
     * Returns whether the field is a static field.
     */
    public boolean isStatic() {
      return Modifier.isStatic(field.getModifiers());
    }

    /**
     * Returns whether the field is always null.
     */
    public boolean isAlwaysNull() {
      return this == AlwaysNull.INSTANCE;
    }
  }

  private static class AlwaysNull extends UnboundField<Void> {
    private static final AlwaysNull INSTANCE = new AlwaysNull();

    private AlwaysNull() {
      super(null, "AlwaysNull");
    }

    @Override
    public Void get(Object target) {
      return null;
    }

    @Override
    public void set(Object target, Void value) {
    }

    @Override
    public String toString() {
      return "Field(AlwaysNull)";
    }

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

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

  public static class StaticField<T> {
    private final UnboundField<T> field;

    private StaticField(UnboundField<T> field) {
      this.field = field;
    }

    public T get() {
      return field.get(null);
    }

    public void set(T value) {
      field.set(null, value);
    }
  }


  public static class BoundField<T> {
    private final UnboundField<T> field;
    private final Object target;

    private BoundField(UnboundField<T> field, Object target) {
      this.field = field;
      this.target = target;
    }

    public T get() {
      return field.get(target);
    }

    public void set(T value) {
      field.set(target, value);
    }
  }

  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {
    private ClassLoader loader = Thread.currentThread().getContextClassLoader();
    private UnboundField<?> field = null;
    private final Set<String> candidates = Sets.newHashSet();
    private boolean defaultAlwaysNull = false;

    /**
     * Set the {@link ClassLoader} used to lookup classes by name.
     * <p>
     * If not set, the current thread's ClassLoader is used.
     *
     * @param newLoader a ClassLoader
     * @return this Builder for method chaining
     */
    public Builder loader(ClassLoader newLoader) {
      this.loader = newLoader;
      return this;
    }

    /**
     * Instructs this builder to return AlwaysNull if no implementation is
     * found.
     *
     * @return this Builder for method chaining
     */
    public Builder defaultAlwaysNull() {
      this.defaultAlwaysNull = true;
      return this;
    }

    /**
     * Checks for an implementation, first finding the class by name.
     *
     * @param className name of a class
     * @param fieldName name of the field
     * @return this Builder for method chaining
     * @see java.lang.Class#forName(String)
     * @see java.lang.Class#getField(String)
     */
    public Builder impl(String className, String fieldName) {
      // don't do any work if an implementation has been found
      if (field != null) {
        return this;
      }

      try {
        Class<?> targetClass = Class.forName(className, true, loader);
        impl(targetClass, fieldName);
      } catch (ClassNotFoundException e) {
        // not the right implementation
        candidates.add(className + "." + fieldName);
      }
      return this;
    }

    /**
     * Checks for an implementation.
     *
     * @param targetClass a class instance
     * @param fieldName name of a field (different from constructor)
     * @return this Builder for method chaining
     * @see java.lang.Class#forName(String)
     * @see java.lang.Class#getField(String)
     */
    public Builder impl(Class<?> targetClass, String fieldName) {
      // don't do any work if an implementation has been found
      if (field != null || targetClass == null) {
        return this;
      }

      try {
        this.field = new UnboundField<>(
            targetClass.getField(fieldName), fieldName);
      } catch (NoSuchFieldException e) {
        // not the right implementation
        candidates.add(targetClass.getName() + "." + fieldName);
      }
      return this;
    }

    /**
     * Checks for a hidden implementation, first finding the class by name.
     *
     * @param className name of a class
     * @param fieldName name of a field (different from constructor)
     * @return this Builder for method chaining
     * @see java.lang.Class#forName(String)
     * @see java.lang.Class#getField(String)
     */
    public Builder hiddenImpl(String className, String fieldName) {
      // don't do any work if an implementation has been found
      if (field != null) {
        return this;
      }

      try {
        Class<?> targetClass = Class.forName(className, true, loader);
        hiddenImpl(targetClass, fieldName);
      } catch (ClassNotFoundException e) {
        // not the right implementation
        candidates.add(className + "." + fieldName);
      }
      return this;
    }

    /**
     * Checks for a hidden implementation.
     *
     * @param targetClass a class instance
     * @param fieldName name of a field (different from constructor)
     * @return this Builder for method chaining
     * @see java.lang.Class#forName(String)
     * @see java.lang.Class#getField(String)
     */
    public Builder hiddenImpl(Class<?> targetClass, String fieldName) {
      // don't do any work if an implementation has been found
      if (field != null || targetClass == null) {
        return this;
      }

      try {
        Field hidden = targetClass.getDeclaredField(fieldName);
        AccessController.doPrivileged(new MakeFieldAccessible(hidden));
        this.field = new UnboundField(hidden, fieldName);
      } catch (SecurityException | NoSuchFieldException e) {
        // unusable
        candidates.add(targetClass.getName() + "." + fieldName);
      }
      return this;
    }

    /**
     * Returns the first valid implementation as a UnboundField or throws a
     * NoSuchFieldException if there is none.
     *
     * @param <T> Java class stored in the field
     * @return a {@link UnboundField} with a valid implementation
     * @throws NoSuchFieldException if no implementation was found
     */
    @SuppressWarnings("unchecked")
    public <T> UnboundField<T> buildChecked() throws NoSuchFieldException {
      if (field != null) {
        return (UnboundField<T>) field;
      } else if (defaultAlwaysNull) {
        return (UnboundField<T>) AlwaysNull.INSTANCE;
      } else {
        throw new NoSuchFieldException("Cannot find field from candidates: " +
            Joiner.on(", ").join(candidates));
      }
    }

    /**
     * Returns the first valid implementation as a BoundMethod or throws a
     * NoSuchMethodException if there is none.
     *
     * @param target an Object on which to get and set the field
     * @param <T> Java class stored in the field
     * @return a {@link BoundField} with a valid implementation and target
     * @throws IllegalStateException if the method is static
     * @throws IllegalArgumentException if the receiver's class is incompatible
     * @throws NoSuchFieldException if no implementation was found
     */
    public <T> BoundField<T> buildChecked(Object target) throws NoSuchFieldException {
      return this.<T>buildChecked().bind(target);
    }

    /**
     * Returns the first valid implementation as a UnboundField or throws a
     * NoSuchFieldException if there is none.
     *
     * @param <T> Java class stored in the field
     * @return a {@link UnboundField} with a valid implementation
     * @throws RuntimeException if no implementation was found
     */
    @SuppressWarnings("unchecked")
    public <T> UnboundField<T> build() {
      if (field != null) {
        return (UnboundField<T>) field;
      } else if (defaultAlwaysNull) {
        return (UnboundField<T>) AlwaysNull.INSTANCE;
      } else {
        throw new RuntimeException("Cannot find field from candidates: " +
            Joiner.on(", ").join(candidates));
      }
    }

    /**
     * Returns the first valid implementation as a BoundMethod or throws a
     * RuntimeException if there is none.
     *
     * @param target an Object on which to get and set the field
     * @param <T> Java class stored in the field
     * @return a {@link BoundField} with a valid implementation and target
     * @throws IllegalStateException if the method is static
     * @throws IllegalArgumentException if the receiver's class is incompatible
     * @throws RuntimeException if no implementation was found
     */
    public <T> BoundField<T> build(Object target) {
      return this.<T>build().bind(target);
    }

    /**
     * Returns the first valid implementation as a StaticField or throws a
     * NoSuchFieldException if there is none.
     *
     * @param <T> Java class stored in the field
     * @return a {@link StaticField} with a valid implementation
     * @throws IllegalStateException if the method is not static
     * @throws NoSuchFieldException if no implementation was found
     */
    public <T> StaticField<T> buildStaticChecked() throws NoSuchFieldException {
      return this.<T>buildChecked().asStatic();
    }

    /**
     * Returns the first valid implementation as a StaticField or throws a
     * RuntimeException if there is none.
     *
     * @param <T> Java class stored in the field
     * @return a {@link StaticField} with a valid implementation
     * @throws IllegalStateException if the method is not static
     * @throws RuntimeException if no implementation was found
     */
    public <T> StaticField<T> buildStatic() {
      return this.<T>build().asStatic();
    }

  }

  private static class MakeFieldAccessible implements PrivilegedAction<Void> {
    private Field hidden;

    MakeFieldAccessible(Field hidden) {
      this.hidden = hidden;
    }

    @Override
    public Void run() {
      hidden.setAccessible(true);
      return null;
    }
  }
}
