/*
 * Copyright The WildFly Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package org.jboss.as.test.integration.domain.suites;

import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import org.jboss.as.test.integration.domain.management.cli.BasicOpsTestCase;
import org.jboss.as.test.integration.domain.management.cli.CliCapabilityCompletionTestCase;
import org.jboss.as.test.integration.domain.management.cli.CliCompletionTestCase;
import org.jboss.as.test.integration.domain.management.cli.CloneProfileTestCase;
import org.jboss.as.test.integration.domain.management.cli.DeployAllDomainTestCase;
import org.jboss.as.test.integration.domain.management.cli.HelpTestCase;
import org.jboss.as.test.integration.domain.management.cli.HierarchicalCompositionTestCase;
import org.jboss.as.test.integration.domain.management.cli.ServerGroupDeploymentManagedAttributeTestCase;
import org.jboss.as.test.integration.domain.management.cli.UndeployTestCase;
import org.jboss.as.test.integration.domain.management.cli.UndeployWildcardDomainTestCase;
import org.jboss.as.test.integration.domain.management.cli.WildCardReadsTestCase;
import org.jboss.as.test.integration.domain.management.util.DomainTestSupport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

/**
 *
 * @author Dominik Pospisil <dpospisi@redhat.com>
 */
@RunWith(Suite.class)
@Suite.SuiteClasses({
    BasicOpsTestCase.class,
    CliCapabilityCompletionTestCase.class,
    CliCompletionTestCase.class,
    CloneProfileTestCase.class,
    UndeployWildcardDomainTestCase.class,
    UndeployTestCase.class,
    HelpTestCase.class,
    HierarchicalCompositionTestCase.class,
    WildCardReadsTestCase.class,
    DeploymentOverlayTestCase.class,
    DeployAllDomainTestCase.class,
    ServerGroupDeploymentManagedAttributeTestCase.class
})
public class CLITestSuite {

    public static final Map<String, String[]> hostServers = new HashMap<String, String[]>();
    public static final Map<String, String> hostAddresses = new HashMap<String, String>();
    public static final Map<String, String[]> serverGroups = new HashMap<String, String[]>();
    public static final Map<String, Integer> portOffsets = new HashMap<String, Integer>();
    public static final Map<String, String[]> serverProfiles = new HashMap<String, String[]>();
    public static final Map<String, Boolean> serverStatus = new HashMap<String, Boolean>();

    private static boolean initializedLocally = false;
    private static volatile DomainTestSupport support;

    // This can only be called from tests as part of this suite
    public static synchronized DomainTestSupport createSupport(final String testName) {
        if(support == null) {
            start(testName);
        }
        return support;
    }

    // This can only be called from tests as part of this suite
    public static synchronized void stopSupport() {
        if(! initializedLocally) {
            stop();
        }
    }

    private static synchronized void start(final String name) {
        try {
            support = DomainTestSupport.createAndStartDefaultSupport(name);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static synchronized void stop() {
        if(support != null) {
            support.close();
            support = null;
        }
    }

    @BeforeClass
    public static void initSuite() throws Exception {
        initializedLocally = true;
        start(CLITestSuite.class.getSimpleName());

        hostServers.put("primary", new String[]{"main-one", "main-two", "other-one"});
        hostServers.put("secondary", new String[]{"main-three", "main-four", "other-two"});

        hostAddresses.put("primary", DomainTestSupport.primaryAddress);
        hostAddresses.put("secondary", DomainTestSupport.secondaryAddress);

        serverGroups.put("main-server-group", new String[]{"main-one", "main-two", "main-three", "main-four"});
        serverGroups.put("other-server-group", new String[]{"other-one", "other-two"});

        serverProfiles.put("default", new String[]{"main-server-group"});
        serverProfiles.put("ha", new String[]{"other-server-group"});

        portOffsets.put("main-one", 0);
        portOffsets.put("main-two", 150);
        portOffsets.put("other-one", 250);
        portOffsets.put("main-three", 350);
        portOffsets.put("main-four", 450);
        portOffsets.put("other-two", 550);

        serverStatus.put("main-one", true);
        serverStatus.put("main-two", false);
        serverStatus.put("main-three", true);
        serverStatus.put("main-four", false);
        serverStatus.put("other-one", false);
        serverStatus.put("other-two", true);

    }

    @AfterClass
    public static void tearDownSuite() {
        stop();
    }

    public static void addServer(String serverName, String hostName, String groupName, String profileName, int portOffset, boolean status) {
        LinkedList<String> hservers = new LinkedList<String>(Arrays.asList(hostServers.get(hostName)));
        hservers.add(serverName);
        hostServers.put(hostName, hservers.toArray(new String[hservers.size()]));

        LinkedList<String> gservers = new LinkedList<String>();
        if (serverGroups.containsKey(groupName)) {
            gservers.addAll(Arrays.asList(serverGroups.get(groupName)));
        }
        gservers.add(serverName);
        serverGroups.put(groupName, gservers.toArray(new String[gservers.size()]));

        LinkedList<String> pgroups = new LinkedList<String>();
        if (serverProfiles.containsKey(profileName)) {
            pgroups.addAll(Arrays.asList(serverProfiles.get(profileName)));
        }
        pgroups.add(groupName);
        serverProfiles.put(profileName, pgroups.toArray(new String[pgroups.size()]));

        portOffsets.put(serverName, portOffset);
        serverStatus.put(serverName, status);
    }

    public static String getServerHost(String serverName) {
        for(Map.Entry<String,String[]> entry : hostServers.entrySet()) {
            if (Arrays.asList(entry.getValue()).contains(serverName)) { return entry.getKey(); }
        }
        return null;
    }
}
