/*
 * 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.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.postinstall.task.DatasourceConfig;
import org.jboss.installer.test.utils.MockLanguageUtils;
import org.junit.Assert;
import org.junit.Test;

import java.util.Arrays;

import static org.jboss.installer.validators.DatasourceValidator.DS_NAME_WHITESPACES_KEY;
import static org.jboss.installer.validators.DatasourceValidator.DUPLICATE_PROPERTY_KEY;
import static org.jboss.installer.validators.DatasourceValidator.EMPTY_FIELDS_KEY;
import static org.jboss.installer.validators.DatasourceValidator.INVALID_JNDI_KEY;
import static org.jboss.installer.validators.DatasourceValidator.INVALID_POOL_SIZE_KEY;

public class DatasourceValidatorTest {

    public static final String VALID_JNDI = "java:/validJndi";
    public static final String VALID_DS_NAME = "dsName";
    public static final String SECURITY_DOMAIN = "securityDomain";
    public static final String CONNECTION_URL = "connectionUrl";
    private final LanguageUtils languageUtils = new MockLanguageUtils();

    private final DatasourceValidator validator = new DatasourceValidator(languageUtils);

    @Test
    public void emptyCommonFieldsTest() {
        DatasourceConfig config = new DatasourceConfig(VALID_DS_NAME, VALID_JNDI, "", "1");
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), EMPTY_FIELDS_KEY);
    }

    @Test
    public void invalidPoolSizeTest() {
        DatasourceConfig config = new DatasourceConfig(VALID_DS_NAME, VALID_JNDI, "2", "1");
        config.setSecurityDomain(SECURITY_DOMAIN);
        config.setConnectionUrl(CONNECTION_URL);
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), INVALID_POOL_SIZE_KEY);
    }

    @Test
    public void invalidJndiNameTest() {
        DatasourceConfig config = new DatasourceConfig(VALID_DS_NAME, "invalidJndi", "0", "1");
        config.setSecurityDomain(SECURITY_DOMAIN);
        config.setConnectionUrl(CONNECTION_URL);
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), INVALID_JNDI_KEY);
    }

    @Test
    public void uniquePropertyKeysTest() {
        DatasourceConfig config = new DatasourceConfig(VALID_DS_NAME, VALID_JNDI, "0", "1");
        config.setSecurityDomain(SECURITY_DOMAIN);
        config.setXaUsername("username");
        config.setXaProperties(Arrays.asList(
                new DatasourceConfig.XaProperty("key", "value"),
                new DatasourceConfig.XaProperty("key", "value")));
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), DUPLICATE_PROPERTY_KEY);
    }

    @Test
    public void datasourceTypeEmptyFieldsTest() {
        DatasourceConfig config = new DatasourceConfig(VALID_DS_NAME, VALID_JNDI, "0", "1");
        config.setSecurityDomain(SECURITY_DOMAIN);
        config.setConnectionUrl("");
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), EMPTY_FIELDS_KEY);
    }

    @Test
    public void securityTypeEmptyFieldsTest() {
        DatasourceConfig config = new DatasourceConfig(VALID_DS_NAME, VALID_JNDI, "0", "1");
        config.setSecurityDomain("");
        config.setConnectionUrl(CONNECTION_URL);
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), EMPTY_FIELDS_KEY);
    }

    @Test
    public void databaseNameContainsWhitespacesTest() {
        DatasourceConfig config = new DatasourceConfig("invalid name with whitespaces", VALID_JNDI, "0", "1");
        config.setSecurityDomain(SECURITY_DOMAIN);
        config.setConnectionUrl(CONNECTION_URL);
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(result.getResult(), ValidationResult.Result.ERROR);
        Assert.assertEquals(result.getMessage(), DS_NAME_WHITESPACES_KEY);
    }

    @Test
    public void nullFieldsTest() {
        DatasourceConfig config = new DatasourceConfig("invalid name with whitespaces", VALID_JNDI, "0", "1");
        config.setSecurityDomain(null);
        validateEmptyField(config);

        config.setConnectionUrl(null);
        validateEmptyField(config);

        config.setDsPassword(null);
        validateEmptyField(config);

        config.setXaPassword(null);
        validateEmptyField(config);

        config.setXaProperties(null);
        validateEmptyField(config);

        config.setXaUsername(null);
        validateEmptyField(config);
    }

    private void validateEmptyField(DatasourceConfig config) {
        ValidationResult result = validator.validate(config);
        Assert.assertEquals(ValidationResult.Result.ERROR, result.getResult());
        Assert.assertEquals(EMPTY_FIELDS_KEY, result.getMessage());
    }
}
