/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.rules;

import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.parser.BuildTargetParser;
import com.facebook.buck.rules.coercer.CoerceFailedException;
import com.facebook.buck.rules.coercer.TypeCoercer;
import com.facebook.buck.rules.coercer.TypeCoercerFactory;
import com.facebook.buck.util.Types;
import com.google.common.base.CaseFormat;
import com.google.common.base.Optional;

import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Map;

import javax.annotation.Nullable;

class ParamInfo<T> implements Comparable<ParamInfo<T>> {

  private final TypeCoercer<?> typeCoercer;

  private final boolean isOptional;
  private final String name;
  private final String pythonName;
  private final boolean isDep;
  private final Field field;

  public ParamInfo(TypeCoercerFactory typeCoercerFactory, Field field) {
    this.field = field;
    this.name = field.getName();
    Hint hint = field.getAnnotation(Hint.class);
    this.pythonName = determinePythonName(this.name, hint);
    this.isDep = hint != null ? hint.isDep() : Hint.DEFAULT_IS_DEP;

    isOptional = Optional.class.isAssignableFrom(field.getType());
    this.typeCoercer = typeCoercerFactory.typeCoercerForType(Types.getFirstNonOptionalType(field));
  }

  public String getName() {
    return name;
  }

  public boolean isOptional() {
    return isOptional;
  }

  public String getPythonName() {
    return pythonName;
  }

  public boolean isDep() {
    return isDep;
  }

  /**
   * Returns the type that input values will be coerced to.
   * Return the type parameter of Optional if wrapped in Optional.
   */
  public Class<?> getResultClass() {
    return typeCoercer.getOutputClass();
  }

  public void traverse(Traversal traversal, T dto) {
    traverseHelper(typeCoercer, traversal, dto);
  }

  @SuppressWarnings("unchecked")
  private <U> void traverseHelper(TypeCoercer<U> typeCoercer, Traversal traversal, T dto) {
    U object;
    try {
      if (isOptional) {
        Optional<U> optional = (Optional<U>) field.get(dto);
        object = optional.orNull();
      } else {
        object = (U) field.get(dto);
      }
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    }

    if (object != null) {
      typeCoercer.traverse(object, traversal);
    }
  }

  public boolean hasElementTypes(final Class<?>... types) {
    return typeCoercer.hasElementClass(types);
  }

  public void setFromParams(
      ProjectFilesystem filesystem,
      BuildRuleFactoryParams params,
      Object arg,
      Map<String, ?> instance
      ) throws ParamInfoException {
    set(
        params.buildTargetParser,
        filesystem,
        params.target.getBasePath(),
        arg,
        instance.get(name));
  }

  /**
   * Sets a single property of the {@code dto}, coercing types as necessary.
   * @param filesystem {@link com.facebook.buck.io.ProjectFilesystem} used to ensure
   *        {@link java.nio.file.Path}s exist.
   * @param pathRelativeToProjectRoot The path relative to the project root that this DTO is for.
   * @param dto The constructor DTO on which the value should be set.
   * @param value The value, which may be coerced depending on the type on {@code dto}.
   */
  public void set(
      BuildTargetParser buildTargetParser,
      ProjectFilesystem filesystem,
      Path pathRelativeToProjectRoot,
      Object dto,
      @Nullable Object value) throws ParamInfoException {
    Object result;

    if (value == null) {
      if (isOptional) {
        result = typeCoercer.getOptionalValue();
      } else if (Number.class.isAssignableFrom(typeCoercer.getOutputClass())) {
        result = 0;
      } else if (Boolean.class.isAssignableFrom(typeCoercer.getOutputClass())) {
        result = false;
      } else {
        throw new ParamInfoException(name, "field cannot be null");
      }
    } else {
      try {
        result = typeCoercer.coerce(
            buildTargetParser,
            filesystem,
            pathRelativeToProjectRoot,
            value);
      } catch (CoerceFailedException e) {
        throw new ParamInfoException(name, e.getMessage(), e);
      }
      if (isOptional) {
        result = Optional.of(result);
      }
    }

    try {
      field.set(dto, result);
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Only valid when comparing {@link ParamInfo} instances from the same description.
   */
  @Override
  public int compareTo(ParamInfo<T> that) {
    return this.name.compareTo(that.name);
  }

  @Override
  public int hashCode() {
    return name.hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof ParamInfo)) {
      return false;
    }

    ParamInfo<?> that = (ParamInfo<?>) obj;
    return name.equals(that.getName());
  }

  private String determinePythonName(String javaName, @Nullable Hint hint) {
    if (hint != null && !Hint.DEFAULT_NAME.equals(hint.name())) {
      return hint.name();
    }
    return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, javaName);
  }

  public interface Traversal extends TypeCoercer.Traversal {}
}

