/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2021 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.validators;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.SystemUtils;
import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.test.utils.MockLanguageUtils;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.assertj.core.api.Assertions.assertThat;
import static org.jboss.installer.validators.MavenSettingsPathValidator.EMPTY_FIELD_ERROR_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.FS;
import static org.jboss.installer.validators.MavenSettingsPathValidator.INVALID_SCHEMA_ERROR_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.NOT_ABSOLUTE_ERROR_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.NOT_WRITABLE_ERROR_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.SETTINGS_EXISTS_EMPTY_WARNING_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.SETTINGS_EXISTS_WARNING_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.SETTINGS_NOT_EXISTENT_WARNING_KEY;
import static org.jboss.installer.validators.MavenSettingsPathValidator.SETTINGS_XML;
import static org.junit.Assert.assertEquals;

public class MavenSettingsPathValidatorTest {

    public static final String HOME_DIR = System.getProperty("user.home");
    private final MavenSettingsPathValidator validator = new MavenSettingsPathValidator(new MockLanguageUtils());

    private final LanguageUtils langUtils = new MockLanguageUtils();

    @Rule
    public TemporaryFolder temp = new TemporaryFolder();

    @Test
    public void validateWriteableEmptyExistingFileTest() throws Exception {
        final Path tempFilePath = temp.newFile("temp.xml").toPath();
        tempFilePath.toFile().deleteOnExit();
        assertThat(validator.validate(tempFilePath.toString()).getMessage())
                .contains(SETTINGS_EXISTS_EMPTY_WARNING_KEY);
    }

    @Test
    public void validateWriteableNotEmptyExistingFileTest() throws Exception {
        InputStream stream = this.getClass().getClassLoader().getResourceAsStream("settings.xml");
        final Path tempFilePath = temp.newFile("temp.xml").toPath();
        FileUtils.copyInputStreamToFile(stream, tempFilePath.toFile());
        assertThat(validator.validate(tempFilePath.toString()).getMessage())
                .contains(SETTINGS_EXISTS_WARNING_KEY);
    }

    @Test
    public void validateWriteableNotExistingFile() {
        Assume.assumeFalse(System.getProperty("os.name").startsWith("Windows"));

        Path notExistingFile = Paths.get(HOME_DIR);
        Assert.assertEquals(SETTINGS_NOT_EXISTENT_WARNING_KEY, validator.validate(notExistingFile.toString()).getMessage());
        notExistingFile = Paths.get(HOME_DIR + FS + SETTINGS_XML);
        Assert.assertEquals(SETTINGS_NOT_EXISTENT_WARNING_KEY, validator.validate(notExistingFile.toString()).getMessage());
    }

    @Test
    public void validateAbsolutePathTest() {
        Path notAbsolutePath = Paths.get("notabsolute");
        Assert.assertEquals(NOT_ABSOLUTE_ERROR_KEY, validator.validate(notAbsolutePath.toString()).getMessage());
    }

    @Test
    public void notWriteableDirectory() throws Exception {
        Assume.assumeFalse(System.getProperty("os.name").startsWith("Windows"));
        final Path tempDirectoryPath = temp.newFolder("temp").toPath();
        tempDirectoryPath.toFile().setWritable(false);
        Assert.assertEquals(NOT_WRITABLE_ERROR_KEY, validator.validate(tempDirectoryPath.toString()).getMessage());
    }

    @Test
    public void notWriteableFile() throws Exception {
        final Path tempFilePath = temp.newFile("temp.xml").toPath();
        tempFilePath.toFile().setWritable(false);
        tempFilePath.toFile().deleteOnExit();
        Assert.assertEquals(NOT_WRITABLE_ERROR_KEY, validator.validate(tempFilePath.toString()).getMessage());
    }

    @Test
    public void emptyFieldTest() {
        Path path = Paths.get("");
        Assert.assertEquals(EMPTY_FIELD_ERROR_KEY, validator.validate(path.toString()).getMessage());
    }

    @Test
    public void validateNotValidXmlFile() throws Exception {
        final Path tempFilePath = temp.newFile("temp.xml").toPath();
        Files.write(tempFilePath, "not xml file".getBytes(StandardCharsets.UTF_8));
        Assert.assertEquals(INVALID_SCHEMA_ERROR_KEY, validator.validate(tempFilePath.toString()).getMessage());
    }

    @Test
    public void nullSettingsPath() {
        Assert.assertEquals(EMPTY_FIELD_ERROR_KEY, validator.validate((String)null).getMessage());
    }

    @Test
    public void nonExistingParentWindows() throws Exception {
        Assume.assumeTrue(SystemUtils.IS_OS_WINDOWS);
        final MavenSettingsPathValidator mavenSettingsPathValidator = new MavenSettingsPathValidator(langUtils);
        Path path = Paths.get("X:\\test\\settings.xml");
        final ValidationResult result = mavenSettingsPathValidator.validate(path, true);
        assertEquals(ValidationResult.Result.ERROR, result.getResult());
        assertThat(result.getMessage()).startsWith("quickstarts.maven.setup.not_writable_error");
    }

    @Test
    public void validateIllegalCharacters() {
        Assume.assumeTrue(SystemUtils.IS_OS_WINDOWS);

        assertThat(validator.validate("abc:efgh").getMessage())
                .contains("quickstarts.invalid_char");
    }
}
