package org.dbunitng.dataset;

import static org.testng.Assert.*;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.dbunit.dataset.Column;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.ITableMetaData;
import org.dbunitng.assertion.AssertionHelper;
import org.dbunitng.beans.testbeans.DateBean;
import org.dbunitng.beans.testbeans.NumericBean;
import org.dbunitng.beans.testbeans.SimpleBean;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

@Test(groups = "bean")
public class BeanListConverterTest {

	@DataProvider(name = "simple-bean")
	public Object[][] dataSimpleBean() {

		SimpleBean bean1 = new SimpleBean();
		bean1.setI(1);
		bean1.setString("");

		SimpleBean bean2 = new SimpleBean();
		bean2.setI(0);
		bean2.setString(null);

		SimpleBean bean3 = new SimpleBean();
		bean3.setI(-1);
		bean3.setString("a");

		List<SimpleBean> list = new ArrayList<SimpleBean>();
		list.add(bean1);
		list.add(bean2);
		list.add(bean3);

		Object[][] datas = new Object[1][1];
		datas[0][0] = list;

		return datas;
	}

	@Test(dataProvider = "simple-bean")
	public void testConvertSimpleBean(List<SimpleBean> list) throws Exception {

		BeanListConverter converter = new BeanListConverter(list);
		IDataSet dataSet = converter.convert();

		String[] names = dataSet.getTableNames();
		assertEquals(names, new String[] { "SimpleBean" });

		ITable table = dataSet.getTable(names[0]);
		assertEquals(table.getRowCount(), list.size());

		ITableMetaData data = table.getTableMetaData();
		Column[] columns = data.getColumns();
		assertEquals(columns.length, 2);

		Set<String> set = new HashSet<String>();
		set.add("string");
		set.add("i");
		assertTrue(set.contains(columns[0].getColumnName()));
		assertTrue(set.contains(columns[1].getColumnName()));

		int i = 0;
		for (Iterator<SimpleBean> iterator = list.iterator(); iterator
			.hasNext();) {
			SimpleBean bean = iterator.next();
			assertEquals(table.getValue(i, "string"), bean.getString());
			assertEquals(table.getValue(i, "i"), bean.getI());
			i++;
		}

	}

	@DataProvider(name = "date-bean")
	public Object[][] dataDateBean() throws ParseException {
		DateBean bean = new DateBean();
		Date date =
			new SimpleDateFormat("yyyyMMddHHmmssSSS")
				.parse("20080808152011000");
		bean.setUtilDate(date);
		bean.setSqlDate(new java.sql.Date(date.getTime()));
		bean.setTimestamp(new Timestamp(date.getTime()));

		List<DateBean> list = new ArrayList<DateBean>();
		list.add(bean);

		return new Object[][] { { list } };
	}

	@Test(dataProvider = "date-bean")
	public void testDateBean(List<DateBean> list) throws Exception {
		BeanListConverter converter = new BeanListConverter(list);
		IDataSet dataSet = converter.convert();

		ITable table = dataSet.getTable("DateBean");
		int i = 0;
		for (Iterator<DateBean> iterator = list.iterator(); iterator.hasNext();) {
			DateBean bean = iterator.next();
			assertEquals(table.getValue(0, "utilDate"), bean.getUtilDate());
			assertEquals(table.getValue(0, "sqlDate"), bean.getSqlDate());
			assertEquals(table.getValue(0, "timestamp"), bean.getTimestamp());
			i++;
		}
	}

	@DataProvider(name = "numeric-bean")
	public Object[][] dataNumericBean() {
		NumericBean bean = new NumericBean();
		bean.setD(1.1);
		bean.setDecimal(new BigDecimal("2.1"));
		bean.setDouble1(Double.valueOf(3.1));
		bean.setF((float) 4.1);
		bean.setFloat1(Float.valueOf((float) 5.1));
		bean.setI(6);
		bean.setInteger(new Integer(7));
		bean.setL(8);
		bean.setLong1(Long.valueOf(9));
		bean.setS((short) 10);
		bean.setShort1(Short.valueOf((short) 11));

		List<NumericBean> list = new ArrayList<NumericBean>();
		list.add(bean);

		return new Object[][] { { list } };
	}

	@Test(dataProvider = "numeric-bean")
	public void testConvertNumericBean(List<NumericBean> list) throws Exception {
		BeanListConverter converter = new BeanListConverter(list);
		IDataSet dataSet = converter.convert();

		ITable table = dataSet.getTable("NumericBean");
		int i = 0;
		for (Iterator<NumericBean> iterator = list.iterator(); iterator
			.hasNext();) {
			NumericBean bean = iterator.next();
			assertEquals(table.getValue(i, "d"), bean.getD());
			assertEquals(table.getValue(i, "decimal"), bean.getDecimal());
			assertEquals(table.getValue(i, "double1"), bean.getDouble1());
			assertEquals(table.getValue(i, "f"), bean.getF());
			assertEquals(table.getValue(i, "float1"), bean.getFloat1());
			assertEquals(table.getValue(i, "i"), bean.getI());
			assertEquals(table.getValue(i, "integer"), bean.getInteger());
			assertEquals(table.getValue(i, "l"), bean.getL());
			assertEquals(table.getValue(i, "long1"), bean.getLong1());
			assertEquals(table.getValue(i, "s"), bean.getS());
			assertEquals(table.getValue(i, "short1"), bean.getShort1());
			i++;
		}
	}

	@Test(dataProvider = "simple-bean")
	public void testAssertSimpleBean(List<SimpleBean> list) throws Exception {
		BeanListConverter converter = new BeanListConverter(list);
		IDataSet dataSet = converter.convert();

		AssertionHelper.assertEqualsOnlyColumnsInFile(
			dataSet,
			"SimpleBean.xml");

	}

	@Test(dataProvider = "date-bean")
	public void testAssertDateBean(List<DateBean> list) throws Exception {

		BeanListConverter converter = new BeanListConverter(list);
		IDataSet dataSet = converter.convert();

		AssertionHelper.assertEqualsOnlyColumnsInFile(
			dataSet,
			"DateBean.xml");

	}

	@Test(dataProvider = "numeric-bean")
	public void testAssertNumericBean(List<NumericBean> list) throws Exception {

		BeanListConverter converter = new BeanListConverter(list);
		IDataSet dataSet = converter.convert();

		AssertionHelper.assertEqualsOnlyColumnsInFile(
			dataSet,
			"NumericBean.xml");

	}
}
