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

namespace MarketData.DataAccess
{
  public class SECFilingDA
  {
    private SECFilingDA()
    {
    }
    public static List<String> GetDistinctFilingSymbols()
    {
      List<String> distinctSymbols = new List<String>();
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
			MySqlCommand sqlCommand=null;
      String strQuery = null;

      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        StringBuilder sb = new StringBuilder();
        sb.Append("select distinct(symbol) from secfilings order by symbol asc");
        strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlDataReader = sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          distinctSymbols.Add(sqlDataReader.GetString(0));
        }
        return distinctSymbols;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return null;
      }
      finally
      {
				if(null!=sqlCommand)sqlCommand.Dispose();
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
    public static List<DateTime> GetDistinctFilingDatesForSymbol(String symbol)
    {
      List<DateTime> distinctFilingDates = new List<DateTime>();
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
			MySqlCommand sqlCommand =null;
      String strQuery = null;

      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        StringBuilder sb = new StringBuilder();
        sb.Append("select distinct(filing_date) from secfilings where symbol=");
        sb.Append(SqlUtils.AddQuotes(symbol));
        sb.Append(" order by 1 desc");
        strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlDataReader = sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          distinctFilingDates.Add(sqlDataReader.GetDateTime(0));
        }
        return distinctFilingDates;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return null;
      }
      finally
      {
				if(null!=sqlCommand)sqlCommand.Dispose();
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
    public static SEC13Info GetSEC13Info(String symbol)
    {
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
			MySqlCommand sqlCommand=null;
      String strQuery = null;
      SEC13Info sec13Info=new SEC13Info();

      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        StringBuilder sb = new StringBuilder();
        sec13Info.Symbol=symbol;
        sb.Append("	select symbol,max(filing_date),count(*) from secfilings where symbol='").Append(symbol).Append("' and (form like '%13D%' or form like '%13G%')"); 
        sb.Append(" group by symbol having datediff(curdate(),max(filing_date))<180");
        strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlDataReader = sqlCommand.ExecuteReader();
        if (!sqlDataReader.Read()) return sec13Info;
        sec13Info.SEC13=true;
        sec13Info.MostRecentFilingDate=sqlDataReader.GetDateTime(1);
        sec13Info.Filings=sqlDataReader.GetInt32(2);
        return sec13Info;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return sec13Info;
      }
      finally
      {
				if(null!=sqlCommand)sqlCommand.Dispose();
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
    public static bool HaveSECFiling(SECFiling secFiling)
    {
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
			MySqlCommand sqlCommand=null;
      String strQuery = null;

      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        StringBuilder sb = new StringBuilder();
        sb.Append("select count(*) from secfilings ");
        sb.Append("where symbol=").Append(SqlUtils.AddQuotes(secFiling.Symbol)).Append(" ");
        sb.Append("and filing_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate))).Append(" ");
        sb.Append("and sec_accession_number=").Append(SqlUtils.AddQuotes(secFiling.SECAccessionNumber)).Append(" ");
        sb.Append("and sequence=").Append(secFiling.Sequence).Append(" ");
        strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlDataReader = sqlCommand.ExecuteReader();
        if (!sqlDataReader.Read()) return false;
        int recordCount = sqlDataReader.GetInt32(0);
        return recordCount > 0 ? true : false;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return false;
      }
      finally
      {
				if(null!=sqlCommand)sqlCommand.Dispose();
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
    public static bool DeleteSECFiling(SECFiling secFiling,MySqlTransaction sqlTransaction) 
    {
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
			MySqlCommand sqlCommand =null;
      String strQuery = null;

      try
      {
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        StringBuilder sb = new StringBuilder();
        sb.Append("delete from secfilings ");
        sb.Append("where symbol=").Append(SqlUtils.AddQuotes(secFiling.Symbol)).Append(" ");
        sb.Append("and filing_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate)));
        sb.Append("and sec_accession_number=").Append(SqlUtils.AddQuotes(secFiling.SECAccessionNumber));
        sb.Append("and sequence=").Append(secFiling.Sequence);
        strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection,sqlTransaction);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlCommand.ExecuteNonQuery();
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return false;
      }
      finally
      {
				if(null!=sqlCommand)sqlCommand.Dispose();
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
    public static bool InsertOrUpdateSECFilings(SECFilings secFilings)
    {
      MySqlTransaction sqlTransaction = null;
      MySqlConnection sqlConnection = null;

      try
      {
        secFilings=secFilings.Distinct();
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
        for (int index = 0; index < secFilings.Count; index++)
        {
          SECFiling secFiling = secFilings[index];
          if (HaveSECFiling(secFiling)) DeleteSECFiling(secFiling,sqlTransaction);
          InsertSECFiling(secFiling,sqlConnection,sqlTransaction);
        }
        sqlTransaction.Commit();
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return false;
      }
      finally
      {
        if (null != sqlTransaction)
        {
          sqlTransaction.Dispose();
          sqlTransaction = null;
        }
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
      }
    }
    public static bool InsertSECFilings(SECFilings secFilings)
    {
      MySqlTransaction sqlTransaction = null;
      MySqlConnection sqlConnection = null;

      try
      {
        secFilings=secFilings.Distinct();
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
        for (int index = 0; index < secFilings.Count; index++)
        {
          SECFiling secFiling = secFilings[index];
          if (HaveSECFiling(secFiling)) continue;
          InsertSECFiling(secFiling, sqlConnection, sqlTransaction);
        }
        sqlTransaction.Commit();
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return false;
      }
      finally
      {
        if (null != sqlTransaction)
        {
          sqlTransaction.Dispose();
          sqlTransaction = null;
        }
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
      }
    }
    private static bool InsertSECFiling(SECFiling secFiling,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction)
    {
      MySqlCommand sqlCommand = null;
      try
      {
        StringBuilder sb = new StringBuilder();
        sqlCommand = new MySqlCommand();
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlCommand.Connection = sqlConnection;
        sb.Append("insert into secfilings(sec_accession_number,sequence,symbol,filing_date,form,form_text,description,sec_filing_url)");
        sb.Append(" values(?sec_accession_number,?sequence,?symbol,?filing_date,?form,?form_text,?description,?secFilingUrl);");
        MySqlParameter secAccessionNumberParameter = new MySqlParameter("?sec_accession_number", MySqlDbType.VarChar,50);
        MySqlParameter sequenceParameter = new MySqlParameter("?sequence", MySqlDbType.Int32);
        MySqlParameter symbolParameter = new MySqlParameter("?symbol", MySqlDbType.VarChar, 15);
        MySqlParameter filingDateParameter = new MySqlParameter("?filing_date", MySqlDbType.DateTime);
        MySqlParameter formParameter = new MySqlParameter("?form", MySqlDbType.VarChar,25);
        MySqlParameter formTextParameter = new MySqlParameter("?form_text", MySqlDbType.Blob, secFiling.FormText.Length);
        MySqlParameter descriptionParameter = new MySqlParameter("?description", MySqlDbType.VarChar, 128);
        MySqlParameter secFilingUrlParameter = new MySqlParameter("?secFilingUrl", MySqlDbType.VarChar, 255);
        secAccessionNumberParameter.Value = secFiling.SECAccessionNumber;
        sequenceParameter.Value = secFiling.Sequence;
        symbolParameter.Value = secFiling.Symbol;
        filingDateParameter.Value=Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate);
        formParameter.Value=secFiling.Form;
        formTextParameter.Value = Utility.Compress(secFiling.FormText);
        descriptionParameter.Value = secFiling.Description;
        secFilingUrlParameter.Value = secFiling.SecFilingUrl;
        sqlCommand.Parameters.Add(secAccessionNumberParameter);
        sqlCommand.Parameters.Add(symbolParameter);
        sqlCommand.Parameters.Add(filingDateParameter);
        sqlCommand.Parameters.Add(formParameter);
        sqlCommand.Parameters.Add(formTextParameter);
        sqlCommand.Parameters.Add(descriptionParameter);
        sqlCommand.Parameters.Add(secFilingUrlParameter);
        sqlCommand.Parameters.Add(sequenceParameter);
        sqlCommand.CommandText = sb.ToString();
        sqlCommand.ExecuteNonQuery();
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return false;
      }
      finally
      {
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
          sqlCommand = null;
        }
      }
    }
    public static SECFilings GetSECFilings(String symbol)
    {
      MySqlCommand sqlCommand = null;
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
      SECFilings secFilings = new SECFilings();
      try
      {
        StringBuilder sb = new StringBuilder();
        sqlCommand = null;
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sb.Append("select symbol,filing_date,form,length(form_text),form_text,description,sec_filing_url,sequence,sec_accession_number from secfilings ");
        sb.Append("where symbol='").Append(symbol).Append("' order by filing_date desc");
        String strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlDataReader=sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          SECFiling secFiling = new SECFiling();
          secFiling.Symbol = sqlDataReader.GetString(0);
          secFiling.FilingDate = sqlDataReader.GetDateTime(1);
          secFiling.Form = sqlDataReader.GetString(2);
          int lengthFormText=sqlDataReader.GetInt32(3);
          byte[] formTextBytes=new byte[lengthFormText];
          sqlDataReader.GetBytes(4,0,formTextBytes,0,lengthFormText);
          secFiling.FormText=Utility.Decompress(formTextBytes);
          secFiling.Description = sqlDataReader.GetString(5);
          secFiling.SecFilingUrl = sqlDataReader.GetString(6);
          secFiling.Sequence = sqlDataReader.GetInt32(7);
          secFiling.SECAccessionNumber = sqlDataReader.GetString(8);
          secFilings.Add(secFiling);
        }
        return secFilings;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return null;
      }
      finally
      {
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
          sqlCommand = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
    public static SECFilings GetSECFilings(String symbol,DateTime filingDate)
    {
      MySqlCommand sqlCommand = null;
      MySqlConnection sqlConnection = null;
      MySqlDataReader sqlDataReader = null;
      SECFilings secFilings = new SECFilings();
      try
      {
        StringBuilder sb = new StringBuilder();
        sqlCommand = null;
        sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data"));
        sb.Append("select symbol,filing_date,form,length(form_text),form_text,description,sec_filing_url,sequence,sec_accession_number from secfilings ");
        sb.Append("where symbol=").Append(SqlUtils.AddQuotes(symbol));
        sb.Append(" and filing_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(filingDate)));
        sb.Append(" order by filing_date desc");
        String strQuery = sb.ToString();
        sqlCommand = new MySqlCommand(strQuery, sqlConnection);
        sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT;
        sqlDataReader = sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
          SECFiling secFiling = new SECFiling();
          secFiling.Symbol = sqlDataReader.GetString(0);
          secFiling.FilingDate = sqlDataReader.GetDateTime(1);
          secFiling.Form = sqlDataReader.GetString(2);
          int lengthFormText = sqlDataReader.GetInt32(3);
          byte[] formTextBytes = new byte[lengthFormText];
          sqlDataReader.GetBytes(4, 0, formTextBytes, 0, lengthFormText);
          secFiling.FormText = Utility.Decompress(formTextBytes);
          secFiling.Description = sqlDataReader.GetString(5);
          secFiling.SecFilingUrl = sqlDataReader.GetString(6);
          secFiling.Sequence = sqlDataReader.GetInt32(7);
          secFiling.SECAccessionNumber = sqlDataReader.GetString(8);
          secFilings.Add(secFiling);
        }
        return secFilings;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return null;
      }
      finally
      {
        if (null != sqlConnection)
        {
          sqlConnection.Close();
          sqlConnection = null;
        }
        if (null != sqlCommand)
        {
          sqlCommand.Dispose();
          sqlCommand = null;
        }
        if (null != sqlDataReader)
        {
          sqlDataReader.Close();
          sqlDataReader.Dispose();
          sqlDataReader = null;
        }
      }
    }
  }
}

