using System;
using System.Text;
using System.Collections.Specialized;
using Amib.Threading;
using System.Collections.Generic;
using PDFGenerator.BusinessLayer;
using PDFGenerator;
using System.IO;
using System.Configuration;
using System.Data;
using System.Diagnostics;

namespace GestorePDF {
    public class GestoreThread {

        private DataThread _dataThread;
        private List<SessionStruct> _tabelleSessione;       
      
   
        public GestoreThread(DataThread dataThread)
        {
            //_tabelleSessione = tabelleSessione;
            _dataThread = dataThread;
            _tabelleSessione = new List<SessionStruct>();

        }

       public int StartWork() {
           int returnValue = 0;
           try
           {

               // Inizio Elaborazione PDF
               //string sAppoIDElaborazionePDF = string.Empty;
               //sAppoIDElaborazionePDF = InizioElaborazionePDF();

               _dataThread.TipoReport = "DIAGNOSI";

               ReportType reportTypeDiagnosi = _dataThread.ReportsType.Find(delegate(ReportType r)
               {
                   return r.Descrizione.ToUpper() == "DIAGNOSI";
               });
               if (reportTypeDiagnosi != null)
               {
                   this.MakePDF(_tabelleSessione, _dataThread);
               }

               ReportType reportTypeMonitoraggio = _dataThread.ReportsType.Find(delegate(ReportType r)
               {
                   return r.Descrizione.ToUpper() == "MONITORAGGIO";
               });
               if (reportTypeMonitoraggio != null)
               {
                   _dataThread.TipoReport = "MONITORAGGIO";
                   this.MakePDF(_tabelleSessione, _dataThread);
                   //per mandare in errore il codice
                   //string prova = "aaa";
                   //apppoo = prova.Substring(-1);
               }

               // Fine Inizio Elaborazione PDF
               //da fare Lele: eliminare riga IDElaborazionePDF se generazione va in errore?
               //FineElaborazionePDF(sAppoIDElaborazionePDF);

               returnValue = 1;
           }
           //Vedere se occorre la diversificazione dell'errore in caso di DataBaseException
           //catch (DataBaseException ex)
           //{
           //    throw ex;
           //}
           catch (Exception ex)
           {
               string message = ex.Message;
               message += "Cliente: " + _dataThread.CodiceFiscale + "; PB_Rete: " + _dataThread.Rete + _dataThread.Agente;
               // Marian Zaki: comment the throw exception.
               // throw new Exception(message);
               // Marian Zaki: Added
               ScriviErroreNelDB(-00001, "Errore nel Gestore PDF: " + message + getException(ex), -292929, "Gestore PDF", "Gestore PDF");
               string reportType;
               if (_dataThread.TipoReport == TipoReport.DIAGNOSI.ToString())
               {
                   reportType = "D";
               }
               else
               {
                   reportType = "M";
                   //Se l'errore � avvenuto in fase di creazione del Report di Monitoraggio,
                   //cancello pure il Diagnosi generato.
                   string saveToDisk = UtilityManager.getAppSetting("SavePDFtoDISK");
                   string sAppoNomeFile;
                   string sSuffissoDiagnosi = "_DP.pdf";
                   string targetFolder = UtilityManager.getAppSetting("SavePDFtoDISK_Folder");
                   switch (saveToDisk)
                   {
                       case "1":
                               // Report Campione stampato su file sistem
                               sAppoNomeFile = targetFolder + _dataThread.NomeFileReport + sSuffissoDiagnosi;
                               if (File.Exists(sAppoNomeFile))
                                  File.Delete(sAppoNomeFile);
                               break;
                       case "2":
                                // stampa report gestione trimestrale
                               sAppoNomeFile = targetFolder + _dataThread.NomeFileReport + sSuffissoDiagnosi;
                               if (File.Exists(sAppoNomeFile))
                                   File.Delete(sAppoNomeFile);
                               break;
                       default :
                           break;                    
                   }
            
                   //if ((UtilityManager.getAppSetting("SavePDFtoDISK") == "1") && (UtilityManager.getAppSetting("Periodico") == "1"))
                   //{
                   //     solo quando scrive sul File System
                   //    string sAppoNomeFile;
                   //    string sSuffissoDiagnosi = "_DP.pdf";
                   //    string targetFolder = UtilityManager.getAppSetting("SavePDFtoDISK_Folder");
                   //    sAppoNomeFile = targetFolder + _dataThread.NomeFileReport + sSuffissoDiagnosi;
                   //    if (File.Exists(sAppoNomeFile))
                   //    {
                   //        File.Delete(sAppoNomeFile);
                   //    }
                   //}
                   //++++++++++++++ Fine Modifica Atzeri Emanuele 8 feb 2012
               }
               InsertFaultCustomer(_dataThread.Rete, _dataThread.CodiceFiscale, reportType, ex.Message);
           }
           return returnValue;
        }

        private void MakePDF(List<SessionStruct> tabelleSessione, DataThread dataThread)
        {
            try
            { 
                PDFGenerator.PDFGenerator generator = new PDFGenerator.PDFGenerator(tabelleSessione, dataThread);
               
                 generator.Create();
                
                    

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static string InizioElaborazionePDF()
        {// metodo solo quando scrive sul File System

            if (!((UtilityManager.getAppSetting("SavePDFtoDISK") == "0") && (UtilityManager.getAppSetting("Periodico") == "0")))
            {
                //inserisco la data inizio elaborazione
                Int16 iIDGestore;
                iIDGestore = CodificaQueryContratti(ConfigurationManager.AppSettings["QueryContratti"]);

                List<Parametro> parametri = new List<Parametro>();
                Parametro p = new Parametro();

                p.ParameterName = "TipoDataScrittura";
                p.DbType = DbType.Boolean;
                p.Value = 0;
                parametri.Add(p);

                p = new Parametro();
                p.ParameterName = "IDGestore";
                p.DbType = DbType.Int16;
                p.Value = iIDGestore;
                parametri.Add(p);

                IDataReader reader = DataAccess.ExecuteDataReaderStoredProcedure(DBProvider.SqlServerStampeC6, ConfigurationManager.AppSettings["SP_GESTIONE_UPDATE_ELABORAZIONE_PDF"], parametri);
                reader.Read();

                return reader["IDElaborazionePDF"].ToString();
            }
            return string.Empty;
        }

        private static void FineElaborazionePDF(string IDElaborazionePDF)
        {// metodo solo quando scrive sul File System

            if (!((UtilityManager.getAppSetting("SavePDFtoDISK") == "0") && (UtilityManager.getAppSetting("Periodico") == "0")))
            {
                if (!string.IsNullOrEmpty(IDElaborazionePDF))
                {
                    List<Parametro> parametri = new List<Parametro>();
                    Parametro p = new Parametro();

                    p.ParameterName = "TipoDataScrittura";
                    p.DbType = DbType.Boolean;
                    p.Value = 1;
                    parametri.Add(p);

                    p = new Parametro();
                    p.ParameterName = "IDElaborazionePDF";
                    p.DbType = DbType.Int32;
                    p.Value = Convert.ToInt32(IDElaborazionePDF);
                    parametri.Add(p);

                    DataAccess.ExecuteScalarStoredProcedure(DBProvider.SqlServerStampeC6, ConfigurationManager.AppSettings["SP_GESTIONE_UPDATE_ELABORAZIONE_PDF"], parametri);
                }
            }
        }

        private static Int16 CodificaQueryContratti(string sQuery)
        {
            Int16 iAppo = 0;
            switch (sQuery)
            {
                case "GESTIONE_SELECT_PDF_GETDATATHREADS":
                    iAppo = 1;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_BIS":
                    iAppo = 2;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_TER":
                    iAppo = 3;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_QUATER":
                    iAppo = 4;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_QUINTO":
                    iAppo = 5;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_SESTO":
                    iAppo = 6;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_SETTIMO":
                    iAppo = 7;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_OTTAVO":
                    iAppo = 8;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_NONO":
                    iAppo = 9;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_DECIMO":
                    iAppo = 10;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_UNDICESIMO":
                    iAppo = 11;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_DODICESIMO":
                    iAppo = 12;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_TREDICESIMO":
                    iAppo = 13;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_QUATTORDICESIMO":
                    iAppo = 14;
                    break;
                case "GESTIONE_SELECT_PDF_GETDATATHREADS_QUINDICESIMO":
                    iAppo = 15;
                    break;
                default:
                    //test
                    iAppo = 0;
                    break;
            }
            return iAppo;
        }

        // Marian Zaki add those functions to handle insert the exceptions into the DB here for each customer and continue with others.
        #region Handle Exception

        private static void InsertFaultCustomer(string rete, string clientID, string reportType, string errorDescription)
        {
            int scriviErroreNelDB = int.Parse(ConfigurationManager.AppSettings["scriviErroreNelDB"]);
            if (scriviErroreNelDB == 1)
            {
                try
                {
                    List<Parametro> parametri = new List<Parametro>();
                    Parametro parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "rete";
                    parametro.Value = rete;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "cod_fiscale";
                    parametro.Value = clientID;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "tipoReport";
                    parametro.Value = reportType;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "errorText";
                    parametro.Value = errorDescription;
                    parametri.Add(parametro);



                    DataAccess.ExecuteNonQueryStoredProcedure(DBProvider.SqlServerStampeC6, "[C6MartPeriodico].[GESTIONE_INSERT_CUSTOMER_ERROR]", parametri);
                }
                catch (Exception ex)
                {
                    DataBaseException dataBaseException = (DataBaseException)ex;
                    Console.WriteLine(dataBaseException.Message);
                }
            }
        }
        
        private static string getDataBaseException(DataBaseException ecc)
        {
            const string aCapo = "#/n#";
            string ritorno = "";
            ritorno += aCapo;
            ritorno += "  Informazioni Comando SQL:" + aCapo;
            ritorno += "    sql file name: " + ecc.SqlFileName + aCapo;
            ritorno += "    connection string: " + ecc.ConnectionStringWithoutCredentials + aCapo;
            //ritorno += "    command text: " + ecc.CommandText + aCapo;
            //controllo se ci sono i parametri
            if (ecc.Parameters != null)
            {
                foreach (Parametro parametro in ecc.Parameters)
                {
                    ritorno += aCapo;
                    ritorno += "     parametro: " + parametro.ParameterName + aCapo;
                    ritorno += "     dimensione: " + parametro.Size.ToString() + aCapo;
                    ritorno += "     direzione: " + parametro.Direction.ToString() + aCapo;
                    ritorno += "     tipo: " + parametro.DbType.ToString() + aCapo;

                    if (parametro.Value == null)
                        ritorno += "     valore: null" + aCapo;
                    else
                    {
                        string valoreParametro = "";
                        if (parametro.Size > 500)
                        {
                            valoreParametro = "     valore: null(sono visualizzati solo i primi 500 bytes): " + parametro.Value.ToString().Substring(0, 500);
                        }
                        else
                        {
                            valoreParametro = "     valore: " + parametro.Value.ToString();
                        }
                        ritorno += valoreParametro + aCapo;
                    }
                }
            }
            ritorno += aCapo;
            ritorno += "    tipo: DataBaseException" + aCapo;
            ritorno += "    descrizione: " + ecc.Eccezione.Message + aCapo;
            ritorno += "    sorgente: " + ecc.Eccezione.Source + aCapo;
            ritorno += "    traccia: " + FormattaErrore(ecc.StackTrace) + aCapo;
            return ritorno;

        }

        private static string getException(Exception ecc)
        {
            const string aCapo = "#/n#";
            string ritorno = "";
            ritorno += aCapo;
            ritorno += "    tipo: " + ecc.GetType().ToString() + aCapo;
            ritorno += "    descrizione: " + ecc.Message + aCapo;
            ritorno += "    sorgente: " + ecc.Source + aCapo;
            if (ecc.InnerException != null)
            {
                ritorno += "    descrizione Inner: " + ecc.InnerException.Message + aCapo;
                ritorno += "    sorgente Inner: " + ecc.InnerException.Source + aCapo;
            }
            ritorno += "    traccia: " + FormattaErrore(ecc.StackTrace) + aCapo;
            return ritorno;

        }

        private static string FormattaErrore(string errore)
        {
            const string aCapo = "#/n#";
            const string spazio = "      ";
            string separatore1 = " at ";
            string separatore2 = " in ";
            string separatore3 = ":line ";
            string erroreInterno = errore.Replace(separatore1, "@");
            string ritorno = aCapo;


            //nome metodo e tutto il resto
            string[] messaggioErrore = erroreInterno.Split('@');
            string messaggioSenzaSpazi;
            string[] messaggioInterno;

            foreach (string messaggio in messaggioErrore)
            {
                messaggioSenzaSpazi = messaggio.Trim();

                if (messaggioSenzaSpazi != "")
                {
                    messaggioSenzaSpazi = messaggioSenzaSpazi.Replace(separatore2, "@");
                    messaggioInterno = messaggioSenzaSpazi.Split('@');
                    if (messaggioInterno.GetUpperBound(0) == 1)
                    {
                        ritorno += spazio + "metodo: " + messaggioInterno[0] + aCapo;
                        string fileLineaSingolo = messaggioInterno[1].Replace(separatore3, "@");
                        string[] fileLinea = fileLineaSingolo.Split('@');
                        ritorno += spazio + "percorsoFile: " + fileLinea[0] + aCapo;
                        ritorno += spazio + "linea: " + fileLinea[1] + aCapo;
                        ritorno += aCapo;
                    }
                    else
                    {
                        ritorno += spazio + "metodo: " + messaggioInterno[0] + aCapo;
                    }
                }
            }

            return ritorno;
        }

        private static void ScriviErroreNelDB(int codiceErrore, string descrizioErrore, int localeId, string nomePackage, string descrizionePackage)
        {
            int scriviErroreNelDB = int.Parse(ConfigurationManager.AppSettings["scriviErroreNelDB"]);
            if (scriviErroreNelDB == 1)
            {
                try
                {
                    List<Parametro> parametri = new List<Parametro>();
                    Parametro parametro = new Parametro();
                    parametro.DbType = DbType.Int32;
                    parametro.ParameterName = "codiceErrore";
                    parametro.Value = codiceErrore;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "descrizioErrore";
                    parametro.Value = descrizioErrore;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.DateTime;
                    parametro.ParameterName = "dataTime";
                    parametro.Value = DateTime.Now;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "localeID";
                    if (localeId == 0)
                        parametro.Value = System.DBNull.Value;
                    else
                        parametro.Value = localeId;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "descrizionePackage";
                    parametro.Value = descrizionePackage;
                    parametri.Add(parametro);

                    parametro = new Parametro();
                    parametro.DbType = DbType.String;
                    parametro.ParameterName = "nomePackage";
                    parametro.Value = nomePackage;
                    parametri.Add(parametro);

                    DataAccess.ExecuteNonQueryStoredProcedure(DBProvider.SqlServerStampeC6, "[C6Mart].[UT_INSERT_ERROR]", parametri);
                }
                catch (Exception ex)
                {
                    DataBaseException dataBaseException = (DataBaseException)ex;
                    Console.WriteLine(dataBaseException.Message);
                }
            }
        }

        /// <summary>
        ///  Marian Zaki: need to verify that it is needed with the Italian team. The reason of using it.
        /// </summary>
        /// <param name="ambiente"></param>
        /// <param name="cawTo_Bin"></param>
        /// <param name="argomentiCaw"></param>
        private static void StartTng(string ambiente, string cawTo_Bin, string argomentiCaw)
        {
            if (!ambiente.Equals("SVILUPPO"))
            {
                Process processTng = new Process();
                try
                {
                    processTng = Process.Start(cawTo_Bin, argomentiCaw);
                    while (!processTng.HasExited) ;
                }
                catch (Exception ex)
                {
                    throw new Exception("cawTo_Bin: Non riesco ad eseguire " + cawTo_Bin + " sulla macchina " + System.Environment.MachineName + ":" + ex.Message);
                }
                finally
                {
                    processTng.Close();
                    processTng.Dispose();
                }
            }
        }
        
        #endregion
    }
}