package org.dbunitng.sample.dao;

import static org.testng.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dbunitng.annotations.DatabaseOperationType;
import org.dbunitng.annotations.DbUnitNGConstrants;
import org.dbunitng.annotations.SetUpOperation;
import org.dbunitng.annotations.TableAssert;
import org.dbunitng.annotations.TearDownOperation;
import org.dbunitng.assertion.AssertionHelper;
import org.dbunitng.listeners.DbUnitNGTestListener;
import org.dbunitng.sample.entity.Dept;
import org.dbunitng.sample.entity.Emp;
import org.testng.TestListenerAdapter;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

@Test(groups = "annotation")
public class DbUnitNGAnnotationTest {

	@SetUpOperation(value = DatabaseOperationType.CLEAN_INSERT, pathname = "data.xml")
	public void testPathNameSpecifyOnlyFileName() {
		DeptDao deptDao = new DeptDao();
		List<Dept> deptList = deptDao.listAllDept();
		AssertionHelper.assertEqualsOnlyColumnsInFile(
			deptList,
			"dept.xml");

		EmpDao empDao = new EmpDao();
		List<Emp> empList = empDao.listAllEmployee();
		AssertionHelper.assertEqualsOnlyColumnsInFile(
			empList,
			"emp.xml");
	}

	@SetUpOperation(value = DatabaseOperationType.CLEAN_INSERT, pathname = "org/dbunitng/sample/dao/data.xml")
	public void testPathNameSpecifyFullPattName() {
		DeptDao deptDao = new DeptDao();
		List<Dept> deptList = deptDao.listAllDept();
		AssertionHelper.assertEqualsOnlyColumnsInFile(
			deptList,
			"dept.xml");

		EmpDao empDao = new EmpDao();
		List<Emp> empList = empDao.listAllEmployee();
		AssertionHelper.assertEqualsOnlyColumnsInFile(
			empList,
			"emp.xml");
	}

	@SetUpOperation(value = DatabaseOperationType.CLEAN_INSERT, pathname = "data.xml")
	@TableAssert(names = { "dept", "emp" }, pathname = "data.xml")
	public void testCleanInsert() {
		assertTrue(true, "Nothing to do.");
	}

	@Test(dependsOnMethods = "testDelete")
	@SetUpOperation(value = DatabaseOperationType.REFRESH, pathname = "data.xml")
	@TableAssert(names = { "dept", "emp" }, pathname = "data.xml")
	public void testReflesh() {
		assertTrue(true, "Nothing to do.");
	}

	@Test(dependsOnMethods = "testCleanInsert")
	@SetUpOperation(value = DatabaseOperationType.DELETE, pathname = "data.xml")
	public void testDelete() {
		DeptDao deptDao = new DeptDao();
		List<Dept> deptList = deptDao.listAllDept();
		assertTrue(deptList.isEmpty());
		EmpDao empDao = new EmpDao();
		List<Emp> empList = empDao.listAllEmployee();
		assertTrue(empList.isEmpty());
	}

	@Test(dependsOnMethods = "testReflesh")
	@SetUpOperation(value = DatabaseOperationType.DELETE_ALL, pathname = "data.xml")
	public void testDeleteAll() {
		DeptDao deptDao = new DeptDao();
		List<Dept> deptList = deptDao.listAllDept();
		assertTrue(deptList.isEmpty());
		EmpDao empDao = new EmpDao();
		List<Emp> empList = empDao.listAllEmployee();
		assertTrue(empList.isEmpty());
	}

	@Test(dependsOnMethods = "testDeleteAll")
	@SetUpOperation(value = DatabaseOperationType.INSERT, pathname = "data.xml")
	@TableAssert(names = { "dept", "emp" }, pathname = "data.xml")
	public void testInsert() {
		assertTrue(true, "Nothing to do.");
	}

	@Test(dependsOnMethods = "testInsert")
	@SetUpOperation(value = DatabaseOperationType.UPDATE, pathname = "data.xml")
	@TableAssert(names = { "dept", "emp" }, pathname = "data.xml")
	public void testUpdate() {
		assertTrue(true, "Nothing to do.");
	}

	@Test(dependsOnMethods = "testUpdate")
	@SetUpOperation(value = DatabaseOperationType.TRUNCATE_TABLE, pathname = "data.xml")
	public void testTruncate() {
		DeptDao deptDao = new DeptDao();
		List<Dept> deptList = deptDao.listAllDept();
		assertTrue(deptList.isEmpty());
		EmpDao empDao = new EmpDao();
		List<Emp> empList = empDao.listAllEmployee();
		assertTrue(empList.isEmpty());
	}

	@Test(dependsOnMethods = "testTearDownOperation")
	@SetUpOperation(value = DatabaseOperationType.NONE, pathname = "")
	@TableAssert(names = { "dept", "emp" }, pathname = "data.xml")
	public void testNone() {
		assertTrue(true, "Nothing to do.");
	}

	@TearDownOperation(value = DatabaseOperationType.CLEAN_INSERT, pathname = "data.xml")
	public void testTearDownOperation() {
		assertTrue(true, "Nothing to do.");
	}

	@SetUpOperation(pathname = "data.xml")
	public void testDefaultOperation() {
		assertTrue(true, "Nothing to do.");
	}

	@SetUpOperation(pathname = "csv/" + DbUnitNGConstrants.CSV_ORDER_FILE, value = DatabaseOperationType.CLEAN_INSERT)
	@TableAssert(names = { "dept", "emp" }, pathname = "csv/"
		+ DbUnitNGConstrants.CSV_ORDER_FILE)
	public void testCsvFile() {
		assertTrue(true, "Nothing to do.");
	}

	@Test(enabled = false)
	public static void main(String[] args) {
		TestNG testNG = new TestNG();

		testNG.addListener(new DbUnitNGTestListener());
		TestListenerAdapter adapter = new TestListenerAdapter();
		testNG.addListener(adapter);

		XmlSuite suite = new XmlSuite();
		Map<String, String> parameters = new HashMap<String, String>();
		parameters.put("driver", "com.mysql.jdbc.Driver");
		parameters.put("url", "jdbc:mysql://127.0.0.1/testframework");
		parameters.put("username", "root");
		parameters.put("password", "root");
		parameters.put("defaultOperation", "CLEAN_INSERT");
		suite.setParameters(parameters);

		XmlTest test = new XmlTest(suite);
		XmlClass[] classes =
			new XmlClass[] { new XmlClass(DbUnitNGAnnotationTest.class) };
		test.setXmlClasses(Arrays.asList(classes));

		List<XmlSuite> list = new ArrayList<XmlSuite>();
		list.add(suite);
		testNG.setXmlSuites(list);

		testNG.run();

		System.out.println("PassedTests:" + adapter.getPassedTests());
		System.out.println("FailedTests:" + adapter.getFailedTests());
		System.out.println("SkippedTests:" + adapter.getSkippedTests());

	}
}
