package dao;

import java.io.File;
import java.sql.SQLException;
import java.util.List;

import org.dbunit.Assertion;
import org.dbunit.DBTestCase;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;

import util.DBUtil;
import business.PreencheProfessor;
import business.Professor;
import business.Usuario;

public class ProfessorDaoTestCase extends DBTestCase {

	private IDatabaseConnection databaseConnection;
	private FlatXmlDataSet dataSet;

	ProfessorDAO professorDAO = new ProfessorDAO();

	UsuarioDAO usuarioDAO = new UsuarioDAO();

	static Professor professor1 = PreencheProfessor.getProfessor1();

	static Professor professor2 = PreencheProfessor.getProfessor2();

	private void compare(Professor professorEsperado, Professor professorLido) {
		assertEquals(professorEsperado.getId(), professorLido.getId());
		assertEquals(professorEsperado.getMatricula(), professorLido
				.getMatricula());
		assertEquals(professorEsperado.getNome(), professorLido.getNome());
		assertEquals(professorEsperado.getPerfil(), professorLido.getPerfil());
		assertEquals(professorEsperado.getTitulacao(), professorLido
				.getTitulacao());
	}

	public void setUp() throws Exception {
		databaseConnection = new DatabaseConnection(DBUtil.getInstance()
				.getConnection());

		dataSet = new FlatXmlDataSet(new File("./Professores.xml"));
	}

	@Override
	protected IDataSet getDataSet() throws Exception {
		return dataSet;
	}

	@Override
	protected IDatabaseConnection getConnection() throws Exception {
		return databaseConnection;
	}

	public void testVerificarProfessoresIniciais() throws Exception {
		DatabaseOperation.CLEAN_INSERT.execute(databaseConnection, dataSet);

		IDataSet expectedDataSet = new FlatXmlDataSet(new File(
				"./Professores.xml"));

		ITable expectedTable = expectedDataSet.getTable("professor");

		ITable actualTable = getConnection().createQueryTable("professor",
				"select nome, matricula, titulacao from professor");

		Assertion.assertEquals(expectedTable, actualTable);
	}

	public void testAdicionarProfessor() throws Exception {
		String msg = professorDAO.adicionarProfessor(professor1);
		assertTrue(msg.contains("Sucesso"));

		msg = professorDAO.adicionarProfessor(professor2);
		assertTrue(msg.contains("Sucesso"));

		List<Professor> lista = professorDAO.listarProfessores();
		assertEquals(5, lista.size());

		IDataSet expectedDataSet = new FlatXmlDataSet(new File(
				"./CheckProfessores.xml"));

		ITable expectedTable = expectedDataSet.getTable("professor");

		ITable actualTable = getConnection().createQueryTable("professor",
				"select nome, matricula, titulacao from professor");

		Assertion.assertEquals(expectedTable, actualTable);
	}

	public void testAdicionarMesmoProfessor() {
		String msg = professorDAO.adicionarProfessor(professor1);
		assertFalse(msg.contains("Sucesso"));
		assertTrue(msg.contains("cadastrada"));
	}

	public void testLeProfessor() {
		List<Professor> lista = professorDAO.listarProfessores();

		Professor professorLido = professorDAO
				.leProfessor(lista.get(0).getId());

		compare(lista.get(0), professorLido);
	}

	public void testListarProfessoresPorNome() {
		List<Professor> lista = professorDAO.listarProfessores();
		String nome = null;
		List<Professor> resultado = null;

		for (int i = 0; i < lista.size(); i++) {
			nome = lista.get(i).getNome();
			resultado = professorDAO.listarProfessoresPorNome(nome);

			for (Professor professorLido : resultado) {
				if (professorLido.getId() == lista.get(i).getId()) {
					compare(lista.get(i), professorLido);
				} else {
					fail("metodo listarProfessoresPorNome incorreto");
				}
			}
		}
	}

	public void testAssociacaoProfessorUsuario() throws ClassNotFoundException,
			SQLException {
		List<Professor> professorList = professorDAO.listarProfessores();

		int countProfessors = 0;
		for (Professor professorLido : professorList) {
			if (professorLido.getMatricula().equals(professor1.getMatricula())) {
				professor1.setId(professorLido.getId());
				countProfessors++;
			}
		}

		assertEquals(1, countProfessors);

		Usuario usuario1 = professor1.getUsuarios().get(0);
		usuarioDAO.inserir(usuario1);

		List<Usuario> userList = usuarioDAO.listar();

		int countUsers = 0;
		for (Usuario usuarioLido : userList) {
			if (usuarioLido.getUserId().equals(usuario1.getUserId())) {
				usuario1.setId(usuarioLido.getId());
				countUsers++;
			}
		}

		assertEquals(1, countUsers);

		usuarioDAO.associar(usuario1, professor1);
		usuario1.setIdPessoa(professor1.getId());

		userList = usuarioDAO.listarAssociados(professor1);

		countUsers = 0;
		for (Usuario usuarioLido : userList) {
			if (usuarioLido.getUserId().equals(usuario1.getUserId())) {
				countUsers++;
			}
		}

		assertEquals(1, countUsers);

		assertEquals(professor1.getId(), professorDAO
				.obtemIdProfComUsername(usuario1.getUserId()));

		String msg = professorDAO.removerProfessor(professor1.getId());
		assertTrue(msg == null);

		usuarioDAO.excluir(usuario1);
	}

	public void testAtualizaProfessor() {
		Professor p2;
		List<Professor> lista = professorDAO
				.listarProfessoresPorNome(professor2.getNome());
		p2 = lista.get(0);

		PreencheProfessor.alteraDadosProfessor(p2);
		String msg = professorDAO.atualizaProfessor(p2);
		assertTrue(msg == null);

		List<Professor> lista2 = professorDAO.listarProfessores();

		int count = 0;
		for (Professor professorLido : lista2) {
			if (professorLido.getId() == p2.getId()) {
				compare(p2, professorLido);
				count++;
			}
		}

		assertEquals(1, count);
	}

	public void testObtemUltimaMatricula() {
		List<Professor> lista = professorDAO.listarProfessores();
		int maxMatriculaEsperada = -1;
		for (Professor professorLido : lista) {
			int m = Integer.parseInt(professorLido.getMatricula());
			if (maxMatriculaEsperada < m) {
				maxMatriculaEsperada = m;
			}
		}

		int maxMatriculaLida = professorDAO.obtemUltimaMatricula();
		assertEquals(maxMatriculaEsperada, maxMatriculaLida);
	}

	public void testRemoverProfessor() {
		Professor p1, p2;
		List<Professor> lista = professorDAO.listarProfessores();
		p1 = lista.get(0);
		p2 = lista.get(1);

		String msg = professorDAO.removerProfessor(p1.getId());
		assertTrue(msg == null);

		msg = professorDAO.removerProfessor(p2.getId());
		assertTrue(msg == null);
	}
}
