package de.renew.formalism.java;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;

import de.renew.util.StringUtil;

/**
 * Represents a suggestion for using a specific constructor.
 */
public class ConstructorSuggestion extends Suggestion {
    private final Constructor<?> _constructor;
    private final String[] _parameters;
    private final String _callWithParameters;

    /**
     * Creates a new suggestion for the given constructor.
     *
     * @param typeName the name of the type
     * @param constructor the constructor to be suggested
     */
    protected ConstructorSuggestion(String typeName, Constructor<?> constructor) {
        super(typeName, typeName);
        this._constructor = constructor;

        Class<?>[] parameterTypes = constructor.getParameterTypes();
        this._parameters = new String[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++) {
            this._parameters[i] = parameterTypes[i].getSimpleName();
        }

        this._callWithParameters = this._name + "(" + StringUtil.join(_parameters, ", ") + ")";
    }

    /**
     * Suggests all public constructors of the given class.
     *
     * @param clazz the class to analyze
     * @return a collection of constructor suggestions
     */
    public static Collection<ConstructorSuggestion> suggest(Class<?> clazz) {
        Collection<ConstructorSuggestion> suggestions = new ArrayList<>();
        Constructor<?>[] constructors = clazz.getConstructors();

        for (Constructor<?> constructor : constructors) {
            suggestions.add(new ConstructorSuggestion(clazz.getSimpleName(), constructor));
        }

        return suggestions;
    }

    /**
     * Returns the constructor this suggestion is based on.
     *
     * @return the suggested constructor
     */
    public Constructor<?> getConstructor() {
        return _constructor;
    }

    /**
     * Returns a string representing the constructor call with parameter types.
     *
     * @return the constructor call as a string
     */
    public String getCallWithParameters() {
        return _callWithParameters;
    }

    /**
     * Returns the parameter type names of the constructor.
     *
     * @return an array of parameter names
     */
    public String[] getParameters() {
        return _parameters;
    }

    @Override
    public String toString() {
        return "<html>" + getCallWithParameters() + " <font color=gray>- "
            + _constructor.getDeclaringClass().getSimpleName() + "</font></html>";
    }
}