/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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;

import org.jboss.installer.auto.InstallationDataSerializer;
import org.jboss.installer.core.InstallationData;
import org.jboss.installer.postinstall.TaskPrinter;
import org.jboss.installer.postinstall.server.DomainServer;
import org.jboss.installer.postinstall.server.ServerOperationException;
import org.jboss.installer.postinstall.server.StandaloneServer;
import org.jboss.installer.postinstall.task.secdom.PropertiesSecurity;
import org.jboss.installer.test.utils.MockLanguageUtils;
import org.jboss.installer.test.utils.TestServer;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

import static org.jboss.installer.test.utils.TestServer.TARGET_PATH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class AddPropertiesSecurityDomainTest {

    private StandaloneServer standaloneServer;
    private DomainServer domainServer;
    @ClassRule
    public static TestServer testServer = new TestServer();
    @Rule
    public TemporaryFolder tempFolder = new TemporaryFolder();
    private SecurityDomainTask task;
    private InstallationData idata;
    private TaskPrinter printer = new NoopPrinter();

    @Before
    public void setup() throws Exception {
        task = new SecurityDomainTask();
        idata = new InstallationData();
        standaloneServer = new StandaloneServer(TARGET_PATH);
        domainServer = new DomainServer(TARGET_PATH);
        idata.setTargetFolder(TARGET_PATH);
    }

    @After
    public void tearDown() {
        standaloneServer.close();
        domainServer.close();
    }

    @Test
    public void testInstallPropertiesSecurityDomainInStandalone() throws Exception {

        final SecurityDomainTask.Config config = new SecurityDomainTask.Config();
        config.setDomainName("TestSD");
        final PropertiesSecurity.PropertiesFileConfig propertiesFileConfig = new PropertiesSecurity.PropertiesFileConfig();
        propertiesFileConfig.setPlainText(true);
        propertiesFileConfig.setUsersFilePath(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("test-users.properties"));
        propertiesFileConfig.setGroupsFilePath(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("test-groups.properties"));
        config.setPropertiesFileConfig(propertiesFileConfig);
        idata.putConfig(config);

        standaloneServer.start("standalone.xml");
        try {
            Files.createFile(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("example-roles.properties"));
            Files.createFile(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("example-users.properties"));
            assertTrue(task.applyToStandalone(idata, standaloneServer, printer));
        } finally {
            standaloneServer.shutdown();
            Files.delete(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("example-roles.properties"));
            Files.delete(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("example-users.properties"));
        }
    }

    @Test
    public void testInstallPropertiesSecurityDomainInDomain() throws Exception {
        testDomain("host.xml");
        testDomain(DomainServer.HOST_PRIMARY_XML);
        testDomain(DomainServer.HOST_SECONDARY_XML);
    }

    private void testDomain(String profile) throws ServerOperationException, IOException {
        final SecurityDomainTask.Config config = new SecurityDomainTask.Config();
        config.setDomainName("TestSD");
        final PropertiesSecurity.PropertiesFileConfig propertiesFileConfig = new PropertiesSecurity.PropertiesFileConfig();
        propertiesFileConfig.setPlainText(true);
        propertiesFileConfig.setUsersFilePath(TARGET_PATH.resolve("domain").resolve("configuration").resolve("test-users.properties"));
        propertiesFileConfig.setGroupsFilePath(TARGET_PATH.resolve("domain").resolve("configuration").resolve("test-groups.properties"));
        config.setPropertiesFileConfig(propertiesFileConfig);
        idata.putConfig(config);

        domainServer.start(profile);
        try {
            Files.createFile(TARGET_PATH.resolve("domain").resolve("configuration").resolve("example-roles.properties"));
            Files.createFile(TARGET_PATH.resolve("domain").resolve("configuration").resolve("example-users.properties"));
            assertTrue(task.applyToDomain(idata, domainServer, printer));
        } finally {
            domainServer.shutdown();
            Files.delete(TARGET_PATH.resolve("domain").resolve("configuration").resolve("example-roles.properties"));
            Files.delete(TARGET_PATH.resolve("domain").resolve("configuration").resolve("example-users.properties"));
        }
    }

    @Test
    public void testSerializePropertiesConfig() throws Exception {
        final PropertiesSecurity.PropertiesFileConfig propertiesFileConfig = new PropertiesSecurity.PropertiesFileConfig();
        propertiesFileConfig.setPlainText(false);
        propertiesFileConfig.setUsersFilePath(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("test-users.properties"));
        propertiesFileConfig.setGroupsFilePath(TARGET_PATH.resolve("standalone").resolve("configuration").resolve("test-groups.properties"));
        propertiesFileConfig.setHashCharset("UTF-8");
        propertiesFileConfig.setHashEncoding("base64");
        final SecurityDomainTask.Config config = new SecurityDomainTask.Config();
        config.setDomainName("TestSD");
        config.setPropertiesFileConfig(propertiesFileConfig);
        idata.putConfig(config);

        final InstallationDataSerializer serializer = new InstallationDataSerializer(new MockLanguageUtils());
        final Path outputFile = tempFolder.newFile().toPath();
        serializer.serialize(idata, outputFile);

        final SecurityDomainTask.Config deserializedConfig = serializer.deserialize(outputFile, Optional.empty()).getConfig(SecurityDomainTask.Config.class);

        assertEquals(propertiesFileConfig, deserializedConfig.getPropertiesFileConfig());
    }
}
