using System.Text;
using MySql.Data.MySqlClient;
using MarketData.MarketDataModel;
using MarketData.Utils;

namespace MarketData.DataAccess
{
	public class EconomicIndicatorDA
	{
    private EconomicIndicatorDA()
    {
    }

    /// <summary>
    /// Retrieves a distinct list of indicator_code
    /// </summary>
    /// <returns></returns>
    public static List<String> GetDistinctIndicators()
    {
      MySqlConnection sqlConnection = null;
      MySqlCommand sqlCommand = null;
      MySqlDataReader sqlDataReader = null;
      List<String> indicators = new List<String>();
      try

      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sqlCommand = sqlConnection.CreateCommand();
        StringBuilder sb = new StringBuilder();
        sb.Append("select distinct(indicator_code) from EconomicIndicators ");
        sb.Append("ORDER BY 1 asc");
        sqlCommand.CommandText = sb.ToString();
        sqlDataReader = sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          indicators.Add(sqlDataReader.GetString(0).ToUpper());
        }
        sqlDataReader.Close();
        sqlDataReader.Dispose();
        sqlCommand.Dispose();
        sqlConnection.Close();
        sqlConnection.Dispose();
        return indicators;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
        return null;
      }
      finally
      {
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
        }
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
        }
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection.Dispose();
        }
      }
    }

    /// <summary>
    /// Retrieve all records
    /// </summary>
    /// <returns></returns>
    public static EconomicIndicators GetEconomicIndicators(String indicatorCode, String countryCode="USA")
    {
      MySqlConnection sqlConnection = null;
      MySqlCommand sqlCommand = null;
      MySqlDataReader sqlDataReader = null;
      EconomicIndicators economicIndicators = new EconomicIndicators();
      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sqlCommand = sqlConnection.CreateCommand();
        StringBuilder sb = new StringBuilder();
        sb.Append("select country_code,country_name,indicator_code,indicator_name,indicator_value,year,source from EconomicIndicators").Append(" ");
        sb.Append("where indicator_code=").Append(SqlUtils.AddQuotes(indicatorCode)).Append(" ");
        sb.Append("AND country_code = ").Append(SqlUtils.AddQuotes(countryCode)).Append(" ");
        sb.Append("ORDER BY YEAR DESC");
        sqlCommand.CommandText = sb.ToString();
        sqlDataReader = sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          EconomicIndicator economicIndicator = new EconomicIndicator();
          if (!sqlDataReader.IsDBNull(0)) economicIndicator.CountryCode = sqlDataReader.GetString(0);
          if (!sqlDataReader.IsDBNull(1)) economicIndicator.CountryName = sqlDataReader.GetString(1);
          if (!sqlDataReader.IsDBNull(2)) economicIndicator.IndicatorCode = sqlDataReader.GetString(2);
          if (!sqlDataReader.IsDBNull(3)) economicIndicator.IndicatorName = sqlDataReader.GetString(3);
          if (!sqlDataReader.IsDBNull(4)) economicIndicator.IndicatorValue = sqlDataReader.GetDouble(4);
          if (!sqlDataReader.IsDBNull(5)) economicIndicator.Year = sqlDataReader.GetInt32(5);
          if (!sqlDataReader.IsDBNull(6)) economicIndicator.Source = sqlDataReader.GetString(6);
          economicIndicators.Add(economicIndicator);
        }
        sqlDataReader.Close();
        sqlDataReader.Dispose();
        sqlCommand.Dispose();
        sqlConnection.Close();
        sqlConnection.Dispose();
        return economicIndicators;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
        return null;
      }
      finally
      {
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
        }
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
        }
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection.Dispose();
        }
      }
    }

    /// <summary>
    /// Retrieve all records
    /// </summary>
    /// <returns></returns>
    public static EconomicIndicators GetEconomicIndicators()
    {
      MySqlConnection sqlConnection = null;
      MySqlCommand sqlCommand = null;
      MySqlDataReader sqlDataReader = null;
      EconomicIndicators economicIndicators = new EconomicIndicators();
      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sqlCommand = sqlConnection.CreateCommand();
        StringBuilder sb = new StringBuilder();
        sb.Append("select country_code,country_name,indicator_code,indicator_name,indicator_value,year,source from EconomicIndicators");
        sqlCommand.CommandText = sb.ToString();
        sqlDataReader = sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          EconomicIndicator economicIndicator = new EconomicIndicator();
          if (!sqlDataReader.IsDBNull(0)) economicIndicator.CountryCode = sqlDataReader.GetString(0);
          if (!sqlDataReader.IsDBNull(1)) economicIndicator.CountryName = sqlDataReader.GetString(1);
          if (!sqlDataReader.IsDBNull(2)) economicIndicator.IndicatorCode = sqlDataReader.GetString(2);
          if (!sqlDataReader.IsDBNull(3)) economicIndicator.IndicatorName = sqlDataReader.GetString(3);
          if (!sqlDataReader.IsDBNull(4)) economicIndicator.IndicatorValue = sqlDataReader.GetDouble(4);
          if (!sqlDataReader.IsDBNull(5)) economicIndicator.Year = sqlDataReader.GetInt32(5);
          if (!sqlDataReader.IsDBNull(6)) economicIndicator.Source = sqlDataReader.GetString(6);
          economicIndicators.Add(economicIndicator);
        }
        sqlDataReader.Close();
        sqlDataReader.Dispose();
        sqlCommand.Dispose();
        sqlConnection.Close();
        sqlConnection.Dispose();
        return economicIndicators;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
        return null;
      }
      finally
      {
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
        }
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
        }
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection.Dispose();
        }
      }
    }

    /// <summary>
    /// Upsert items 
    /// </summary>
    /// <returns></returns>    
    public static bool InsertUpdateEconomicIndicators(EconomicIndicators economicIndicators)
    {
      MySqlConnection sqlConnection = null;
      MySqlCommand sqlCommand = null;
      MySqlTransaction sqlTransaction = null;
      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);
        sqlCommand = sqlConnection.CreateCommand();
        sqlCommand.Transaction = sqlTransaction;
        List<String> distinctCountryCodes = (from EconomicIndicator economicIndicator in economicIndicators select economicIndicator.CountryCode).Distinct().ToList();
        List<String> indicatorCodes = (from EconomicIndicator economicIndicator in economicIndicators select economicIndicator.IndicatorCode).Distinct().ToList();
        if(indicatorCodes.Count>1)
        {
          MDTrace.WriteLine(LogLevel.DEBUG, String.Format("InsertUpdateEconomicIndicators Expected a single indicator code but found multiple '{0}'",Utility.ListToString(indicatorCodes)));
          return false;
        }
        for (int index = 0; index < distinctCountryCodes.Count; index++)
        {
          String countryCode = distinctCountryCodes[index];
          List<int> years = (from EconomicIndicator economicIndicator in economicIndicators select economicIndicator.Year).Distinct().ToList();
          DeleteEconomicIndicator(indicatorCodes.First(),countryCode, years, sqlCommand, sqlTransaction);
        }
        InsertEconomicIndicators(economicIndicators, sqlCommand, sqlTransaction);
        sqlTransaction.Commit();
        sqlTransaction.Dispose();
        sqlCommand.Dispose();
        sqlConnection.Close();
        sqlConnection.Dispose();
        sqlConnection = null;
        sqlCommand = null;
        sqlTransaction = null;
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}", exception.ToString()));
        return false;
      }
      finally
      {
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection.Dispose();
        }
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
        }
        if (null != sqlTransaction)
        {
          sqlTransaction.Dispose();
        }
      }
    }

    /// <summary>
    /// Remove items 
    /// </summary>
    /// <returns></returns>      
    private static bool DeleteEconomicIndicator(String indicatorCode,String countryCode, List<int> years, MySqlCommand sqlCommand, MySqlTransaction sqlTransaction)
    {
      String strQuery = null;
      try
      {
        StringBuilder sb = new StringBuilder();
        sb.Append("delete from EconomicIndicators ").Append(" where ");
        sb.Append("indicator_code=").Append("'").Append(indicatorCode).Append("'").Append(" and ");
        sb.Append("country_code=").Append("'").Append(countryCode).Append("'").Append(" and ");
        sb.Append("year in ").Append(SqlUtils.CreateInClause(years));
        strQuery = sb.ToString();
        sqlCommand.CommandText = strQuery;
        sqlCommand.ExecuteNonQuery();
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}, query was {1}", exception.ToString(), strQuery));
        return false;
      }
    }

    /// <summary>
    /// Remove items 
    /// </summary>
    /// <returns></returns>      
    // private static bool DeleteEconomicIndicator(String countryCode, List<int> years, MySqlCommand sqlCommand, MySqlTransaction sqlTransaction)
    // {
    //   String strQuery = null;
    //   try
    //   {
    //     StringBuilder sb = new StringBuilder();
    //     sb.Append("delete from EconomicIndicators ").Append(" where ");
    //     sb.Append("country_code=").Append("'").Append(countryCode).Append("'").Append(" and ");
    //     sb.Append("year in ").Append(SqlUtils.CreateInClause(years));
    //     strQuery = sb.ToString();
    //     sqlCommand.CommandText = strQuery;
    //     sqlCommand.ExecuteNonQuery();
    //     return true;
    //   }
    //   catch (Exception exception)
    //   {
    //     MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Exception:{0}, query was {1}", exception.ToString(), strQuery));
    //     return false;
    //   }
    // }
    
    /// <summary>
    /// Insert items 
    /// </summary>
    /// <returns></returns>   
    private static bool InsertEconomicIndicators(EconomicIndicators economicIndicators,MySqlCommand sqlCommand,MySqlTransaction sqlTransaction)
    {
      String strQuery=null;
      try
      {
        StringBuilder sb=new StringBuilder();
        sb.Append("insert into EconomicIndicators(country_code,country_name,indicator_code,indicator_name,indicator_value,year,source)values");
        for(int index=0;index<economicIndicators.Count;index++)
        {
          EconomicIndicator economicIndicator = economicIndicators[index];
          sb.Append("(");
          sb.Append(SqlUtils.ToSqlString(economicIndicator.CountryCode)).Append(",");
          sb.Append(SqlUtils.ToSqlString(economicIndicator.CountryName)).Append(",");
          sb.Append(SqlUtils.ToSqlString(economicIndicator.IndicatorCode)).Append(",");
          sb.Append(SqlUtils.ToSqlString(economicIndicator.IndicatorName)).Append(",");
          sb.Append(economicIndicator.IndicatorValue).Append(",");
          sb.Append(economicIndicator.Year).Append(",");
          sb.Append(SqlUtils.ToSqlString(economicIndicator.Source));
          sb.Append(")");
          if(index<economicIndicators.Count-1)sb.Append(",");
          else sb.Append(";");
        }
        strQuery=sb.ToString();
        sqlCommand.CommandText=sb.ToString();
        sqlCommand.ExecuteNonQuery();
        return true;
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
			  return false;
      }
      finally
      {
      }
    }
	}
}
