/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.idea.blaze.base.model.blaze.deepequalstester;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.junit.Assert;

import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public final class ReachabilityAnalysis {

  /**
   * Wrapper around a map from class to set of paths that lead to that path from the root object
   */
  public static final class ReachableClasses {

    Map<Class<? extends Serializable>, Set<List<String>>> map;

    public ReachableClasses() {
      map = Maps.newHashMap();
    }

    boolean alreadyFound(Class<? extends Serializable> clazz) {
      return map.containsKey(clazz);
    }

    void addPath(Class<? extends Serializable> clazz, List<String> path) {
      Set<List<String>> paths;
      if (map.containsKey(clazz)) {
        paths = map.get(clazz);
      }
      else {
        paths = Sets.newHashSet();
        map.put(clazz, paths);
      }
      paths.add(path);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder();

      Set<? extends Entry<Class<? extends Serializable>, ? extends Set<? extends List<String>>>> entries = map
        .entrySet();
      for (Entry<Class<? extends Serializable>, ? extends Set<? extends List<String>>> entry : entries) {
        sb.append(entry.getKey().toString());
        sb.append("\n");
      }

      return sb.toString();
    }

    public Set<Class<? extends Serializable>> getClasses() {
      return map.keySet();
    }

    public List<String> getExamplePathTo(Class<? extends Serializable> aClass) {
      if (map.containsKey(aClass)) {
        return map.get(aClass).iterator().next();
      }
      return Lists.newArrayList();
    }
  }

  /**
   * Find all of the classes reachable from a root object
   *
   * @param root              object to start reachability calculation from
   * @param declaredRootClass declared class of the root object
   * @param currentPath       field access path to get to root
   * @param reachableClasses  output: add classes reachable from root to this object
   * @throws IllegalAccessException
   * @throws ClassNotFoundException
   */
  public static void computeReachableFromObject(Object root, Class<?> declaredRootClass,
                                                List<String> currentPath, ReachableClasses reachableClasses)
    throws IllegalAccessException, ClassNotFoundException {
    final Class<?> concreteRootClass = DeepEqualsTesterUtil.getClass(declaredRootClass, root);
    List<Field> allFields = DeepEqualsTesterUtil.getAllFields(concreteRootClass);
    for (Field field : allFields) {
      if (!Modifier.isStatic(field.getModifiers())) {
        field.setAccessible(true);
        final Object fieldObject;
        if (root == null) {
          fieldObject = null;
        }
        else {
          fieldObject = field.get(root);
        }
        List<String> childPath = Lists.newArrayList();
        childPath.addAll(currentPath);
        childPath.add(field.toString());
        addToReachableAndRecurse(fieldObject, field.getType(), field.getGenericType(),
                                 childPath, reachableClasses);
      }
    }
  }

  /**
   * Determine the action we should take based on the type of Object and then take it. In the
   * normal object case, this results in a recursive call to
   * {@link #computeReachableFromObject(Object, Class, List, ReachableClasses)}. In the case of
   * Collections, we skip the Collection type and continue on with the type contained in the
   * collection.
   */
  private static void addToReachableAndRecurse(Object object, Class<?> declaredObjectClass,
                                               Type genericType, List<String> currentPath, ReachableClasses reachableClasses)
    throws ClassNotFoundException, IllegalAccessException {
    Class<? extends Serializable> objectType = DeepEqualsTesterUtil
      .getClass(declaredObjectClass, object);
    // TODO(salguarnieri) modify if so all ignored classes are taken care of together
    if (objectType.isPrimitive()) {
      // ignore
    }
    else if (objectType.isEnum()) {
      // assume enums do the right thing, ignore
    }
    else if (DeepEqualsTesterUtil.isSubclassOf(objectType, String.class)) {
      // ignore
    }
    else if (DeepEqualsTesterUtil.isSubclassOf(objectType, File.class)) {
      // ignore
    }
    else if (DeepEqualsTesterUtil.isSubclassOf(objectType, Collection.class) || DeepEqualsTesterUtil
      .isSubclassOf(objectType, Map.class)) {
      if (genericType instanceof ParameterizedType) {
        ParameterizedType parameterType = (ParameterizedType)genericType;
        Type[] actualTypeArguments = parameterType.getActualTypeArguments();
        for (Type typeArgument : actualTypeArguments) {
          if (typeArgument instanceof Class) {
            List<String> childPath = Lists.newArrayList();
            childPath.addAll(currentPath);
            childPath.add("[[IN COLLECTION]]");
            // this does not properly handle subtyping
            addToReachableAndRecurse(null, (Class)typeArgument, null, childPath,
                                     reachableClasses);
          }
          else {
            Assert.fail("This case is not handled yet");
          }
        }
      }
      else {
        Assert.fail("This case is not handled yet");
      }
    }
    else if (objectType.isArray()) {
      Class<?> typeInArray = objectType.getComponentType();
      // This does not properly handle subtyping
      List<String> childPath = Lists.newArrayList();
      childPath.addAll(currentPath);
      childPath.add("[[IN ARRAY]]");
      addToReachableAndRecurse(null, typeInArray, null, childPath, reachableClasses);
    }
    else {
      boolean doRecursion = !reachableClasses.alreadyFound(objectType);
      reachableClasses.addPath(objectType, currentPath);
      if (doRecursion) {
        computeReachableFromObject(object, declaredObjectClass, currentPath, reachableClasses);
      }
    }
  }
}
