package eu.dnetlib.dlms.jdbc;

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

import java.sql.Date;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.List;
import java.util.TimeZone;

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

import eu.dnetlib.dlms.rmi.ParameterDescription;

public class WSRemotePreparedStatementTest {

	private transient WSRemotePreparedStatement stmt;

	private ParameterDescription p1;
	private ParameterDescription p2;
	private ParameterDescription p3;

	@Before
	public void setUp() throws Exception {
		this.stmt = new WSRemotePreparedStatement(null, null, null);
		this.p1 = new ParameterDescription();
		this.p2 = new ParameterDescription();
		this.p3 = new ParameterDescription();
	}

	@Test
	public void testSetParameter() {
		this.stmt.setParameter(1, this.p1);
		this.stmt.setParameter(2, this.p2);
		this.stmt.setParameter(3, this.p3);

		final List<ParameterDescription> params = this.stmt.getStatementDescription().getPositionalParameters();
		assertEquals(this.p1, params.get(0));
		assertEquals(this.p2, params.get(1));
		assertEquals(this.p3, params.get(2));
	}

	@Test
	public void testSetParameter2() {
		this.stmt.setParameter(1, this.p1);
		this.stmt.setParameter(2, this.p2);
		this.stmt.setParameter(2, this.p3);

		final List<ParameterDescription> params = this.stmt.getStatementDescription().getPositionalParameters();
		assertEquals(this.p1, params.get(0));
		assertEquals(this.p3, params.get(1));
		assertEquals(2, params.size());
	}

	@Test(expected = IllegalArgumentException.class)
	public void testSetParameter3() {
		this.stmt.setParameter(1, this.p1);
		this.stmt.setParameter(2, this.p2);
		this.stmt.setParameter(4, this.p3);
	}

	@Test
	public void testSetters() throws SQLException {
		this.stmt.setString(1, "uno");
		this.stmt.setLong(2, 2);
		this.stmt.setInt(3, 3);

		this.stmt.setInt(4, 3);
		this.stmt.setString(4, "quattro");

		this.stmt.setInt(5, 5);
		this.stmt.setObject(5, new InformationObjectReference("5,unknown,unknown"));

		final List<ParameterDescription> params = this.stmt.getStatementDescription().getPositionalParameters();
		assertTrue(params.get(0).getType().equals("STRING"));
		assertTrue(params.get(0).getValue().equals("uno"));

		assertTrue(params.get(1).getType().equals("INT"));
		assertTrue(params.get(1).getValue().equals("2"));

		assertTrue(params.get(2).getType().equals("INT"));
		assertTrue(params.get(2).getValue().equals("3"));

		assertTrue(params.get(3).getType().equals("STRING"));
		assertTrue(params.get(3).getValue().equals("quattro"));

		assertEquals(5, params.size());
		assertTrue(params.get(4).getType().equals("INFORMATION_OBJECT"));
		assertTrue(params.get(4).getValue().equals("5,unknown,unknown"));
	}

	@Test(expected = IllegalArgumentException.class)
	public void testIllegalObject() throws SQLException {
		this.stmt.setObject(1, new Integer(1));
	}

	@Test
	public void testClearParameters() throws SQLException {
		this.stmt.setInt(1, 1);
		this.stmt.clearParameters();

		final List<ParameterDescription> params = this.stmt.getStatementDescription().getPositionalParameters();
		assertEquals(0, params.size());
	}

	@Test
	public void testDate() throws SQLException, ParseException {
		final Date date1 = new Date(0);
		this.stmt.setDate(1, date1);

		final List<ParameterDescription> params = this.stmt.getStatementDescription().getPositionalParameters();
		assertEquals("DATE", params.get(0).getType());
		assertEquals("Jan 1, 1970", params.get(0).getValue());

		final DateFormat df = DateFormat.getDateInstance();
		df.setTimeZone(TimeZone.getTimeZone("GMT"));
		final java.util.Date date2 = df.parse(params.get(0).getValue());
		final Date date3 = new Date(date2.getTime());

		assertTrue(date2.equals(date1));
		assertTrue(date3.equals(date1));
	}

}
