/**
 * 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.heron.eco.builder;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.heron.eco.definition.ConfigurationMethodDefinition;
import org.apache.heron.eco.definition.EcoExecutionContext;
import org.apache.heron.eco.definition.ObjectDefinition;

public class ObjectBuilder {
  private static final Logger LOG = LoggerFactory.getLogger(ObjectBuilder.class);

  private BuilderUtility builderUtility;

  public void setBuilderUtility(BuilderUtility builderUtility) {
    this.builderUtility = builderUtility;
  }

  @SuppressWarnings("rawtypes")
  public Object buildObject(ObjectDefinition def, EcoExecutionContext context)
      throws ClassNotFoundException, IllegalAccessException, InstantiationException,
      InvocationTargetException, NoSuchFieldException {
    Class clazz = builderUtility.classForName(def.getClassName());

    Object obj;
    if (def.hasConstructorArgs()) {
      LOG.debug("Found constructor arguments in definition ");
      List<Object> cArgs = def.getConstructorArgs();

      if (def.hasReferences()) {
        LOG.debug("The definition has references");
        cArgs = builderUtility.resolveReferences(cArgs, context);
      } else {
        LOG.debug("The definition does not have references");
      }
      LOG.debug("finding compatible constructor for : " + clazz.getName());
      Constructor con = findCompatibleConstructor(cArgs, clazz);
      if (con != null) {
        LOG.debug("Found something seemingly compatible, attempting invocation...");
        obj = con.newInstance(getArgsWithListCoercian(cArgs, con.getParameterTypes()));
      } else {
        String msg = String
            .format("Couldn't find a suitable constructor for class '%s' with arguments '%s'.",
            clazz.getName(),
            cArgs);
        throw new IllegalArgumentException(msg);
      }
    } else {
      obj = clazz.newInstance();
    }
    builderUtility.applyProperties(def, obj, context);
    invokeConfigMethods(def, obj, context);
    return obj;
  }

  @SuppressWarnings("rawtypes")
  protected Constructor findCompatibleConstructor(List<Object> args, Class target) {
    Constructor retval = null;
    int eligibleCount = 0;

    LOG.debug("Target class: " + target.getName() + ", constructor args: " + args);
    Constructor[] cons = target.getDeclaredConstructors();

    for (Constructor con : cons) {
      Class[] paramClasses = con.getParameterTypes();

      if (paramClasses.length == args.size()) {
        LOG.debug("found constructor with same number of args..");
        boolean invokable = canInvokeWithArgs(args, con.getParameterTypes());
        if (invokable) {
          retval = con;
          eligibleCount++;
        }
        LOG.debug("** invokable --> {}" + invokable);
      } else {
        LOG.debug("Skipping constructor with wrong number of arguments.");
      }
    }
    if (eligibleCount > 1) {
      LOG.error("Found multiple invokable constructors for class: "
          + target + ", given arguments " + args + ". Using the last one found.");
    }
    return retval;
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  protected boolean canInvokeWithArgs(List<Object> args, Class[] parameterTypes) {
    if (parameterTypes.length != args.size()) {
      LOG.warn("parameter types were the wrong size");
      return false;
    }

    for (int i = 0; i < args.size(); i++) {
      Object obj = args.get(i);
      if (obj == null) {
        throw new IllegalArgumentException("argument shouldn't be null - index: " + i);
      }
      Class paramType = parameterTypes[i];
      Class objectType = obj.getClass();
      LOG.debug("Comparing parameter class " + paramType + " to object class "
          + objectType + "to see if assignment is possible.");
      if (paramType.equals(objectType)) {
        LOG.debug("Yes, they are the same class.");
      } else if (paramType.isAssignableFrom(objectType)) {
        LOG.debug("Yes, assignment is possible.");
      } else if (isPrimitiveBoolean(paramType) && Boolean.class.isAssignableFrom(objectType)) {
        LOG.debug("Yes, assignment is possible.");
      } else if (isPrimitiveNumber(paramType) && Number.class.isAssignableFrom(objectType)) {
        LOG.debug("Yes, assignment is possible.");
      } else if (paramType.isEnum() && objectType.equals(String.class)) {
        LOG.debug("Yes, will convert a String to enum");
      } else if (paramType.isArray() && List.class.isAssignableFrom(objectType)) {
        LOG.debug("Assignment is possible if we convert a List to an array.");
        LOG.debug("Array Type: " + paramType.getComponentType() + ", List type: "
            + ((List) obj).get(0).getClass());
      } else {
        LOG.debug("returning false");
        return false;
      }
    }
    return true;
  }

  @SuppressWarnings("rawtypes")
  protected boolean isPrimitiveNumber(Class clazz) {
    return clazz.isPrimitive() && !clazz.equals(boolean.class);
  }

  @SuppressWarnings("rawtypes")
  protected boolean isPrimitiveBoolean(Class clazz) {
    return clazz.isPrimitive() && clazz.equals(boolean.class);
  }

  @SuppressWarnings("rawtypes")
  public void invokeConfigMethods(ObjectDefinition bean,
                                         Object instance, EcoExecutionContext context)
      throws InvocationTargetException, IllegalAccessException {

    List<ConfigurationMethodDefinition> methodDefs = bean.getConfigMethods();
    if (methodDefs == null || methodDefs.size() == 0) {
      return;
    }
    Class clazz = instance.getClass();
    for (ConfigurationMethodDefinition methodDef : methodDefs) {
      List<Object> args = methodDef.getArgs();
      if (args == null) {
        args = new ArrayList<Object>();
      }
      if (methodDef.hasReferences()) {
        args = builderUtility.resolveReferences(args, context);
      }
      String methodName = methodDef.getName();
      LOG.debug("method name: " + methodName);
      Method method = findCompatibleMethod(args, clazz, methodName);
      if (method != null) {
        Object[] methodArgs = getArgsWithListCoercian(args, method.getParameterTypes());
        method.invoke(instance, methodArgs);
      } else {
        String msg = String
            .format("Unable to find configuration method '%s' in class '%s' with arguments %s.",
            new Object[]{methodName, clazz.getName(), args});
        throw new IllegalArgumentException(msg);
      }
    }
  }

  @SuppressWarnings("rawtypes")
  private Method findCompatibleMethod(List<Object> args, Class target, String methodName) {
    Method retval = null;
    int eligibleCount = 0;
    LOG.debug("Target class: " + target.getName() + ",  methodName: "
        + methodName + ", args: " + args);
    Method[] methods = target.getMethods();
    LOG.debug("methods count: " + methods.length);
    for (Method method : methods) {
      Class[] paramClasses = method.getParameterTypes();
      if (paramClasses.length == args.size() && method.getName().equals(methodName)) {
        LOG.debug("found constructor with same number of args..");
        boolean invokable = false;
        if (args.size() == 0) {
          // it's a method with zero args
          invokable = true;
        } else {
          invokable = canInvokeWithArgs(args, method.getParameterTypes());
        }
        if (invokable) {
          retval = method;
          eligibleCount++;
        }
        LOG.debug("** invokable --> " + invokable);
      } else {
        LOG.debug("Skipping method with wrong number of arguments.");
      }
    }
    if (eligibleCount > 1) {
      LOG.warn("Found multiple invokable methods for class, method, given arguments {} "
          + new Object[]{target, methodName, args});
    }
    return retval;
  }



  /**
   * Given a java.util.List of contructor/method arguments, and a list of parameter types,
   * attempt to convert the
   * list to an java.lang.Object array that can be used to invoke the constructor.
   * If an argument needs
   * to be coerced from a List to an Array, do so.
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  private Object[] getArgsWithListCoercian(List<Object> args, Class[] parameterTypes) {
//        Class[] parameterTypes = constructor.getParameterTypes();
    if (parameterTypes.length != args.size()) {
      throw new IllegalArgumentException("Contructor parameter count does not "
          + "egual argument size.");
    }
    Object[] constructorParams = new Object[args.size()];

    // loop through the arguments, if we hit a list that has to be convered to an array,
    // perform the conversion
    for (int i = 0; i < args.size(); i++) {
      Object obj = args.get(i);
      Class paramType = parameterTypes[i];
      Class objectType = obj.getClass();
      LOG.debug("Comparing parameter class " + paramType.getName() + " to object class "
          +  objectType.getName() + " to see if assignment is possible.");
      if (paramType.equals(objectType)) {
        LOG.debug("They are the same class.");
        constructorParams[i] = args.get(i);
        continue;
      }
      if (paramType.isAssignableFrom(objectType)) {
        LOG.debug("Assignment is possible.");
        constructorParams[i] = args.get(i);
        continue;
      }
      if (isPrimitiveBoolean(paramType) && Boolean.class.isAssignableFrom(objectType)) {
        LOG.debug("Its a primitive boolean.");
        Boolean bool = (Boolean) args.get(i);
        constructorParams[i] = bool.booleanValue();
        continue;
      }
      if (isPrimitiveNumber(paramType) && Number.class.isAssignableFrom(objectType)) {
        LOG.debug("Its a primitive number.");
        Number num = (Number) args.get(i);
        if (paramType == Float.TYPE) {
          constructorParams[i] = num.floatValue();
        } else if (paramType == Double.TYPE) {
          constructorParams[i] = num.doubleValue();
        } else if (paramType == Long.TYPE) {
          constructorParams[i] = num.longValue();
        } else if (paramType == Integer.TYPE) {
          constructorParams[i] = num.intValue();
        } else if (paramType == Short.TYPE) {
          constructorParams[i] = num.shortValue();
        } else if (paramType == Byte.TYPE) {
          constructorParams[i] = num.byteValue();
        } else {
          constructorParams[i] = args.get(i);
        }
        continue;
      }

      // enum conversion
      if (paramType.isEnum() && objectType.equals(String.class)) {
        LOG.debug("Yes, will convert a String to enum");
        constructorParams[i] = Enum.valueOf(paramType, (String) args.get(i));
        continue;
      }

      // List to array conversion
      if (paramType.isArray() && List.class.isAssignableFrom(objectType)) {
        LOG.debug("Conversion appears possible...");
        List list = (List) obj;
        LOG.debug("Array Type: {}, List type: {}" + paramType.getComponentType()
            + list.get(0).getClass());

        // create an array of the right type
        Object newArrayObj = Array.newInstance(paramType.getComponentType(), list.size());
        for (int j = 0; j < list.size(); j++) {
          Array.set(newArrayObj, j, list.get(j));

        }
        constructorParams[i] = newArrayObj;
        LOG.debug("After conversion: {}" + constructorParams[i]);
      }
    }
    return constructorParams;
  }
}
