package eu.jonahbauer.wizard.client.cli.util;

import eu.jonahbauer.wizard.client.cli.Client;
import eu.jonahbauer.wizard.client.cli.state.ClientState;
import picocli.CommandLine;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

public class StateAwareFactory implements CommandLine.IFactory {
    private final CommandLine.IFactory defaultFactory = CommandLine.defaultFactory();
    private final Client client;
    private final ClientState clientState;

    public StateAwareFactory(Client client, ClientState clientState) {
        this.client = client;
        this.clientState = clientState;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <K> K create(Class<K> cls) throws Exception {
        try {
            return defaultFactory.create(cls);
        } catch (Exception e) {
            c: for (Constructor<K> constructor : (Constructor<K>[]) cls.getDeclaredConstructors()) {
                Object[] values = new Object[constructor.getParameterCount()];
                Parameter[] parameters = constructor.getParameters();
                for (int i = 0; i < parameters.length; i++) {
                    Parameter parameter = parameters[i];
                    if (ClientState.class.isAssignableFrom(parameter.getType())) {
                        values[i] = clientState;
                    } else if (Client.class.isAssignableFrom(parameter.getType())) {
                        values[i] = client;
                    } else {
                        continue c;
                    }
                }

                constructor.setAccessible(true);
                return constructor.newInstance(values);
            }

            var e2 = new NoSuchMethodException("Could not find a suitable constructor for class " + cls.getName());
            e2.addSuppressed(e);
            throw e2;
        }
    }
}
