package meerkat.bulletinboard;

import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer.SQLQueryProvider;
import meerkat.bulletinboard.sqlserver.MySQLQueryProvider;
import meerkat.comm.CommunicationException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import static org.junit.Assert.fail;

/**
 * Created by Arbel Deutsch Peled on 07-Dec-15.
 */
public class MySQLBulletinBoardServerTest {

    private final String dbAddress = "localhost";
    private final int dbPort = 3306;
    private final String dbName = "meerkat";
    private final String username = "arbel";
    private final String password = "mypass";

    private GenericBulletinBoardServerTest serverTest;

    private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); // Used to time the tests

    @Before
    public void init(){

        System.err.println("Starting to initialize MySQLBulletinBoardServerTest");
        long start = threadBean.getCurrentThreadCpuTime();

        SQLQueryProvider queryProvider = new MySQLQueryProvider(dbAddress,dbPort,dbName,username,password);

        try {

            Connection conn = queryProvider.getDataSource().getConnection();
            Statement stmt = conn.createStatement();

            List<String> deletionQueries = queryProvider.getSchemaDeletionCommands();

            for (String deletionQuery : deletionQueries) {
                stmt.execute(deletionQuery);
            }

        } catch (SQLException e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

        BulletinBoardServer bulletinBoardServer = new BulletinBoardSQLServer(queryProvider);
        try {
            bulletinBoardServer.init();

        } catch (CommunicationException e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
            return;
        }

        serverTest = new GenericBulletinBoardServerTest();
        try {
            serverTest.init(bulletinBoardServer);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

        long end = threadBean.getCurrentThreadCpuTime();
        System.err.println("Finished initializing MySQLBulletinBoardServerTest");
        System.err.println("Time of operation: " + (end - start));
    }

    @Test
    public void bulkTest() {
        System.err.println("Starting bulkTest of MySQLBulletinBoardServerTest");
        long start = threadBean.getCurrentThreadCpuTime();

        try {
            serverTest.testInsert();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

        try{
            serverTest.testSimpleTagAndSignature();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

        try{
            serverTest.testEnhancedTagsAndSignatures();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

        long end = threadBean.getCurrentThreadCpuTime();
        System.err.println("Finished bulkTest of MySQLBulletinBoardServerTest");
        System.err.println("Time of operation: " + (end - start));
    }

    @Test
    public void testBatch() {

        final int BATCH_NUM = 20;

        try{
            for (int i = 0 ; i < BATCH_NUM ; i++) {
                serverTest.testPostBatch();
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

        try{
            serverTest.testReadBatch();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }

    }

    @Test
    public void testSyncQuery() {
        try {
            serverTest.testSyncQuery();
        } catch (Exception e) {
            System.err.println(e.getMessage());
            fail(e.getMessage());
        }
    }

    @After
    public void close() {
        System.err.println("Starting to close MySQLBulletinBoardServerTest");
        long start = threadBean.getCurrentThreadCpuTime();

        serverTest.close();

        long end = threadBean.getCurrentThreadCpuTime();
        System.err.println("Finished closing MySQLBulletinBoardServerTest");
        System.err.println("Time of operation: " + (end - start));
    }

}
