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.Date;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;

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

import eu.dnetlib.dlms.jdbc.serialization.ItemWrapper;
import eu.dnetlib.dlms.jdbc.serialization.RSMetadataWrapper;

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

	private transient WSRemoteResultSet remoteRS;
	//9 elements in row:
	String xmlString = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><ns2:item xmlns:ns2='http://dnetlib.eu/itemwrapper'>"
			+ "<types>BOOLEAN</types>" + "<types>DATE</types>" + "<types>DOUBLE</types>" + "<types>INT</types>" + "<types>LONG</types>"
			+ "<types>INFORMATION_OBJECT</types>" + "<types>STRING</types>" + "<types>URL</types>" + "<types>COLL</types>" + "<values>true</values>"
			+ "<values>2010-03-06</values>" + "<values>1.0</values>" + "<values>1</values>" + "<values>2</values>" + "<values>3,setname,type</values>"
			+ "<values>hello</values>" + "<values>http://doroty/1</values>" + "<values>[hello, world, !] | STRING</values>" + "</ns2:item>";
	String metadataString = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><ns2:rsmetadata xmlns:ns2='http://dnetlib.eu/rsmetadatawrapper'>"
			+ "<columnCount>9</columnCount>" + "<columnNames>boolCol</columnNames>" + "<columnTypeCodes>6</columnTypeCodes>"
			+ "<columnNames>dateCol</columnNames>" + "<columnTypeCodes>4</columnTypeCodes>" + "<columnNames>doubleCol</columnNames>"
			+ "<columnTypeCodes>15</columnTypeCodes>" + "<columnNames>intCol</columnNames>" + "<columnTypeCodes>2</columnTypeCodes>"
			+ "<columnNames>longCol</columnNames>" + "<columnTypeCodes>9</columnTypeCodes>" + "<columnNames>objCol</columnNames>"
			+ "<columnTypeCodes>13</columnTypeCodes>" + "<columnNames>strCol</columnNames>" + "<columnTypeCodes>0</columnTypeCodes>"
			+ "<columnNames>urlCol</columnNames>" + "<columnTypeCodes>8</columnTypeCodes>" + "<columnNames>collCol</columnNames>"
			+ "<columnTypeCodes>16</columnTypeCodes>" + "</ns2:rsmetadata>";

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		this.remoteRS = new WSRemoteResultSet(null, null, null);
		this.remoteRS.setCurrentValue(this.xmlString);
		this.remoteRS.setMetaData(this.remoteRS.unwrapMetaData(this.metadataString));
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.WSRemoteResultSet#unwrap(java.lang.String)}.
	 */
	@Test
	public void testUnwrapString() {
		final ItemWrapper iw = this.remoteRS.unwrap(this.xmlString);
		System.out.println(iw);
		for (int i = 0; i < iw.getTypes().size(); i++) {
			System.out.println(iw.getTypes().get(i));
			System.out.println(iw.getValues().get(i));
		}
	}

	/**
	 * Test method for {@link eu.dnetlib.dlms.jdbc.WSRemoteResultSet#unwrap(java.lang.String)}.
	 */
	@Test
	public void testUnwrapMetaDataString() {
		final RSMetadataWrapper mw = this.remoteRS.unwrapMetaData(this.metadataString);
		System.out.println(mw);
		System.out.println("metadata column count == " + mw.getColumnCount());
		for (int i = 0; i < mw.getColumnNames().size(); i++) {
			System.out.println(mw.getColumnNames().get(i));
			System.out.println(mw.getColumnTypeCodes().get(i));
		}
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

	}

}
