package profileEngine;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ListIterator;

public class TableList 
{
	public TableList(Connection dataConnection, String databaseProduct, String database, String schema)
	{
		DatabaseMetaData databaseMetaData = null;
		ResultSet tableNames = null;
		String query;
		Statement statement = null;
		ResultSet rowCount = null;
		String tableName;
		String[] tableTypes = {"TABLE"};
		TableElement tableElement;
		String encoding;
		DatabaseSchemaTableList databaseSchemaTableList;
		ListIterator<TableElement> iterator;
		
		new DatabaseEncoding(dataConnection, databaseProduct, database);
		encoding = new String(DatabaseEncoding.getEncoding());
		
		DatabaseSchemaTableList databaseSchemaTableListWithCount;
		
		databaseSchemaTableList = new DatabaseSchemaTableList();
		
		try 
		{
			databaseMetaData = dataConnection.getMetaData();
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
		}	
		
		try 
		{
			tableNames = databaseMetaData.getTables(null, schema, null, tableTypes);
//			tableNames = databaseMetaData.getTables(database, schema, null, tableTypes);
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
		}

//		new MetaDataColumns(tableNames);
		
		//  hive-jdbc.jar (from Apache) requires column names for database metadata to be in uppercase.
		//  Does this apply on all ResultSets?  Are column names simply case-sensitive?
		try 
		{
			while (tableNames.next())
			{
				tableElement = new TableElement
				(
					tableNames.getString("TABLE_CAT"),      // This is a gratuitous abbreviation of CATALOG.  I use it because it is in the DatabaseMetadata class (as TABLE_CAT)
					encoding,
					tableNames.getString("TABLE_SCHEM"),    // This is a gratuitous abbreviation of SCHEMA.  I use it because it is in the DatabaseMetadata class (as TABLE_SCHEM)
					tableNames.getString("TABLE_NAME"),
					tableNames.getString("TABLE_TYPE"),		// This is a rubbish name.  What does it mean? I use it because it is in the DatabaseMetadata class (as TABLE_TYPE)
					tableNames.getString("REMARKS")			// This is a rubbish name.  What does it mean? I use it because it is in the DatabaseMetadata class (as REMARKS)
				);
				if (databaseProduct.equals("PostgreSQL"))
					tableElement.setDatabaseName(database);
				databaseSchemaTableList.add(tableElement);
//				System.out.println("Database: " + database + " , TABLE_CAT: " + tableNames.getString("TABLE_CAT"));
			}
		} 
		catch (SQLException e) 
		{
			e.printStackTrace();
		}

		databaseSchemaTableListWithCount = new DatabaseSchemaTableList();
		
		for (iterator = databaseSchemaTableList.listIterator(); iterator.hasNext();)
		{
			tableElement = (TableElement) iterator.next();
			tableName = new String(tableElement.getTableName());
			if (tableName.contains(" "))
				tableName = new String("\"" + tableName + "\"");
			query = new String("select count(*) as row_count from " + database + "." + schema + "." + tableName);
			try 
			{
				statement = dataConnection.createStatement();
			} 
			catch (SQLException e) 
			{
				e.printStackTrace();
			}
			try 
			{
				rowCount = statement.executeQuery(query);
				if (rowCount.next())
				{
					tableElement.setRowCount(rowCount.getInt("row_count"));
					databaseSchemaTableListWithCount.add(tableElement);
				}
			} 
			catch (SQLException e) 
			{
				System.out.println("Failed to select from table " + tableName + ".  Probably a permission/ownership issue.");
			}
		}
		databaseSchemaTableListWithCount.print("table");
	}
}