/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2022 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * 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.installer.postinstall.task.impl;

import org.codehaus.plexus.util.FileUtils;
import org.jboss.installer.core.InstallationData;
import org.jboss.installer.postinstall.TaskPrinter;
import org.jboss.installer.postinstall.task.AbstractHttpsEnableConfig;
import org.jboss.installer.postinstall.task.AdminHttpsConfig;
import org.jboss.installer.postinstall.task.NoopPrinter;
import org.jboss.installer.postinstall.task.PortBindingConfig;
import org.jboss.installer.test.utils.TestServer;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;

import java.nio.file.Files;
import java.util.List;
import java.util.Set;

import static org.jboss.installer.postinstall.task.AbstractHttpsEnableConfig.DEFAULT_CIPHER_NAMES_TLS13;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class JBossCliPortUpdaterTaskTest {

    @ClassRule
    public static TestServer testServer = new TestServer();
    private TaskPrinter printer = new NoopPrinter();

    @Before
    public void setUp() throws Exception {
        // copy the configuration file so that we can quickly restore it between tests
        FileUtils.copyFile(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml").toFile(), TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml_bkp").toFile());
    }

    @After
    public void tearDown() throws Exception {
        FileUtils.forceDelete(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml").toFile());
        FileUtils.copyFile(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml_bkp").toFile(), TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml").toFile());
        FileUtils.forceDelete(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml_bkp").toFile());
    }

    @Test
    public void changeOnlyPortIfOffsetIsSet() throws Exception {
        final InstallationData idata = new InstallationData();
        idata.putConfig(new PortBindingConfig(100));
        idata.setTargetFolder(TestServer.TARGET_PATH);
        new JBossCliPortUpdaterTask().applyToInstallation(idata, printer);

        final List<String> lines = Files.readAllLines(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml"));
        assertTrue(lines.stream().anyMatch(l -> l.contains("<port>10090</port>")));
        assertFalse(lines.stream().anyMatch(l -> l.contains("remote+https")));
    }

    @Test
    public void changePortToHttpsAndProtocolIfHttpsEnabled() throws Exception {
        final InstallationData idata = new InstallationData();
        idata.putConfig(new AdminHttpsConfig(Set.of(AbstractHttpsEnableConfig.PROTOCOL_TLSv12), AbstractHttpsEnableConfig.DEFAULT_CIPHER_SUITES_TLS12, DEFAULT_CIPHER_NAMES_TLS13,
                "foo.keystore", "bar",
                false, null, null, false, null, null, null, false));
        idata.setTargetFolder(TestServer.TARGET_PATH);
        new JBossCliPortUpdaterTask().applyToInstallation(idata, printer);

        final List<String> lines = Files.readAllLines(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml"));
        assertTrue(lines.stream().anyMatch(l -> l.contains("<port>9993</port>")));
        assertTrue(lines.stream().anyMatch(l -> l.contains("remote+https")));
        assertFalse(lines.stream().anyMatch(l -> l.contains("remote+http<")));
    }

    @Test
    public void useStandaloneXmlManagementPortIfProvided() throws Exception {
        final InstallationData idata = new InstallationData();
        final PortBindingConfig config = new PortBindingConfig();
        config.setPorts("standalone.xml", List.of(new PortBindingConfig.SocketBinding("management-http", "", 1234)));
        idata.putConfig(config);
        idata.setTargetFolder(TestServer.TARGET_PATH);
        new JBossCliPortUpdaterTask().applyToInstallation(idata, printer);

        final List<String> lines = Files.readAllLines(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml"));
        assertTrue(lines.stream().anyMatch(l -> l.contains("<port>1234</port>")));
        assertTrue(lines.stream().anyMatch(l -> l.contains("remote+http<")));
    }

    @Test
    public void useStandaloneXmlManagementPortWithHttpsIfProvided() throws Exception {
        final InstallationData idata = new InstallationData();
        final PortBindingConfig config = new PortBindingConfig();
        idata.putConfig(new AdminHttpsConfig(Set.of(AbstractHttpsEnableConfig.PROTOCOL_TLSv12), AbstractHttpsEnableConfig.DEFAULT_CIPHER_SUITES_TLS12, DEFAULT_CIPHER_NAMES_TLS13,
                "foo.keystore", "bar",
                false, null, null, false, null, null, null, false));
        config.setPorts("standalone.xml", List.of(new PortBindingConfig.SocketBinding("management-https", "", 1234)));
        idata.putConfig(config);
        idata.setTargetFolder(TestServer.TARGET_PATH);
        new JBossCliPortUpdaterTask().applyToInstallation(idata, printer);

        final List<String> lines = Files.readAllLines(TestServer.TARGET_PATH.resolve("bin").resolve("jboss-cli.xml"));
        assertTrue(lines.stream().anyMatch(l -> l.contains("<port>1234</port>")));
        assertTrue(lines.stream().anyMatch(l -> l.contains("remote+https<")));
    }
}