/*
 * Copyright 2018 Red Hat, Inc.
 *
 * Licensed 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.jboss.shamrock.smallrye.health;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.eclipse.microprofile.health.Health;
import org.eclipse.microprofile.health.spi.HealthCheckResponseProvider;
import org.jboss.jandex.DotName;
import org.jboss.shamrock.arc.deployment.AdditionalBeanBuildItem;
import org.jboss.shamrock.arc.deployment.BeanDefiningAnnotationBuildItem;
import org.jboss.shamrock.deployment.annotations.BuildProducer;
import org.jboss.shamrock.deployment.annotations.BuildStep;
import org.jboss.shamrock.deployment.annotations.ExecutionTime;
import org.jboss.shamrock.deployment.annotations.Record;
import org.jboss.shamrock.deployment.builditem.FeatureBuildItem;
import org.jboss.shamrock.deployment.recording.RecorderContext;
import org.jboss.shamrock.deployment.util.ServiceUtil;
import org.jboss.shamrock.runtime.annotations.ConfigItem;
import org.jboss.shamrock.runtime.annotations.ConfigRoot;
import org.jboss.shamrock.smallrye.health.runtime.SmallRyeHealthServlet;
import org.jboss.shamrock.smallrye.health.runtime.SmallRyeHealthTemplate;
import org.jboss.shamrock.undertow.ServletBuildItem;

import io.smallrye.health.SmallRyeHealthReporter;

class SmallRyeHealthProcessor {

    private static final DotName HEALTH = DotName.createSimple(Health.class.getName());

    /**
     * The configuration for health checking.
     */
    SmallRyeHealthConfig health;

    @ConfigRoot(name = "smallrye-health")
    static final class SmallRyeHealthConfig {
        /**
         * The path of the health-checking servlet.
         */
        @ConfigItem(defaultValue = "/health")
        String path;
    }


    @BuildStep
    ServletBuildItem produceServlet() {
        ServletBuildItem servletBuildItem = new ServletBuildItem("health", SmallRyeHealthServlet.class.getName());
        servletBuildItem.getMappings().add(health.path);
        return servletBuildItem;
    }

    @BuildStep
    List<AdditionalBeanBuildItem> additionalBeans(BuildProducer<BeanDefiningAnnotationBuildItem> beanDefiningAnnotation) {
        beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(HEALTH));

        return Arrays.asList(
                new AdditionalBeanBuildItem(SmallRyeHealthReporter.class),
                new AdditionalBeanBuildItem(SmallRyeHealthServlet.class));
    }

    @BuildStep
    @Record(ExecutionTime.STATIC_INIT)
    @SuppressWarnings("unchecked")
    void registerHealthCheckResponseProvider(SmallRyeHealthTemplate template, RecorderContext recorder) throws IOException {
        Set<String> providers = ServiceUtil.classNamesNamedIn(getClass().getClassLoader(), "META-INF/services/" + HealthCheckResponseProvider.class.getName());

        if (providers.isEmpty()) {
            throw new IllegalStateException("No HealthCheckResponseProvider implementation found.");
        } else if (providers.size() > 1) {
            throw new IllegalStateException(String.format("Multiple HealthCheckResponseProvider implementations found: %s", providers));
        }

        template.registerHealthCheckResponseProvider((Class<? extends HealthCheckResponseProvider>) recorder.classProxy(providers.iterator().next()));
    }

    @BuildStep
    FeatureBuildItem feature() {
        return new FeatureBuildItem(FeatureBuildItem.SMALLRYE_HEALTH);
    }

}

@@ -668,56 +668,8 @@
 on;%0A
-import java.util.Arrays;%0Aimport java.util.List;%0A
 impo
@@ -2232,17 +2232,16 @@
 %0A    %7D%0A%0A
-%0A
     @Bui
@@ -2255,43 +2255,559 @@
     
-ServletBuildItem p
+@Record(ExecutionTime.STATIC_INIT)%0A    @SuppressWarnings(%22unchecked%22)%0A    void build(SmallRyeHealthTemplate template, RecorderContext recorder,%0A                BuildProducer%3CFeatureBuildItem%3E feature,%0A                BuildP
 roduce
+r%3C
 Servlet
-() %7B
+BuildItem%3E servlet,%0A                BuildProducer%3CAdditionalBeanBuildItem%3E additionalBean,%0A                BuildProducer%3CBeanDefiningAnnotationBuildItem%3E beanDefiningAnnotation) throws IOException %7B%0A%0A        feature.produce(new FeatureBuildItem(FeatureBuildItem.SMALLRYE_HEALTH));%0A%0A        // Register the servlet
 %0A   
@@ -2983,23 +2983,32 @@
         
-return 
+servlet.produce(
 servletB
@@ -3019,154 +3019,84 @@
 Item
-;
+);%0A
 %0A    
-%7D%0A%0A    @BuildStep%0A    List%3CAdditionalBeanBuildItem%3E additionalBeans(BuildProducer%3CBeanDefiningAnnotationBuildItem%3E beanDefiningAnnotation) %7B
+    // Make ArC discover the beans marked with the @Health qualifier
 %0A   
@@ -3190,46 +3190,63 @@
     
-return Arrays.asList(%0A                
+// Add additional beans%0A        additionalBean.produce(
 new 
@@ -3301,189 +3301,64 @@
 lass
-),%0A                new AdditionalBeanBuildItem(SmallRyeHealthServlet.class));%0A    %7D%0A%0A    @BuildStep%0A    @Record(ExecutionTime.STATIC_INIT)%0A    @SuppressWarnings(%22unchecked%22)%0A    voi
+, SmallRyeHealthServlet.class));%0A%0A        // Discover an
 d re
@@ -3355,32 +3355,37 @@
 ver and register
+ the 
 HealthCheckRespo
@@ -3399,88 +3399,8 @@
 ider
-(SmallRyeHealthTemplate template, RecorderContext recorder) throws IOException %7B
 %0A   
@@ -4045,133 +4045,6 @@
   %7D%0A
-%0A    @BuildStep%0A    FeatureBuildItem feature() %7B%0A        return new FeatureBuildItem(FeatureBuildItem.SMALLRYE_HEALTH);%0A    %7D%0A%0A
 %7D%0A

Restructure the SmallRyeHealthProcessor