package org.innovateuk.ifs.health;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.pool.PoolStats;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
@Component
public class HttpClientHealthIndicator implements HealthIndicator {

    @Value("${ifs.web.rest.connections.monitoring.low-pool-warning-count:5}")
    private int lowPoolWarningCount;

    @Autowired
    private PoolingHttpClientConnectionManager poolingHttpClientConnectionManager;

    @Scheduled(timeUnit = TimeUnit.MINUTES, initialDelay = 15, fixedDelay = 500)
    public void scheduled() {
        log.error("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        log.error("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        log.error("XX  Shutting down");
        log.error("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        log.error("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        poolingHttpClientConnectionManager.shutdown();
    }

    @Override
    public Health health() {
        PoolStats poolStats = poolingHttpClientConnectionManager.getTotalStats();
        Map<String, Integer> stats = getStats(poolStats);
        if (getIsShutdown()) {
            return Health.up().withDetails(stats).build();
        } else if (poolStats.getAvailable() <= lowPoolWarningCount) {
            return Health.outOfService().withDetails(stats).build();
        }
        return Health.down().withDetails(stats).build();
    }

    private boolean getIsShutdown() {
        Field isShutDownField = ReflectionUtils.findField(PoolingHttpClientConnectionManager.class, "isShutDown");
        ReflectionUtils.makeAccessible(isShutDownField);
        AtomicBoolean isShutdown = (AtomicBoolean) ReflectionUtils.getField(isShutDownField, poolingHttpClientConnectionManager);
        return isShutdown.get();
    }

    private Map<String, Integer> getStats(PoolStats poolStats) {
        Map<String, Integer> details = new HashMap<>();
        details.put("Available", poolStats.getAvailable());
        details.put("Leased", poolStats.getLeased());
        details.put("Pending", poolStats.getPending());
        details.put("Max", poolStats.getMax());
        return details;
    }
}

@@ -1102,17 +1102,16 @@
 elay = 1
-5
 , fixedD
@@ -1579,24 +1579,55 @@
 talStats();%0A
+        logWarning(poolStats);%0A
         Map%3C
@@ -1733,10 +1733,12 @@
 lth.
-up
+down
 ().w
@@ -1778,44 +1778,195 @@
   %7D 
-else if (poolStats.getAvailable() %3C=
+return Health.up().withDetails(stats).build();%0A    %7D%0A%0A    private void logWarning(PoolStats poolStats) %7B%0A        if (poolStats.getPending() %3E lowPoolWarningCount %7C poolStats.getLeased() +
  low
@@ -1985,145 +1985,125 @@
 ount
-) %7B%0A            return Health.outOfService().withDetails(stats).build();%0A        %7D%0A        return Health.down().withDetails(stats).build(
+ %3E poolStats.getMax()) %7B%0A            log.warn(poolStats.toString());%0A        %7D%0A        log.trace(poolStats.toString()
 );%0A 
@@ -2448,16 +2448,146 @@
 nager);%0A
+        if (isShutdown.get()) %7B%0A            log.error(%22Connection pool has been terminated by the HttpClient Library%22);%0A        %7D%0A
         

rewrite the pooling connection health filter