package eu.dnetlib.dlms.jdbc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.net.URL;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import com.google.common.collect.Lists;

import eu.dnetlib.dlms.lowlevel.objects.DorotyObjectEnum;
import eu.dnetlib.dlms.lowlevel.objects.structures.BooleanBasicValue;
import eu.dnetlib.dlms.lowlevel.objects.structures.DateBasicValue;
import eu.dnetlib.dlms.lowlevel.objects.structures.DescriptionValueCollection;
import eu.dnetlib.dlms.lowlevel.objects.structures.DoubleBasicValue;
import eu.dnetlib.dlms.lowlevel.objects.structures.IntBasicValue;
import eu.dnetlib.dlms.lowlevel.objects.structures.LabelValue;
import eu.dnetlib.dlms.lowlevel.objects.structures.StringBasicValue;

/**
 * @author lexis
 * 
 */
public class DOLResultSetTest {

	private DOLResultSet resultSet;
	private ColumnInfo[] resultSetInfo;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		//colInfo with 9 elements, one for each type
		this.resultSetInfo = new ColumnInfo[] { new ColumnInfo("boolCol", DorotyObjectEnum.d_boolean),
				new ColumnInfo("dateCol", DorotyObjectEnum.d_date), new ColumnInfo("doubleCol", DorotyObjectEnum.d_double),
				new ColumnInfo("intCol", DorotyObjectEnum.d_int), new ColumnInfo("longCol", DorotyObjectEnum.std_long),
				new ColumnInfo("objCol", DorotyObjectEnum.object), new ColumnInfo("stringCol", DorotyObjectEnum.d_string),
				new ColumnInfo("urlCol", DorotyObjectEnum.std_url), new ColumnInfo("collCol", DorotyObjectEnum.d_coll),

		};
		final List<DataResult> rsContent = Lists.newArrayList();
		final DescriptionValueCollection dvc = new DescriptionValueCollection(DorotyObjectEnum.d_string);
		//dvc.setCollType(new CollectionDescriptionType(new BasicType(StringBasicValue.class)));
		final List<LabelValue> values = Lists.newArrayList();
		values.add(new StringBasicValue("hello"));
		values.add(new StringBasicValue("world"));
		values.add(new StringBasicValue("!"));
		dvc.setValueCollection(values);
		rsContent.add(new DataResult(new Object[] { new BooleanBasicValue(true), new DateBasicValue("2010-12-12"), new DoubleBasicValue(1.0),
				new IntBasicValue(1), new Long(2), new InformationObjectImpl(1), new StringBasicValue("hello world"), new URL("http://doroty/1"), dvc }));
		this.resultSet = new SimpleDOLResultSet(new DOLStatement(), this.resultSetInfo);
		this.resultSet.setResults(rsContent);
		this.resultSet.setCurrResultIndex(0);
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getBoolean(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetBooleanInt() throws SQLException {
		assertTrue(this.resultSet.getBoolean(1));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getDate(int)}. TODO: fix issues with dates...It is a
	 * mess!!!
	 * 
	 * @throws SQLException
	 */
	@Test
	@Ignore
	public void testGetDateInt() throws SQLException {
		assertNotNull(this.resultSet.getDate(2));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getDouble(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetDoubleInt() throws SQLException {
		assertEquals(this.resultSet.getDouble(3), 1.0, 0);
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getInt(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetIntInt() throws SQLException {
		assertEquals(this.resultSet.getInt(4), 1);
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getLong(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetLongInt() throws SQLException {
		assertEquals(this.resultSet.getLong(5), 2);
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getObject(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetObjectInt() throws SQLException {
		assertNotNull(this.resultSet.getObject(6));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getString(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetStringInt() throws SQLException {

		assertNotNull(this.resultSet.getString(7));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getURL(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetURLInt() throws SQLException {

		assertNotNull(this.resultSet.getURL(8));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getObject(int)}.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void testGetCollField() throws SQLException {

		assertNotNull(this.resultSet.getObject(9));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.DOLResultSet#getObject(int)}.
	 * 
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	@Test
	public void testGetObjectAll() throws SQLException, ClassNotFoundException {
		final BooleanBasicValue b1 = (BooleanBasicValue) this.resultSet.getObject(1);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(1), b1.getClass().getCanonicalName());
		final DateBasicValue d2 = (DateBasicValue) this.resultSet.getObject(2);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(2), d2.getClass().getCanonicalName());
		final DoubleBasicValue d3 = (DoubleBasicValue) this.resultSet.getObject(3);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(3), d3.getClass().getCanonicalName());
		final IntBasicValue i4 = (IntBasicValue) this.resultSet.getObject(4);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(4), i4.getClass().getCanonicalName());
		final Long l5 = (Long) this.resultSet.getObject(5);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(5), l5.getClass().getCanonicalName());
		final InformationObject o6 = (InformationObject) this.resultSet.getObject(6);
		final Class<?>[] objInterfaces = o6.getClass().getInterfaces();
		assertTrue(Arrays.asList(objInterfaces).contains(Class.forName(this.resultSet.getMetaData().getColumnClassName(6))));
		final StringBasicValue s7 = (StringBasicValue) this.resultSet.getObject(7);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(7), s7.getClass().getCanonicalName());
		final URL u8 = (URL) this.resultSet.getObject(8);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(8), u8.getClass().getCanonicalName());
		final DescriptionValueCollection c9 = (DescriptionValueCollection) this.resultSet.getObject(9);
		assertEquals(this.resultSet.getMetaData().getColumnClassName(9), c9.getClass().getCanonicalName());
		//final Collection<String> c9 = (Collection<String>) this.resultSet.getObject(9);

	}
}
