/*
 * 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.meecrowave.runner;

import org.apache.catalina.Server;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardServer;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.ParseException;
import org.apache.meecrowave.Meecrowave;
import org.apache.meecrowave.runner.cli.CliOption;
import org.apache.xbean.recipe.ObjectRecipe;

import javax.enterprise.inject.Vetoed;
import java.io.File;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

@Vetoed
public class Cli implements Runnable, AutoCloseable {
    private final String[] args;
    private volatile Meecrowave instance;
    private volatile boolean closed;

    public Cli(final String[] args) {
        this.args = args;
    }

    public void run() {
        final ParsedCommand parsedCommand = new ParsedCommand(args).invoke();
        if (parsedCommand.isFailed()) {
            return;
        }

        final Meecrowave.Builder builder = parsedCommand.getBuilder();
        final CommandLine line = parsedCommand.getLine();
        try (final Meecrowave meecrowave = new Meecrowave(builder)) {
            synchronized (this) {
                if (closed) {
                    return;
                }
                this.instance = meecrowave;
            }

            final String ctx = line.getOptionValue("context", "");
            final String fixedCtx = !ctx.isEmpty() && !ctx.startsWith("/") ? '/' + ctx : ctx;
            final String war = line.getOptionValue("webapp");
            meecrowave.start();
            if (war == null) {
                meecrowave.deployClasspath(new Meecrowave.DeploymentMeta(
                        ctx,
                        ofNullable(line.getOptionValue("docbase")).map(File::new).orElseGet(() ->
                                Stream.of("base", "home")
                                    .map(it -> System.getProperty("meecrowave." + it))
                                    .filter(Objects::nonNull)
                                    .map(it -> new File(it, "docBase"))
                                    .filter(File::isDirectory)
                                    .findFirst()
                                    .orElse(null)),
                        null));
            } else {
                meecrowave.deployWebapp(fixedCtx, new File(war));
            }
            doWait(meecrowave, line);
        }
    }

    protected void doWait(final Meecrowave meecrowave, final CommandLine line) {
        meecrowave.getTomcat().getServer().await();
    }

    @Override
    public synchronized void close() {
        if (closed) {
            return;
        }
        this.closed = true;
        if (instance != null) {
            final Server server = instance.getTomcat().getServer();
            if (StandardServer.class.isInstance(server)) {
                StandardServer.class.cast(server).stopAwait();
            }
        }
    }

    public static void main(final String[] args) {
        new Cli(args).run();
    }

    // utility when user wraps the command, it enables him to manage the instance but reuse most of our options
    public static Meecrowave.Builder create(final String[] args) {
        final ParsedCommand command = new ParsedCommand(args).invoke();
        if (command.isFailed()) {
            return null;
        }
        return command.getBuilder();
    }

    private static void bind(final Meecrowave.Builder builder, final CommandLine line, final List<Field> fields, final Object config) {
        fields.forEach(f -> {
            final CliOption opt = f.getAnnotation(CliOption.class);
            final Optional<String> first = Stream.of(Stream.of(opt.name()), Stream.of(opt.alias()))
                    .flatMap(a -> a)
                    .filter(line::hasOption)
                    .findFirst();
            if (first.isPresent()) {
                final String name = first.get();
                ofNullable(f.getType() == boolean.class ?
                        ofNullable(line.getOptionValue(name)).map(Boolean::parseBoolean).orElse(true) :
                        toValue(builder, name, line.getOptionValues(name), f.getType()))
                        .ifPresent(v -> {
                            if (!f.isAccessible()) {
                                f.setAccessible(true);
                            }
                            try {
                                f.set(config, v);
                            } catch (final IllegalAccessException e) {
                                throw new IllegalStateException(e);
                            }
                        });
            }
        });
    }

    private static Object toValue(final Meecrowave.Builder builder, final String name, final String[] optionValues, final Class<?> type) {
        if (optionValues == null || optionValues.length == 0) {
            return null;
        }

        // decode options while it is strings
        IntStream.range(0, optionValues.length)
                .forEach(i -> optionValues[i] = builder.getExtension(Meecrowave.ValueTransformers.class).apply(optionValues[i]));

        if (String.class == type) {
            return optionValues[0];
        }
        if (int.class == type) {
            return Integer.parseInt(optionValues[0]);
        }
        if (File.class == type) {
            return new File(optionValues[0]);
        }
        if (Properties.class == type) {
            final Properties props = new Properties();
            Stream.of(optionValues).map(v -> v.split("=")).forEach(v -> props.setProperty(v[0], v[1]));
            return props;
        }
        if (Map.class == type) {
            final Map<String, String> props = new HashMap<>();
            Stream.of(optionValues).map(v -> v.split("=")).forEach(v -> props.put(v[0], v[1]));
            return props;
        }

        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
        switch (name) {
            case "realm": // org.foo.Impl:attr1=val1;attr2=val2
                try {
                    int end = optionValues[0].indexOf(':');
                    if (end < 0) {
                        return loader.loadClass(optionValues[0]).newInstance();
                    }
                    final ObjectRecipe recipe = new ObjectRecipe(optionValues[0].substring(0, end));
                    Stream.of(optionValues[0].substring(end + 1, optionValues[0].length()).split(";"))
                            .map(v -> v.split("="))
                            .forEach(v -> recipe.setProperty(v[0], v[1]));
                    return recipe.create(loader);
                } catch (final Exception cnfe) {
                    throw new IllegalArgumentException(optionValues[0]);
                }
            case "security-constraint": // attr1=val1;attr2=val2
                return Stream.of(optionValues)
                        .map(item -> {
                            try {
                                final ObjectRecipe recipe = new ObjectRecipe(Meecrowave.SecurityConstaintBuilder.class);
                                Stream.of(item.split(";"))
                                        .map(v -> v.split("="))
                                        .forEach(v -> recipe.setProperty(v[0], v[1]));
                                return recipe.create(loader);
                            } catch (final Exception cnfe) {
                                throw new IllegalArgumentException(optionValues[0]);
                            }
                        }).collect(toList());
            case "login-config":
                try {
                    final ObjectRecipe recipe = new ObjectRecipe(Meecrowave.LoginConfigBuilder.class);
                    Stream.of(optionValues[0].split(";"))
                            .map(v -> v.split("="))
                            .forEach(v -> recipe.setProperty(v[0], v[1]));
                    return recipe.create(loader);
                } catch (final Exception cnfe) {
                    throw new IllegalArgumentException(optionValues[0]);
                }
            case "connector": // org.foo.Impl:attr1=val1;attr2=val2
                return Stream.of(optionValues)
                        .map(v -> {
                            try {
                                int end = v.indexOf(':');
                                if (end < 0) {
                                    return new Connector(v);
                                }
                                final Connector connector = new Connector(optionValues[0].substring(0, end));
                                Stream.of(v.substring(end + 1, v.length()).split(";"))
                                        .map(i -> i.split("="))
                                        .forEach(i -> connector.setProperty(i[0], i[1]));
                                return connector;
                            } catch (final Exception cnfe) {
                                throw new IllegalArgumentException(optionValues[0]);
                            }
                        }).collect(toList());
            default:
                throw new IllegalArgumentException("Unsupported " + name);
        }
    }

    public interface Options {
    }

    private static final class ParsedCommand {
        private final String[] args;
        private boolean failed;
        private CommandLine line;
        private Meecrowave.Builder builder;

        private ParsedCommand(final String... args) {
            this.args = args;
        }

        private static void help(final org.apache.commons.cli.Options options) {
            new HelpFormatter().printHelp("java -jar meecrowave-runner.jar", options);
        }

        private static Meecrowave.Builder buildConfig(final CommandLine line, final List<Field> fields,
                                                      final Map<Object, List<Field>> propertiesOptions) {
            final Meecrowave.Builder config = new Meecrowave.Builder();
            bind(config, line, fields, config);
            propertiesOptions.forEach((o, f) -> {
                bind(config, line, f, o);
                config.setExtension(o.getClass(), o);
            });
            return config;
        }

        boolean isFailed() {
            return failed;
        }

        public CommandLine getLine() {
            return line;
        }

        public Meecrowave.Builder getBuilder() {
            return builder;
        }

        public ParsedCommand invoke() {
            final org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
            options.addOption(null, "help", false, "Show help");
            options.addOption(null, "context", true, "The context to use to deploy the webapp");
            options.addOption(null, "webapp", true, "Location of the webapp, if not set the classpath will be deployed");
            options.addOption(null, "docbase", true, "Location of the docbase for a classpath deployment");
            final List<Field> fields = Stream.of(Meecrowave.Builder.class.getDeclaredFields())
                    .filter(f -> f.isAnnotationPresent(CliOption.class))
                    .collect(toList());
            final Map<Object, List<Field>> propertiesOptions = StreamSupport.stream(ServiceLoader.load(Options.class).spliterator(), false)
                    .collect(toMap(identity(), o -> Stream.of(o.getClass().getDeclaredFields()).filter(f -> f.isAnnotationPresent(CliOption.class)).collect(toList())));
            fields.forEach(f -> {
                final CliOption opt = f.getAnnotation(CliOption.class);
                final String description = opt.description();
                options.addOption(null, opt.name(), true /*even for booleans otherwise no way to set false for true by default ones*/, description);
                Stream.of(opt.alias()).forEach(a -> options.addOption(null, a, true, description));
            });
            propertiesOptions.values().forEach(all -> all.forEach(f -> {
                final CliOption opt = f.getAnnotation(CliOption.class);
                final String description = opt.description();
                options.addOption(null, opt.name(), true, description);
                Stream.of(opt.alias()).forEach(a -> options.addOption(null, a, true, description));
            }));

            final CommandLineParser parser = new DefaultParser();
            try {
                line = parser.parse(options, args, true);
            } catch (final ParseException exp) {
                help(options);
                failed = true;
                return this;
            }

            if (line.hasOption("help")) {
                help(options);
                failed = true;
                return this;
            }

            builder = buildConfig(line, fields, propertiesOptions);
            failed = false;
            return this;
        }
    }
}
