/*
 * 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.geronimo.arthur.impl.nativeimage.generator;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.geronimo.arthur.impl.nativeimage.ArthurNativeImageConfiguration;
import org.apache.geronimo.arthur.spi.ArthurExtension;
import org.apache.geronimo.arthur.spi.model.ClassReflectionModel;
import org.apache.geronimo.arthur.spi.model.DynamicProxyModel;
import org.apache.geronimo.arthur.spi.model.ResourcesModel;

import java.io.IOException;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Collections.singletonList;
import static java.util.Comparator.comparing;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

@Slf4j
@RequiredArgsConstructor
public class ConfigurationGenerator implements Runnable {
    private final List<ArthurExtension> extensions;
    private final ArthurNativeImageConfiguration configuration;
    private final Path workingDirectory;
    private final BiConsumer<Object, Writer> jsonSerializer;
    private final Function<Class<? extends Annotation>, Collection<Class<?>>> classFinder;
    private final Function<Class<?>, Collection<Class<?>>> implementationFinder;
    private final Function<Class<? extends Annotation>, Collection<Method>> methodFinder;
    private final Map<String, String> extensionProperties;

    public ConfigurationGenerator(final Iterable<ArthurExtension> extensions, final ArthurNativeImageConfiguration configuration,
                                  final Path workingDirectory, final BiConsumer<Object, Writer> jsonSerializer,
                                  final Function<Class<? extends Annotation>, Collection<Class<?>>> classFinder,
                                  final Function<Class<? extends Annotation>, Collection<Method>> methodFinder,
                                  final Function<Class<?>, Collection<Class<?>>> implementationFinder,
                                  final Map<String, String> extensionProperties) {
        this.extensions = StreamSupport.stream(extensions.spliterator(), false).collect(toList());
        this.configuration = configuration;
        this.workingDirectory = workingDirectory;
        this.jsonSerializer = jsonSerializer;
        this.classFinder = classFinder;
        this.methodFinder = methodFinder;
        this.implementationFinder = implementationFinder;
        this.extensionProperties = extensionProperties;
    }

    @Override
    public void run() {
        // ensure to have a writtable instance (see Context#setProperty(String, String))
        final HashMap<String, String> properties = ofNullable(this.extensionProperties).map(HashMap::new).orElseGet(HashMap::new);
        properties.put("workingDirectory", workingDirectory.toAbsolutePath().toString());

        final DefautContext context = new DefautContext(configuration, classFinder, methodFinder, implementationFinder, properties);
        for (final ArthurExtension extension : extensions) {
            log.debug("Executing {}", extension);
            context.setModified(false);
            extension.execute(context);
            if (context.isModified()) { // todo: loop while it modifies the context?
                log.info("Extension {} updated build context", extension.getClass().getName());
            }
        }
        try {
            updateConfiguration(context);
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        }
    }

    private void updateConfiguration(final DefautContext context) throws IOException {
        if (!context.getReflections().isEmpty()) {
            ensureWorkingDirectoryExists();
            final Path json = workingDirectory.resolve("reflection.arthur.json");
            log.info("Creating reflection model '{}'", json);
            try (final Writer writer = Files.newBufferedWriter(
                    json, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
                jsonSerializer.accept(
                        context.getReflections().stream()
                                .collect(groupingBy(ClassReflectionModel::getName))
                                .values().stream()
                                .map(this::merge)
                                .sorted(comparing(ClassReflectionModel::getName))
                                .collect(toList()),
                        writer);
            }
            context.addReflectionConfigFile(json.toAbsolutePath().toString());
        }
        if (!context.getResources().isEmpty() || !context.getBundles().isEmpty()) {
            final ResourcesModel resourcesModel = new ResourcesModel();
            if (!context.getResources().isEmpty()) {
                resourcesModel.setResources(context.getResources());
            }
            if (!context.getBundles().isEmpty()) {
                resourcesModel.setBundles(context.getBundles());
            }
            ensureWorkingDirectoryExists();
            final Path json = workingDirectory.resolve("resources.arthur.json");
            log.info("Creating resources model '{}'", json);
            try (final Writer writer = Files.newBufferedWriter(
                    json, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
                jsonSerializer.accept(resourcesModel, writer);
            }
            context.addResourcesConfigFile(json.toAbsolutePath().toString());
        }
        if (!context.getDynamicProxyModels().isEmpty()) {
            final Set<Collection<String>> proxies = context.getDynamicProxyModels().stream()
                    .map(DynamicProxyModel::getClasses)
                    .collect(toSet());

            ensureWorkingDirectoryExists();
            final Path json = workingDirectory.resolve("dynamicproxies.arthur.json");
            log.info("Creating dynamic proxy model '{}'", json);
            try (final Writer writer = Files.newBufferedWriter(
                    json, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
                jsonSerializer.accept(proxies, writer);
            }
            context.addDynamicProxiesConfigFile(json.toAbsolutePath().toString());
        }
        if (!context.getDynamicClasses().isEmpty()) {
            final Path dynamicClassesDir = workingDirectory.resolve("dynamic_classes");
            context.getDynamicClasses().forEach((name, content) -> {
                final Path target = dynamicClassesDir.resolve(name.replace('.', '/') + ".class");
                if (!Files.exists(target.getParent())) {
                    try {
                        Files.createDirectories(target.getParent());
                    } catch (final IOException e) {
                        throw new IllegalStateException(e);
                    }
                }
                try {
                    Files.write(target, content, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
                } catch (final IOException e) {
                    throw new IllegalStateException(e);
                }
            });
            log.info("Dumped generated classes in '{}'", dynamicClassesDir);
            if (configuration.getClasspath() == null) {
                configuration.setClasspath(singletonList(dynamicClassesDir.toString()));
            } else {
                configuration.setClasspath(Stream.concat(
                        configuration.getClasspath().stream(),
                        Stream.of(dynamicClassesDir.toString())
                ).distinct().collect(toList()));
            }
        }
    }

    private ClassReflectionModel merge(final List<ClassReflectionModel> classReflectionModels) {
        final Iterator<ClassReflectionModel> modelIterator = classReflectionModels.iterator();
        final ClassReflectionModel model = modelIterator.next();
        while (modelIterator.hasNext()) {
            final ClassReflectionModel next = modelIterator.next();
            if (next.getAllDeclaredClasses()) {
                model.setAllDeclaredClasses(true);
            }
            if (next.getAllDeclaredFields()) {
                model.setAllDeclaredFields(true);
            }
            if (next.getAllDeclaredConstructors()) {
                model.setAllDeclaredConstructors(true);
            }
            if (next.getAllDeclaredMethods()) {
                model.setAllDeclaredMethods(true);
            }
            if (next.getAllPublicMethods()) {
                model.setAllPublicMethods(true);
            }
            if (next.getAllPublicFields()) {
                model.setAllPublicFields(true);
            }
            if (next.getAllPublicConstructors()) {
                model.setAllPublicConstructors(true);
            }
            if (next.getAllPublicClasses()) {
                model.setAllPublicClasses(true);
            }
        }
        return model;
    }

    private void ensureWorkingDirectoryExists() throws IOException {
        if (!Files.exists(workingDirectory)) {
            Files.createDirectories(workingDirectory);
        }
    }
}
