package de.dhbwstuttgart.core;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import de.dhbwstuttgart.server.SocketClient;
import de.dhbwstuttgart.util.Logger;

import java.io.File;
import java.io.IOException;
import java.util.*;

class Args {
    @Parameter(description = "Set destination directory", names = "-d")
    File outputPath;
    @Parameter(description = "Set class path", names = {"-cp", "-classpath"})
    String classpath;
    @Parameter(description = "[FILE]...")
    List<File> input;
    @Parameter(description = "Server mode", names = "--server-port")
    Integer serverPort;
    @Parameter(description = "Unify server url", names = "--unify-server")
    String serverUrl;
    @Parameter(description = "Write logs", names = "--write-logs")
    boolean writeLogs = false;
    @Parameter(names = "-v", description = "Verbosity level")
    int verbosity = 0;
    @Parameter(names = "--infer-together", description = "Runs the type inference on all input files together instead of sequentially")
    boolean inferTogether = false;
    @Parameter(names = "--help", help = true)
    boolean help;
}

public class ConsoleInterface {
    public static Logger.LogLevel logLevel = Logger.LogLevel.ERROR;
    public static boolean writeToConsole = true;
    public static boolean writeLogFiles = false;
    public static boolean inferTogether = false;
    public static Optional<String> unifyServerUrl = Optional.empty();

	public static void main(String[] argv) throws IOException, ClassNotFoundException {
        var args = new Args();
        var builder = JCommander.newBuilder().addObject(args).build();
        builder.setProgramName("javatx");
        try {
            builder.parse(argv);
            if (args.help) {
                builder.usage();
                return;
            }
        } catch (ParameterException e) {
            System.err.println(e.getMessage());
            System.err.println();
            builder.usage();
            System.exit(1);
        }

        inferTogether = args.inferTogether;
        unifyServerUrl = Optional.ofNullable(args.serverUrl);
        writeLogFiles = args.writeLogs;
        switch (args.verbosity) {
            case 1 -> logLevel = Logger.LogLevel.WARNING;
            case 2 -> logLevel = Logger.LogLevel.INFO;
            case 3 -> logLevel = Logger.LogLevel.DEBUG;
            default -> logLevel = Logger.LogLevel.ERROR;
        }


        if (args.serverPort != null) {
            if (unifyServerUrl.isPresent()) throw new RuntimeException("Cannot use unifyServer when in server mode!");
            JavaTXServer server = new JavaTXServer(args.serverPort);
            server.listen();
        } else {
            if (args.input == null) {
                System.err.println("No input files given. Get help with --help");
                System.exit(1);
            }
            List<File> classpath = args.classpath == null ? List.of() : Arrays.stream(args.classpath.split(File.pathSeparator)).map(File::new).toList();
            JavaTXCompiler compiler = new JavaTXCompiler(args.input, classpath, args.outputPath, inferTogether);
            compiler.generateBytecode();
            SocketClient.closeIfOpen();
        }
	}
}
