package org.mercury_im.messenger.learning_tests.smack;

import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLErrorException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smack.util.stringencoder.java7.Java7Base64Encoder;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.junit.Assume.assumeTrue;

/**
 * Learning Test to study Smacks behavior during connection process.
 */
public class XmppConnectionLoginBehaviorTest {

    public static final String CREDENTIALS_PROPERTIES = "testcredentials.properties";

    private static final Logger LOGGER = Logger.getLogger(XmppConnectionLoginBehaviorTest.class.getName());
    private static Properties testCredentials = null;

    @BeforeClass
    public static void readProperties() {
        Properties properties = new Properties();
        File propertiesFile = new File(CREDENTIALS_PROPERTIES);
        if (!propertiesFile.exists() || !propertiesFile.isFile()) {
            LOGGER.log(Level.WARNING, "Cannot find file domain/testcredentials.properties. Some tests will be skipped.");
            return;
        }

        try(FileReader reader = new FileReader(propertiesFile)) {
            properties.load(reader);
        } catch (IOException e) {
            LOGGER.log(Level.WARNING, "Error reading properties file testcredentials.properties.", e);
            return;
        }
        testCredentials = properties;

        Base64.setEncoder(Java7Base64Encoder.getInstance());
    }

    /*
     * Connecting to an invalid host causes {@link org.jivesoftware.smack.SmackException.ConnectionException}
     * to be thrown.
     */
    @Test(expected = SmackException.ConnectionException.class)
    public void invalidHostConnectionTest() throws IOException, InterruptedException, XMPPException, SmackException {
        ignoreIfNoCredentials();
        new XMPPTCPConnection(
                testCredentials.getProperty("invalidHostUsername"),
                testCredentials.getProperty("invalidHostPassword"))
                .connect().login();
    }

    /*
     * Connecting with invalid user causes {@link SASLErrorException} to be thrown.
     */
    @Test(expected = SASLErrorException.class)
    public void invalidUserConnectionTest() throws IOException, InterruptedException, XMPPException, SmackException {
        ignoreIfNoCredentials();
        new XMPPTCPConnection(
                testCredentials.getProperty("invalidUserUsername"),
                testCredentials.getProperty("invalidUserPassword"))
                .connect().login();
    }

    /*
     * Connecting with invalid password causes {@link SASLErrorException} to be thrown.
     */
    @Test(expected = SASLErrorException.class)
    public void invalidPasswordConnectionTest() throws IOException, InterruptedException, XMPPException, SmackException {
        ignoreIfNoCredentials();
        new XMPPTCPConnection(
                testCredentials.getProperty("invalidPasswordUsername"),
                testCredentials.getProperty("invalidPasswordPassword"))
                .connect().login();
    }

    private void ignoreIfNoCredentials() {
        assumeTrue("Test ignored as domain/testcredentials.properties file not found.", testCredentials != null);
    }
}
