/*
 * 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 static com.facebook.buck.model.BuildTarget.BUILD_TARGET_PREFIX;

import com.facebook.buck.model.BuildTarget;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.primitives.Primitives;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;

import javax.annotation.Nullable;

/**
 * Parameter information derived from the object returned by
 * {@link Description#getConstructorArg()}.
 */
// DO NOT EXPOSE OUT OF PACKAGE.
class ParamInfo implements Comparable<ParamInfo> {
  private final String name;

  /**
   * Is the property optional (indicated by being Optional or @Hinted with a default value.
   */
  private final boolean isOptional;

  /**
   * If the value is a List or Set, which of the two is it.
   */
  @Nullable
  private final Class<?> containerType;

  /**
   * The type of the field, or the contained type of an Optional or a Collection.
   */
  private final Class<?> type;
  private final Path pathRelativeToProjectRoot;

  private Field field;

  /**
   * @param pathRelativeToProjectRoot The path to the directory containing the build file this param
   *     is for.
   * @param field The field in the constructor arg that this represents.
   */
  public ParamInfo(Path pathRelativeToProjectRoot, Field field) {
    this.pathRelativeToProjectRoot = Preconditions.checkNotNull(pathRelativeToProjectRoot);

    this.field = Preconditions.checkNotNull(field);
    Hint hint = field.getAnnotation(Hint.class);
    this.name = determineName(field.getName(), hint);

    Class<?> rawType = field.getType();
    Type genericType = field.getGenericType();

    this.isOptional = Optional.class.isAssignableFrom(rawType);

    // TODO(simons): Check for a wildcard here.
    if (List.class.isAssignableFrom(rawType) || Set.class.isAssignableFrom(rawType)) {
      this.containerType = rawType;
      this.type = determineGenericType(genericType);
    } else if (Optional.class.isAssignableFrom(rawType)) {
      this.type = unwrapGenericType(genericType);

      Class<?> container = null;

      if (genericType instanceof ParameterizedType) {
        Type containerType = ((ParameterizedType) genericType).getActualTypeArguments()[0];
        if (containerType instanceof ParameterizedType) {
          Type rawContainerType = ((ParameterizedType) containerType).getRawType();
          if (!(rawContainerType instanceof Class)) {
            throw new RuntimeException("Container type isn't a class: " + rawContainerType);
          }
          container = (Class<?>) rawContainerType;
          if (!Collection.class.isAssignableFrom(container)) {
            throw new RuntimeException("Cannot determine container type: " + container);
          }
        }
      }
      containerType = container;
    } else {
      this.containerType = null;
      this.type = Primitives.wrap(rawType);
    }
  }

  String getName() {
    return name;
  }

  boolean isOptional() {
    return isOptional;
  }

  @Nullable
  Class<?> getContainerType() {
    return containerType;
  }

  Class<?> getType() {
    return type;
  }

  private Class<?> unwrapGenericType(Type type) {
    if (!(type instanceof ParameterizedType)) {
      return (Class<?>) type;
    }

    Type[] types = ((ParameterizedType) type).getActualTypeArguments();
    if (types.length != 1) {
      throw new IllegalArgumentException("Unable to determine generic type");
    }

    if (types[0] instanceof WildcardType) {
      throw new IllegalStateException("Generic types must be specific: " + type);
    }

    if (types[0] instanceof ParameterizedType) {
      return unwrapGenericType(types[0]);
    }
    return (Class<?>) types[0];
  }

  private String determineName(String name, @Nullable Hint hint) {
    return hint == null ? name : hint.name();
  }

  private Class<?> determineGenericType(Type genericType) {
    if (!(genericType instanceof ParameterizedType)) {
      throw new IllegalArgumentException("Collection type was not generic");
    }

    Type[] types = ((ParameterizedType) genericType).getActualTypeArguments();
    if (types.length != 1) {
      throw new IllegalArgumentException("Unable to determine generic type");
    }

    if (types[0] instanceof WildcardType) {
      WildcardType wild = (WildcardType) types[0];

      if (Object.class.equals(wild.getUpperBounds()[0])) {
        throw new IllegalArgumentException("Generic types must be specific: " + genericType);
      }
      return Primitives.wrap((Class<?>) wild.getUpperBounds()[0]);
    }

    return Primitives.wrap((Class<?>) types[0]);
  }

  public void setFromParams(
      BuildRuleResolver ruleResolver,
      Object dto,
      BuildRuleFactoryParams params) {
    if (containerType != null) {
      set(ruleResolver, dto, params.getOptionalListAttribute(name));
    } else if (Path.class.isAssignableFrom(type) ||
        SourcePath.class.isAssignableFrom(type) ||
        String.class.equals(type)) {
      set(ruleResolver, dto, params.getOptionalStringAttribute(name).orNull());
    } else if (Number.class.isAssignableFrom(type)) {
      set(ruleResolver, dto, params.getRequiredLongAttribute(name));
    } else if (BuildTarget.class.isAssignableFrom(type)) {
      Optional<BuildTarget> optionalTarget = params.getOptionalBuildTarget(name);
      set(ruleResolver, dto, optionalTarget.orNull());
    } else if (BuildRule.class.isAssignableFrom(type)) {
      Optional<BuildTarget> optionalTarget = params.getOptionalBuildTarget(name);
      set(ruleResolver, dto, optionalTarget.orNull());
    } else if (Boolean.class.equals(type)) {
      set(ruleResolver, dto, params.getBooleanAttribute(name));
    } else {
      throw new RuntimeException("Unknown type: " + type);
    }
  }

  /**
   * Sets a single property of the {@code dto}, coercing types as necessary.
   *
   * @param resolver {@link com.facebook.buck.rules.BuildRuleResolver} used for {@link com.facebook.buck.rules.BuildRule} instances.
   * @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(BuildRuleResolver resolver, Object dto, @Nullable Object value) {
    if (value == null) {
      if (!isOptional) {
        throw new IllegalArgumentException(String.format(
            "%s cannot be null. Build file can be found in %s.",
            dto, pathRelativeToProjectRoot));
      }

      value = Optional.absent();
    } else if (isOptional && matchesDefaultValue(value)) {
      if (value instanceof Collection) {
        value = asCollection(resolver, Lists.newArrayList());
        value = Optional.of(value);
      } else {
        value = Optional.absent();
      }
    } else if (containerType == null) {
      value = coerceToExpectedType(resolver, value);
      if (isOptional) {
        value = Optional.of(value);
      }
    } else {
      value = asCollection(resolver, value);
      if (isOptional) {
        value = Optional.of(value);
      }
    }

    try {
      field.set(dto, value);
    } catch (ReflectiveOperationException e) {
      throw new RuntimeException(e);
    } catch (ClassCastException | IllegalArgumentException | NullPointerException e) {
      throw new IllegalArgumentException(String.format(
          "Unable to convert '%s' to %s in build file in %s",
          value, type, pathRelativeToProjectRoot));
    }
  }

  private boolean matchesDefaultValue(Object value) {
    if (value instanceof String && "".equals(value)) {
      return true;
    }

    if (value instanceof Number && ((Number)value).intValue() == 0) {
      return true;
    }

    if (Boolean.FALSE.equals(value)) {
      return true;
    }

    if (value instanceof List && ((List) value).isEmpty()) {
      return true;
    }

    return false;
  }

  private Object coerceToExpectedType(BuildRuleResolver ruleResolver, Object value) {
    if (BuildRule.class.isAssignableFrom(type)) {
      BuildTarget target = asBuildTarget(value);
      return ruleResolver.get(target);
    }

    if (BuildTarget.class.isAssignableFrom(type)) {
      return asBuildTarget(value);
    }

    // All paths should be relative to the base path.
    if (Path.class.isAssignableFrom(type)) {
      return asNormalizedPath(value);
    }

    if (SourcePath.class.isAssignableFrom(type)) {
      BuildTarget target = asBuildTarget(value);
      if (target != null) {
        return new BuildTargetSourcePath(target);
      }
      Path path = asNormalizedPath(value);
      return new FileSourcePath(pathRelativeToProjectRoot.relativize(path).toString());
    }

    if (value instanceof Number) {
      Number num = (Number) value;
      if (Double.class.equals(type)) {
        return num.doubleValue();
      } else if (Integer.class.equals(type)) {
        return num.intValue();
      } else if (Float.class.equals(type)) {
        return num.floatValue();
      } else if (Long.class.equals(type)) {
        return num.longValue();  // not strictly necessary, but included for completeness.
      } else if (Short.class.equals(type)) {
        return num.shortValue();
      }
    }

    // We're going to cheat and let the JVM take the strain of converting between primitive and
    // object wrapper types, but it has a habit of coercing to a String that should be avoided.
    if (String.class.equals(type) && !String.class.equals(value.getClass())) {
      throw new IllegalArgumentException(
          String.format("Unable to convert '%s' to %s", value, type));
    }

    return value;
  }

  @Nullable
  private BuildTarget asBuildTarget(Object value) {
    if (value instanceof BuildTarget) {
      return (BuildTarget) value;
    }

    Preconditions.checkArgument(value instanceof String,
        "Expected argument '%s' to be a build target", value);

    String param = (String) value;
    int colon = param.indexOf(':');
    if (colon == 0 && param.length() > 1) {
      return new BuildTarget(
          BUILD_TARGET_PREFIX + pathRelativeToProjectRoot.toString(),
          param.substring(1));
    } else if (colon > 0 && param.length() > 2) {
      return new BuildTarget(param.substring(0, colon), param.substring(colon + 1));
    }
    return null;
  }

  private Path asNormalizedPath(Object value) {
    Preconditions.checkArgument(value instanceof String,
        "Expected argument '%s' to be a string in build file in %s",
        value, pathRelativeToProjectRoot);

    return pathRelativeToProjectRoot.resolve((String) value).normalize();
  }

  @SuppressWarnings("unchecked")
  private Object asCollection(BuildRuleResolver ruleResolver, Object value) {
    if (!(value instanceof Collection)) {
      throw new IllegalArgumentException(String.format(
          "May not set '%s' on a collection type in build file in %s",
          value, pathRelativeToProjectRoot));
    }

    List<Object> collection = Lists.newArrayList();

    for (Object obj : (Iterable<Object>) value) {
      collection.add(coerceToExpectedType(ruleResolver, obj));
    }

    if (SortedSet.class.isAssignableFrom(containerType)) {
      return ImmutableSortedSet.copyOf(collection);
    } else if (Set.class.isAssignableFrom(containerType)) {
      return ImmutableSet.copyOf(collection);
    } else {
      return ImmutableList.copyOf(collection);
    }
  }

  /**
   * Only valid when comparing {@link ParamInfo} instances from the same description.
   */
  @Override
  public int compareTo(ParamInfo 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());
  }
}
