using System;
using System.Collections.Generic;

using Howest.SchemaDiscovery.DbObjects;
using System.Data.Common;
using Howest.SchemaDiscovery.CommonHelpers;

namespace Howest.SchemaDiscovery
{
	public abstract class DbSchemaProvider
	{
		public abstract bool UseNamedParameters
		{
			get;
		}

		public abstract DbProviderFactory GetFactory();
		
		public List<Table> GetTables(DbConnection connection)
		{
			if (ValidateConnection(connection))
			{
				try
				{
					return GetTablesFromDb(connection);
				}
				catch (NotImplementedException)
				{
				}
			}
			return new List<Table>();
		}

		protected abstract List<Table> GetTablesFromDb(DbConnection connection);

		public List<View> GetViews(DbConnection connection)
		{
			if (ValidateConnection(connection))
			{
				try
				{
					return GetViewsFromDb(connection);
				}
				catch (NotImplementedException)
				{
				}
			}
			return new List<View>();
		}

		protected abstract List<View> GetViewsFromDb(DbConnection connection);

		public List<Procedure> GetProcedures(DbConnection connection)
		{
			if (ValidateConnection(connection))
			{
				try
				{
					return GetProceduresFromDb(connection);
				}
				catch (NotImplementedException)
				{
				}
			}
			return new List<Procedure>();
		}

		protected abstract List<Procedure> GetProceduresFromDb(DbConnection connection);


		public List<Parameter> GetProcedureResultSet(DbConnection connection, Procedure procedure)
		{
			if (ValidateConnection(connection))
			{
				try
				{
					return GetProceduresResultSetFromDb(connection, procedure);
				}
				catch (NotImplementedException)
				{
				}
			}
			return new List<Parameter>();
		}

		protected abstract List<Parameter> GetProceduresResultSetFromDb(DbConnection connection, Procedure procedure);

		protected abstract bool ValidateConnection(DbConnection connection);

		public List<Relation> GetRelations(DbConnection connection)
		{
			if (ValidateConnection(connection))
			{
				try
				{
					return GetRelationsFromDb(connection);
				}
				catch (NotImplementedException)
				{
				}
			}
			return new List<Relation>();
			/*if (col.IsPrimaryKey)
			{
				try
				{
					return GetRelatedColumnsFromDb(connection, col.Table.Schema, col.Table.Name, col.Name);
				}
				catch (NotSupportedException)
				{ 
				}
			}
			return new List<Column>();*/
		}

		protected abstract List<Relation> GetRelationsFromDb(DbConnection connection);

		/*protected abstract List<Column> GetRelatedColumnsFromDb(DbConnection connection, string schema, string table, string col);

		public Column GetReferencedColumn(DbConnection connection, Column col)
		{
			if (col.IsForeignKey)
			{
				try
				{
					return GetReferencedColumnFromDb(connection, col.Table.Schema, col.Table.Name, col.Name);
				}
				catch (NotSupportedException)
				{ 
				}
			}
			return null;
		}

		protected abstract Column GetReferencedColumnFromDb(DbConnection connection, string schema, string table, string col);*/

		public List<Parameter> GetSqlResultSet(DbConnection con, string sql)
		{
			if (ValidateConnection(con))
			{
				try
				{
					return GetSqlResultSetFromDb(con, sql);
				}
				catch (NotImplementedException)
				{
				}
			}
			return new List<Parameter>();
		}

		protected abstract List<Parameter> GetSqlResultSetFromDb(DbConnection connection, string sql);

		public void RunSqlStatement(DbConnection con, string sql)
		{
			if (ValidateConnection(con))
			{
				RunSqlStatementToDb(con, sql);
			}
		}

		protected abstract void RunSqlStatementToDb(DbConnection connection, string sql);
	}
}
