/*
 * 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.camel.quarkus.core.deployment;

import java.io.IOException;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem;
import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
import io.quarkus.arc.processor.BuildExtension;
import io.quarkus.deployment.ApplicationArchive;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Overridable;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.recording.RecorderContext;
import io.quarkus.runtime.RuntimeValue;
import org.apache.camel.CamelContext;
import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
import org.apache.camel.quarkus.core.CamelConfig;
import org.apache.camel.quarkus.core.CamelMain;
import org.apache.camel.quarkus.core.CamelMainProducers;
import org.apache.camel.quarkus.core.CamelMainRecorder;
import org.apache.camel.quarkus.core.CamelProducers;
import org.apache.camel.quarkus.core.CamelRecorder;
import org.apache.camel.quarkus.core.CoreAttachmentsRecorder;
import org.apache.camel.quarkus.core.Flags;
import org.apache.camel.quarkus.core.UploadAttacher;
import org.apache.camel.quarkus.support.common.CamelCapabilities;
import org.apache.camel.spi.TypeConverterLoader;
import org.apache.camel.spi.TypeConverterRegistry;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class BuildProcessor {
    private static final Logger LOGGER = LoggerFactory.getLogger(BuildProcessor.class);

    private static final DotName ROUTES_BUILDER_TYPE = DotName.createSimple(
            "org.apache.camel.RoutesBuilder");
    private static final DotName ROUTE_BUILDER_TYPE = DotName.createSimple(
            "org.apache.camel.builder.RouteBuilder");
    private static final DotName ADVICE_WITH_ROUTE_BUILDER_TYPE = DotName.createSimple(
            "org.apache.camel.builder.AdviceWithRouteBuilder");
    private static final DotName DATA_FORMAT_TYPE = DotName.createSimple(
            "org.apache.camel.spi.DataFormat");
    private static final DotName LANGUAGE_TYPE = DotName.createSimple(
            "org.apache.camel.spi.Language");
    private static final DotName COMPONENT_TYPE = DotName.createSimple(
            "org.apache.camel.Component");
    private static final DotName PRODUCER_TYPE = DotName.createSimple(
            "org.apache.camel.Producer");
    private static final DotName PREDICATE_TYPE = DotName.createSimple(
            "org.apache.camel.Predicate");

    private static final Set<DotName> UNREMOVABLE_BEANS_TYPES = CamelSupport.setOf(
            ROUTES_BUILDER_TYPE,
            DATA_FORMAT_TYPE,
            LANGUAGE_TYPE,
            COMPONENT_TYPE,
            PRODUCER_TYPE,
            PREDICATE_TYPE);

    /*
     * Build steps related to camel core.
     */
    public static class Core {
        @BuildStep
        BeanRegistrationPhaseBuildItem.BeanConfiguratorBuildItem containerBeans(
                BeanRegistrationPhaseBuildItem beanRegistrationPhase,
                BuildProducer<ContainerBeansBuildItem> containerBeans) {

            containerBeans.produce(
                    new ContainerBeansBuildItem(beanRegistrationPhase.getContext().get(BuildExtension.Key.BEANS)));

            // method using BeanRegistrationPhaseBuildItem should return a BeanConfiguratorBuildItem
            // otherwise the build step may be processed at the wrong time.
            return new BeanRegistrationPhaseBuildItem.BeanConfiguratorBuildItem();
        }

        @BuildStep
        void beans(BuildProducer<AdditionalBeanBuildItem> beanProducer) {
            beanProducer.produce(AdditionalBeanBuildItem.unremovableOf(CamelProducers.class));
        }

        /*
         * Configure filters for core services.
         */
        @BuildStep
        void coreServiceFilter(BuildProducer<CamelServiceFilterBuildItem> filterBuildItems) {
            filterBuildItems.produce(
                    new CamelServiceFilterBuildItem(CamelServiceFilter.forService("properties-component-factory")));
        }

        /*
         * Discover {@link TypeConverterLoader}.
         */
        @SuppressWarnings("unchecked")
        @Record(ExecutionTime.STATIC_INIT)
        @BuildStep
        CamelTypeConverterRegistryBuildItem typeConverterRegistry(
                CamelRecorder recorder,
                RecorderContext recorderContext,
                ApplicationArchivesBuildItem applicationArchives,
                List<CamelTypeConverterLoaderBuildItem> additionalLoaders) {

            RuntimeValue<TypeConverterRegistry> typeConverterRegistry = recorder.createTypeConverterRegistry();

            //
            // This should be simplified by searching for classes implementing TypeConverterLoader but that
            // would lead to have org.apache.camel.impl.converter.AnnotationTypeConverterLoader taken into
            // account even if it should not.
            //
            // TODO: we could add a filter to discard AnnotationTypeConverterLoader but maybe we should introduce
            //       a marker interface like StaticTypeConverterLoader for loaders that do not require to perform
            //       any discovery at runtime.
            //
            for (ApplicationArchive archive : applicationArchives.getAllApplicationArchives()) {
                Path path = archive.getArchiveRoot().resolve(BaseTypeConverterRegistry.META_INF_SERVICES_TYPE_CONVERTER_LOADER);
                if (!Files.isRegularFile(path)) {
                    continue;
                }

                try {
                    Files.readAllLines(path, StandardCharsets.UTF_8).stream()
                            .map(String::trim)
                            .filter(l -> !l.isEmpty())
                            .filter(l -> !l.startsWith("#"))
                            .map(l -> (Class<? extends TypeConverterLoader>) recorderContext.classProxy(l))
                            .forEach(loader -> recorder.addTypeConverterLoader(typeConverterRegistry, loader));
                } catch (IOException e) {
                    throw new RuntimeException("Error discovering TypeConverterLoader", e);
                }
            }

            //
            // User can register loaders by providing a CamelTypeConverterLoaderBuildItem that can be used to
            // provide additional TypeConverter or override default converters discovered by the previous step.
            //
            for (CamelTypeConverterLoaderBuildItem item : additionalLoaders) {
                recorder.addTypeConverterLoader(typeConverterRegistry, item.getValue());
            }

            return new CamelTypeConverterRegistryBuildItem(typeConverterRegistry);
        }

        @Record(ExecutionTime.STATIC_INIT)
        @BuildStep
        CamelRegistryBuildItem registry(
                CamelRecorder recorder,
                RecorderContext recorderContext,
                ApplicationArchivesBuildItem applicationArchives,
                ContainerBeansBuildItem containerBeans,
                List<CamelBeanBuildItem> registryItems,
                List<CamelServiceFilterBuildItem> serviceFilters) {

            final RuntimeValue<org.apache.camel.spi.Registry> registry = recorder.createRegistry();

            CamelSupport.services(applicationArchives)
                    .filter(si -> !containerBeans.getBeans().contains(si))
                    .filter(si -> {
                        //
                        // by default all the service found in META-INF/service/org/apache/camel are
                        // bound to the registry but some of the services are then replaced or set
                        // to the camel context directly by extension so it does not make sense to
                        // instantiate them in this phase.
                        //
                        boolean blacklisted = serviceFilters.stream().anyMatch(filter -> filter.getPredicate().test(si));
                        if (blacklisted) {
                            LOGGER.debug("Ignore service: {}", si);
                        }

                        return !blacklisted;
                    })
                    .forEach(si -> {
                        LOGGER.debug("Binding bean with name: {}, type {}", si.name, si.type);

                        recorder.bind(
                                registry,
                                si.name,
                                recorderContext.classProxy(si.type));
                    });

            registryItems.stream()
                    .filter(item -> !containerBeans.getBeans().contains(item))
                    .forEach(item -> {
                        LOGGER.debug("Binding bean with name: {}, type {}", item.getName(), item.getType());
                        if (item.getValue().isPresent()) {
                            recorder.bind(
                                    registry,
                                    item.getName(),
                                    recorderContext.classProxy(item.getType()),
                                    item.getValue().get());
                        } else {
                            // the instance of the service will be instantiated by the recorder, this avoid
                            // creating a recorder for trivial services.
                            recorder.bind(
                                    registry,
                                    item.getName(),
                                    recorderContext.classProxy(item.getType()));
                        }
                    });

            return new CamelRegistryBuildItem(registry);
        }

        @Overridable
        @BuildStep
        @Record(value = ExecutionTime.STATIC_INIT, optional = true)
        public CamelModelJAXBContextFactoryBuildItem createJaxbContextFactory(CamelRecorder recorder) {
            return new CamelModelJAXBContextFactoryBuildItem(recorder.newDisabledModelJAXBContextFactory());
        }

        @Overridable
        @BuildStep
        @Record(value = ExecutionTime.STATIC_INIT, optional = true)
        public CamelRoutesLoaderBuildItems.Xml createXmlLoader(CamelRecorder recorder) {
            return new CamelRoutesLoaderBuildItems.Xml(recorder.newDisabledXmlRoutesLoader());
        }

        @BuildStep
        @Record(ExecutionTime.STATIC_INIT)
        void disableXmlReifiers(CamelRecorder recorder, Capabilities capabilities) {
            if (!capabilities.isCapabilityPresent(CamelCapabilities.XML)) {
                LOGGER.debug("Camel XML capability not detected, disable XML reifiers");
                recorder.disableXmlReifiers();
            }
        }

        @Record(ExecutionTime.STATIC_INIT)
        @BuildStep
        CamelContextBuildItem context(
                CamelRecorder recorder,
                CamelRegistryBuildItem registry,
                CamelTypeConverterRegistryBuildItem typeConverterRegistry,
                CamelModelJAXBContextFactoryBuildItem contextFactory,
                CamelRoutesLoaderBuildItems.Xml xmlLoader,
                BeanContainerBuildItem beanContainer) {

            RuntimeValue<CamelContext> context = recorder.createContext(
                    registry.getRegistry(),
                    typeConverterRegistry.getRegistry(),
                    contextFactory.getContextFactory(),
                    xmlLoader.getLoader(),
                    beanContainer.getValue());

            return new CamelContextBuildItem(context);
        }

        @Record(ExecutionTime.RUNTIME_INIT)
        @BuildStep
        CamelRuntimeRegistryBuildItem bindRuntimeBeansToRegistry(
                CamelRecorder recorder,
                RecorderContext recorderContext,
                ContainerBeansBuildItem containerBeans,
                CamelRegistryBuildItem registry,
                List<CamelRuntimeBeanBuildItem> registryItems) {

            registryItems.stream()
                    .filter(item -> !containerBeans.getBeans().contains(item))
                    .forEach(item -> {
                        LOGGER.debug("Binding runtime bean with name: {}, type {}", item.getName(), item.getType());

                        if (item.getValue().isPresent()) {
                            recorder.bind(
                                    registry.getRegistry(),
                                    item.getName(),
                                    recorderContext.classProxy(item.getType()),
                                    item.getValue().get());
                        } else {
                            // the instance of the service will be instantiated by the recorder, this avoid
                            // creating a recorder for trivial services.
                            recorder.bind(
                                    registry.getRegistry(),
                                    item.getName(),
                                    recorderContext.classProxy(item.getType()));
                        }
                    });

            return new CamelRuntimeRegistryBuildItem(registry.getRegistry());
        }
    }

    /*
     * Build steps related to camel main that are activated by default but can be
     * disabled by setting quarkus.camel.disable-main = true
     */
    public static class Main {
        @Overridable
        @BuildStep
        @Record(value = ExecutionTime.STATIC_INIT, optional = true)
        public CamelRoutesLoaderBuildItems.Registry createRegistryLoader(CamelRecorder recorder) {
            return new CamelRoutesLoaderBuildItems.Registry(recorder.newDefaultRegistryRoutesLoader());
        }

        @BuildStep(onlyIf = { Flags.MainEnabled.class, Flags.RoutesDiscoveryEnabled.class })
        public List<CamelRoutesBuilderClassBuildItem> discoverRoutesBuilderClassNames(
                CombinedIndexBuildItem combinedIndex,
                CamelConfig config) {

            final IndexView index = combinedIndex.getIndex();

            Set<ClassInfo> allKnownImplementors = new HashSet<>();
            allKnownImplementors.addAll(index.getAllKnownImplementors(ROUTES_BUILDER_TYPE));
            allKnownImplementors.addAll(index.getAllKnownSubclasses(ROUTE_BUILDER_TYPE));
            allKnownImplementors.addAll(index.getAllKnownSubclasses(ADVICE_WITH_ROUTE_BUILDER_TYPE));

            return allKnownImplementors
                    .stream()
                    // public and non-abstract
                    .filter(ci -> ((ci.flags() & (Modifier.ABSTRACT | Modifier.PUBLIC)) == Modifier.PUBLIC))
                    .map(ClassInfo::name)
                    .filter(dotName -> CamelSupport.isPathIncluded(
                            dotName.toString('/'),
                            config.main.routesDiscovery.excludePatterns.orElse(Collections.emptyList()),
                            config.main.routesDiscovery.includePatterns.orElse(Collections.emptyList())))
                    .map(CamelRoutesBuilderClassBuildItem::new)
                    .collect(Collectors.toList());
        }

        @Overridable
        @BuildStep
        @Record(value = ExecutionTime.STATIC_INIT, optional = true)
        public CamelRoutesCollectorBuildItem createRoutesCollector(
                CamelMainRecorder recorder,
                CamelRoutesLoaderBuildItems.Registry registryRoutesLoader,
                CamelRoutesLoaderBuildItems.Xml xmlRoutesLoader) {

            return new CamelRoutesCollectorBuildItem(
                    recorder.newRoutesCollector(registryRoutesLoader.getLoader(), xmlRoutesLoader.getLoader()));
        }

        @BuildStep(onlyIf = Flags.MainEnabled.class)
        void beans(BuildProducer<AdditionalBeanBuildItem> beanProducer) {
            beanProducer.produce(AdditionalBeanBuildItem.unremovableOf(CamelMainProducers.class));
        }

        /*
         * Camel is not pulling the RouteBuilders from the CDI container when the main is off so there is no point in
         * making the lazy beans unremovable in that case.
         */
        @BuildStep(onlyIf = Flags.MainEnabled.class)
        UnremovableBeanBuildItem unremovableRoutesBuilders() {
            return new UnremovableBeanBuildItem(
                    b -> b.getTypes().stream().map(Type::name).anyMatch(UNREMOVABLE_BEANS_TYPES::contains));
        }

        @Overridable
        @Record(value = ExecutionTime.RUNTIME_INIT, optional = true)
        @BuildStep(onlyIf = Flags.MainEnabled.class)
        CamelReactiveExecutorBuildItem reactiveExecutor(CamelMainRecorder recorder) {
            return new CamelReactiveExecutorBuildItem(recorder.createReactiveExecutor());
        }

        /**
         * This method is responsible to configure camel-main during static init phase which means
         * discovering routes, listeners and services that need to be bound to the camel-main.
         * <p>
         * This method should not attempt to start or initialize camel-main as this need to be done
         * at runtime.
         */
        @SuppressWarnings("unchecked")
        @Record(ExecutionTime.STATIC_INIT)
        @BuildStep(onlyIf = Flags.MainEnabled.class)
        CamelMainBuildItem main(
                ContainerBeansBuildItem containerBeans,
                CamelMainRecorder recorder,
                CamelContextBuildItem context,
                CamelRoutesCollectorBuildItem routesCollector,
                List<CamelRoutesBuilderClassBuildItem> routesBuilderClasses,
                List<CamelMainListenerBuildItem> listeners,
                BeanContainerBuildItem beanContainer) {

            RuntimeValue<CamelMain> main = recorder.createCamelMain(
                    context.getCamelContext(),
                    routesCollector.getValue(),
                    beanContainer.getValue());

            for (CamelRoutesBuilderClassBuildItem item : routesBuilderClasses) {
                // don't add routes builders that are known by the container
                if (containerBeans.getClasses().contains(item.getDotName())) {
                    continue;
                }

                recorder.addRoutesBuilder(main, item.getDotName().toString());
            }
            for (CamelMainListenerBuildItem listener : listeners) {
                recorder.addListener(main, listener.getListener());
            }
            return new CamelMainBuildItem(main);
        }

        /**
         * This method is responsible to start camel-main ar runtime.
         *
         * @param recorder  the recorder.
         * @param main      a reference to a {@link CamelMain}.
         * @param registry  a reference to a {@link org.apache.camel.spi.Registry}; note that this parameter is here as
         *                  placeholder to
         *                  ensure the {@link org.apache.camel.spi.Registry} is fully configured before starting camel-main.
         * @param executor  the {@link org.apache.camel.spi.ReactiveExecutor} to be configured on camel-main, this
         *                  happens during {@link ExecutionTime#RUNTIME_INIT} because the executor may need to start
         *                  threads and so on.
         * @param shutdown  a reference to a {@link io.quarkus.runtime.ShutdownContext} used to register shutdown logic.
         * @param startList a placeholder to ensure camel-main start after the ArC container is fully initialized. This
         *                  is required as under the hoods the camel registry may look-up beans form the
         *                  container thus we need it to be fully initialized to avoid unexpected behaviors.
         */
        @Record(ExecutionTime.RUNTIME_INIT)
        @BuildStep(onlyIf = Flags.MainEnabled.class)
        void start(
                CamelMainRecorder recorder,
                CamelMainBuildItem main,
                CamelRuntimeRegistryBuildItem registry,
                CamelReactiveExecutorBuildItem executor,
                ShutdownContextBuildItem shutdown,
                List<ServiceStartBuildItem> startList) {

            recorder.setReactiveExecutor(main.getInstance(), executor.getInstance());
            recorder.start(shutdown, main.getInstance());
        }
    }

    /**
     * Build steps related to Camel Attachments.
     */
    public static class Attachments {

        /**
         * Produces an {@link UploadAttacherBuildItem} holding a no-op {@link UploadAttacher}.
         * <p>
         * Note that this {@link BuildStep} is effective only if {@code camel-quarkus-attachments} extension is not in
         * the class path.
         *
         * @param  recorder the {@link CoreAttachmentsRecorder}
         * @return          a new {@link UploadAttacherBuildItem}
         */
        @Overridable
        @Record(value = ExecutionTime.STATIC_INIT, optional = true)
        @BuildStep
        UploadAttacherBuildItem uploadAttacher(CoreAttachmentsRecorder recorder) {
            return new UploadAttacherBuildItem(recorder.createNoOpUploadAttacher());
        }

    }
}
