
package org.eclipse.virgo.test.tools;

import static java.time.Instant.now;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.eclipse.virgo.util.io.NetUtils;

// TODO - rework static usage of virgoHome
public class JmxUtils {

    public static File virgoHome;

    private static final Duration HALF_SECOND = Duration.ofMillis(500);

    private static final Duration THIRTY_SECONDS = Duration.ofSeconds(30);

    private static final Duration TWO_MINUTES = Duration.ofMinutes(2);

    private static final String ARTIFACT_BUNDLE = "bundle";

    private static MBeanServerConnection connection = null;

    private final static int JMX_DEFAULT_PORT = 9875;

    private static final String JMXURL = "service:jmx:rmi:///jndi/rmi://localhost:" + JMX_DEFAULT_PORT + "/jmxrmi";

    private static final String KEYSTORE = "/configuration/keystore";

    private static final String KEYPASSWORD = "changeit";

    private static final String DEPLOYER_MBEAN_NAME = "org.eclipse.virgo.kernel:category=Control,type=Deployer";

    private static final String[] DEPLOYMENT_IDENTITY_FIELDS = new String[] { "type", "symbolicName", "version" };

    private final static String STATUS_STARTED = "STARTED";

    private final static String STATUS_STARTING = "STARTING";

    public static boolean isDefaultJmxPortAvailable() {
        return NetUtils.isPortAvailable(JMX_DEFAULT_PORT);
    }

    public static boolean isKernelStarted() {
        return JmxUtils.STATUS_STARTED.equals(getKernelStatus());
    }

    public static boolean waitForVirgoServerStartFully() throws Exception {
        Instant start = Instant.now();
        while (start.plus(THIRTY_SECONDS).isAfter(Instant.now())) {
            try {
                String currentKernelStatus = getKernelStatus();
                System.out.println("Current kernel status: '" + currentKernelStatus + "'");
                switch (currentKernelStatus) {
                    case STATUS_STARTED:
                        // wait for startup to complete
                        SECONDS.sleep(15);
                        return true;
                    case STATUS_STARTING:
                    default:
                        break;
                }
            } catch (IllegalStateException e) {
                // ignore JMX related exception and try again?
            }
            SECONDS.sleep(1);
        }
        // startup failed
        return false;
    }

    public static boolean waitForVirgoServerShutdownFully() throws Exception {
        Instant start = now();
        while (start.plus(THIRTY_SECONDS).isAfter(now())) {
            if (isDefaultJmxPortAvailable()) {
                // allow some more time to finish shutdown
                SECONDS.sleep(5);
                return true;
            }
            try {
                String currentKernelStatus = getKernelStatus();
                System.out.println("Current kernel status: '" + currentKernelStatus + "'");
                if (!getKernelStatus().equals(STATUS_STARTED)) {
                }
            } catch (IllegalStateException e) {
                // ignore JMX related exception and try again?
            }
            SECONDS.sleep(1);
        }
        // shutdown failed
        return false;
    }

    public static void waitForMBean(String mBeanName) throws Exception {
        waitForMBean(mBeanName, HALF_SECOND, TWO_MINUTES);
    }

    public static void waitForMBean(String mBeanName, Duration sleepDuration, Duration duration) throws Exception {
        Instant start = Instant.now();
        boolean mbeanStatus = false;
        while (start.plus(duration).isAfter(Instant.now())) {
            try {
                ObjectName objectName = new ObjectName(mBeanName);
                System.out.println("Looking for JMX object '" + objectName + "'");
                mbeanStatus = getMBeanServerConnection().isRegistered(objectName);
                if (mbeanStatus) {
                    return;
                }
            } catch (IOException e) {
                // swallow and retry - No JMX server available (yet)
            }
            Thread.sleep(sleepDuration.toMillis());
        }
        fail(String.format("After %d s and %d ns, artifact %s mbean Status was", duration.getSeconds(), duration.getNano(), mBeanName) + mbeanStatus);
    }

    public static void waitForArtifactInUserRegion(String type, String name, String version, long interval, long duration) throws Exception {
        long startTime = System.currentTimeMillis();
        boolean mbeanStatus = false;
        while (System.currentTimeMillis() - startTime < duration) {
            try {
                ObjectName objectName = getObjectName(type, name, version);
                System.out.println("Looking for JMX object '" + objectName + "'");
                mbeanStatus = getMBeanServerConnection().isRegistered(objectName);
                if (mbeanStatus) {
                    return;
                }
            } catch (IOException e) {
                // swallow and retry
            }
            Thread.sleep(interval);
        }
        fail(String.format("After %d ms, artifact %s mbean Status was", duration, name) + mbeanStatus);
    }

    public static void waitForArtifactInKernelRegion(String type, String name, String version, long interval, long duration) throws Exception {
        long startTime = System.currentTimeMillis();
        boolean mbeanStatus = false;
        while (System.currentTimeMillis() - startTime < duration) {
            try {
                ObjectName objectName = getObjectNameInKernelRegion(type, name, version);
                System.out.println("Looking for JMX object '" + objectName + "'");
                mbeanStatus = getMBeanServerConnection().isRegistered(objectName);
                if (mbeanStatus) {
                    return;
                }
            } catch (IOException e) {
                // swallow and retry
            }
            Thread.sleep(interval);
        }
        fail(String.format("After %d ms, artifact %s mbean Status was", duration, name) + mbeanStatus);
    }

    public static MBeanServerConnection getMBeanServerConnection() throws IOException {
        String severDir = null;

        String[] creds = { "admin", "admin" };
        Map<String, String[]> env = new HashMap<String, String[]>();

        try {
            severDir = virgoHome.getCanonicalPath();
        } catch (IOException e) {
            throw new IllegalStateException("Failed to get canonical path of server directory '" + virgoHome + "'.");
        }

        env.put(JMXConnector.CREDENTIALS, creds);
        System.setProperty("javax.net.ssl.trustStore", severDir + KEYSTORE);
        System.setProperty("javax.net.ssl.trustStorePassword", KEYPASSWORD);
        JMXServiceURL url;
        try {
            url = new JMXServiceURL(JMXURL);
            connection = JMXConnectorFactory.connect(url, env).getMBeanServerConnection();
        } catch (MalformedURLException e) {
            throw new IllegalStateException("Failed to create JMX connection to '" + JMXURL + "'.", e);
        }
        return connection;
    }

    public static ObjectName getObjectName(String type, String name, String version) throws MalformedObjectNameException {
        return new ObjectName(String.format(
            "org.eclipse.virgo.kernel:type=ArtifactModel,artifact-type=%s,name=%s,version=%s,region=org.eclipse.virgo.region.user", type, name,
            version));
    }

    public static ObjectName getObjectNameInKernelRegion(String type, String name, String version) throws MalformedObjectNameException {
        return new ObjectName(String.format(
            "org.eclipse.virgo.kernel:type=ArtifactModel,artifact-type=%s,name=%s,version=%s,region=org.eclipse.equinox.region.kernel", type, name,
            version));
    }

    public static void deploy(File uploadedFile) throws Exception {
        deploy(java.util.Collections.singletonList(uploadedFile));
    }

    public static void deploy(List<File> uploadedFiles) throws Exception {
        waitForMBean(DEPLOYER_MBEAN_NAME, HALF_SECOND, TWO_MINUTES);
        ObjectName objectName = new ObjectName(DEPLOYER_MBEAN_NAME);
        for (File file : uploadedFiles) {
            URI uri = file.toURI();
            System.out.println("Deploying file '" + uri + "' on '" + objectName + "'");
            Object invoke = getMBeanServerConnection().invoke(objectName, "deploy", new Object[] { uri.toString() },
                new String[] { String.class.getName() });
            getDeploymentIdentity(invoke);
        }
    }

    // Taken from org.eclipse.virgo.management.console.UploadServlet.getDeploymentIdentity()
    private static String getDeploymentIdentity(Object deploymentIdentity) {
        StringBuilder builder = new StringBuilder();
        if (deploymentIdentity instanceof CompositeDataSupport) {
            CompositeDataSupport deploymentIdentityInstance = (CompositeDataSupport) deploymentIdentity;
            Object[] all = deploymentIdentityInstance.getAll(DEPLOYMENT_IDENTITY_FIELDS);
            builder.append(all[0]);
            builder.append(" - ").append(all[1]);
            builder.append(": ").append(all[2]);
        }
        return builder.toString();
    }

    public static void waitForArtifactState(String type, String name, String version, String state, long interval, long duration) throws Exception {
        long startTime = System.currentTimeMillis();
        String artifactstate = null;
        while (System.currentTimeMillis() - startTime < duration) {
            artifactstate = getMBeanServerConnection().getAttribute(getObjectName(type, name, version), "State").toString();
            if (artifactstate.equals(state)) {
                return;
            }
            Thread.sleep(interval);
        }
        fail(String.format("After %d ms, artifact %s state was", duration, name) + artifactstate);
    }

    public static void assertArtifactExists(String type, String name, String version) throws Exception {
        assertTrue(String.format("Artifact %s:%s:%s does not exist", type, name, version),
            getMBeanServerConnection().isRegistered(JmxUtils.getObjectName(type, name, version)));
    }

    public static void assertBundleArtifactExists(String name, String version) throws Exception {
        assertTrue(String.format("Artifact %s:%s:%s does not exist", ARTIFACT_BUNDLE, name, version),
            getMBeanServerConnection().isRegistered(JmxUtils.getObjectName(ARTIFACT_BUNDLE, name, version)));
    }

    public static void assertBundleArtifactExistsInKernelRegion(String name, String version) throws Exception {
        assertTrue(String.format("Artifact %s:%s:%s does not exist", ARTIFACT_BUNDLE, name, version),
            getMBeanServerConnection().isRegistered(JmxUtils.getObjectNameInKernelRegion(ARTIFACT_BUNDLE, name, version)));
    }

    public static void assertBundleArtifactState(String name, String version, String state) throws Exception {
        assertArtifactState(ARTIFACT_BUNDLE, name, version, state);
    }

    public static void assertBundleArtifactStateInKernelRegion(String name, String version, String state) throws Exception {
        assertArtifactStateInKernelRegion(ARTIFACT_BUNDLE, name, version, state);
    }

    public static void assertArtifactState(String type, String name, String version, String state) throws Exception {
        assertEquals(String.format("admin console plan artifact %s:%s:%s is not in state %s", type, name, version, state), state,
            getMBeanServerConnection().getAttribute(JmxUtils.getObjectName(type, name, version), "State"));
    }

    public static void assertArtifactStateInKernelRegion(String type, String name, String version, String state) throws Exception {
        assertEquals(String.format("admin console plan artifact %s:%s:%s is not in state %s", type, name, version, state), state,
            getMBeanServerConnection().getAttribute(JmxUtils.getObjectNameInKernelRegion(type, name, version), "State"));
    }

    public static void uninstall(String type, String name, String version) throws Exception {
        getMBeanServerConnection().invoke(getObjectName(type, name, version), "uninstall", new Object[] {}, new String[] {});
    }

    public static String getKernelStatus() {
        try {
            return (String) getMBeanServerConnection().getAttribute(new ObjectName("org.eclipse.virgo.kernel:type=KernelStatus"), "Status");
        } catch (AttributeNotFoundException e) {
            throw new IllegalStateException("Failed to get server status.", e);
        } catch (InstanceNotFoundException e) {
            throw new IllegalStateException("Failed to get server status.", e);
        } catch (MalformedObjectNameException e) {
            throw new IllegalStateException("Failed to get server status.", e);
        } catch (MBeanException e) {
            throw new IllegalStateException("Failed to get server status.", e);
        } catch (ReflectionException e) {
            throw new IllegalStateException("Failed to get server status.", e);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to get server status.", e);
        }
    }

}
