/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2008 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.io.sql;

import static org.junit.Assert.*;

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

import com.approximatrix.draco.datamodel.DateObject;
import com.approximatrix.draco.datamodel.StatTableModel;

public class DracoSQLReadTest {

	private static final String PANEL_FILE = "resources/panel.sql-draco";
	private static final String ANNUAL_FILE = "resources/annual.sql-draco";
	private static final String QUARTERLY_FILE = "resources/quarterly.sql-draco";
	private static final String MONTHLY_FILE = "resources/monthly.sql-draco";
	private static final String BIMONTHLY_FILE = "resources/bimonthly.sql-draco";
	private static final String WEEKLY_FILE = "resources/weekly.sql-draco";
	private static final String DAILY_FILE = "resources/daily.sql-draco";
	
	private DracoSQLRead reader = null;
	
	@Before
	public void setUp() throws Exception {
		
	}

	@After
	public void tearDown() throws Exception {
		if(reader != null)
			reader.close();
		reader = null;
	}

	@Test
	public void testLoadModelPanelData() {
		reader = new DracoSQLRead(PANEL_FILE);
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(30,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		assertEquals("series1",model.getColumnName(0));
		assertEquals("series2",model.getColumnName(1));
		
		int i=0;
		for(Number x : model.getVariable(0)) {
			assert(x instanceof Integer);
			assertEquals(x.intValue(),i);
			i++;
		}
		
		i=0;
		for(Number x : model.getVariable(0)) {
			assert(x instanceof Double);
			assertEquals(x.intValue(),i);
			i++;
		}
	}
	
	@Test
	public void testLoadModelAnnual() {
		reader = new DracoSQLRead(ANNUAL_FILE);
		
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(21,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		
		assertEquals("Time",model.getColumnName(0));
		assertEquals("ser1",model.getColumnName(1));
		
		assertEquals(DateObject.YEARLY,model.getDateType());
		assertEquals(0,model.getDateColumn());
		
		for(int i=0;i<21;i++) {
			assertTrue(model.getVariable(0).get(i) instanceof DateObject);
			assertEquals(Integer.toString(i+1980),model.getVariable(0).get(i).toString());
			assertEquals(i,model.getVariable(0).get(i).intValue());
		}
	}

	@Test
	public void testLoadModelQuarterly() {
		reader = new DracoSQLRead(QUARTERLY_FILE);
		
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(24,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		
		assertEquals("Time",model.getColumnName(0));
		assertEquals("ser1",model.getColumnName(1));
		
		assertEquals(DateObject.QUARTERLY,model.getDateType());
		assertEquals(0,model.getDateColumn());
		
		for(int i=0;i<24;i++) {
			DateObject toCompare = new DateObject(DateObject.QUARTERLY,1980+i/4,i%4+1,0,0,0,0);
			
			assertTrue(model.getVariable(0).get(i) instanceof DateObject);
			assertEquals(toCompare.toString(),model.getVariable(0).get(i).toString());
			assertEquals(i,model.getVariable(0).get(i).intValue());
		}
	}
	
	@Test
	public void testLoadModelMonthly() {
		reader = new DracoSQLRead(MONTHLY_FILE);
		
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(24,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		
		assertEquals("Time",model.getColumnName(0));
		assertEquals("ser1",model.getColumnName(1));
		
		assertEquals(DateObject.MONTHLY,model.getDateType());
		assertEquals(0,model.getDateColumn());
		
		for(int i=0;i<24;i++) {
			DateObject toCompare = new DateObject(DateObject.MONTHLY,1980+i/12,0,i%12+1,0,0,0);
			
			assertTrue(model.getVariable(0).get(i) instanceof DateObject);
			assertEquals(toCompare.toString(),model.getVariable(0).get(i).toString());
			assertEquals(i,model.getVariable(0).get(i).intValue());
		}
	}
	
	@Test
	public void testLoadModelBiMonthly() {
		reader = new DracoSQLRead(BIMONTHLY_FILE);
		
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(48,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		
		assertEquals("Time",model.getColumnName(0));
		assertEquals("ser1",model.getColumnName(1));
		
		assertEquals(DateObject.BIMONTHLY,model.getDateType());
		assertEquals(0,model.getDateColumn());
		
		for(int i=0;i<48;i++) {
			DateObject toCompare = new DateObject(DateObject.BIMONTHLY,1980+i/24,0,(i/2)%12+1,i%2+1,0,0);
			
			assertTrue(model.getVariable(0).get(i) instanceof DateObject);
			assertEquals(toCompare.toString(),model.getVariable(0).get(i).toString());
			assertEquals(i,model.getVariable(0).get(i).intValue());
		}
	}
	
	@Test
	public void testLoadModelWeekly() {
		reader = new DracoSQLRead(WEEKLY_FILE);
		
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(104,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		
		assertEquals("Time",model.getColumnName(0));
		assertEquals("ser1",model.getColumnName(1));
		
		assertEquals(DateObject.WEEKLY,model.getDateType());
		assertEquals(0,model.getDateColumn());
		
		for(int i=0;i<104;i++) {
			DateObject toCompare = new DateObject(DateObject.WEEKLY,1980+i/52,0,0,0,i%52+1,0);
			
			assertTrue(model.getVariable(0).get(i) instanceof DateObject);
			assertEquals(toCompare.toString(),model.getVariable(0).get(i).toString());
			assertEquals(i,model.getVariable(0).get(i).intValue());
		}
	}
	
	@Test
	public void testLoadModelDaily() {
		reader = new DracoSQLRead(DAILY_FILE);
		
		StatTableModel model = reader.loadModel();
		
		assertNotNull(model);
		assertEquals(62,model.getRowCount());
		assertEquals(2,model.getColumnCount());
		
		assertEquals("Time",model.getColumnName(0));
		assertEquals("ser1",model.getColumnName(1));
		
		assertEquals(DateObject.DAILY,model.getDateType());
		assertEquals(0,model.getDateColumn());
		
		for(int i=0;i<62;i++) {
			
			DateObject toCompare = new DateObject(DateObject.DAILY,i <= 30 ? 1980 : 1981, 0,
																   i <= 30 ? 12 : 1, 0,0,
																   i <= 30 ? i+1 : i-30);

			assertTrue(model.getVariable(0).get(i) instanceof DateObject);
			assertEquals(toCompare.toString(),model.getVariable(0).get(i).toString());
			assertEquals(i,model.getVariable(0).get(i).intValue());
		}
	}
	
	@Test
	public void testLoadConstants() {
		reader = new DracoSQLRead(PANEL_FILE);
		StatTableModel model = reader.loadModel();
		assertTrue(reader.loadConstants(model));
		
		assertNotNull(model.getConstants());
		assertEquals(3,model.getConstants().size());

		assertValidConstant(model,"one",1);
		assertValidConstant(model,"two",2);
		assertValidConstant(model,"three",3);
	}

	private void assertValidConstant(StatTableModel model, String cname, int value) {
		assertNotNull(model.getConstantValue(cname));
		assertEquals(value,model.getConstantValue(cname).intValue());
	}
	
}
