using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.IO;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Collections;
using System.Net;
using System.Globalization;
using ICSharpCode.SharpZipLib.Zip;

namespace SmartFTPThread
{

    struct QueryGestioneInsertZip
    {
        public int IdZip;
        public string nomeFile;
        public string nomeCartella;
    }

    public class Program
    {
       


        static int Main(string[] args)
        {

            //elimino il proxy
            IWebProxy proxy = WebRequest.GetSystemWebProxy();
            WebRequest.DefaultWebProxy = null;

            try
            {
                
                Console.WriteLine("INIZIO WHITELIST");
             
                IDataReader rpts = DataAccess.ExecuteDataReaderStoredProcedure(DBProvider.SqlServerStampeC6, ConfigurationManager.AppSettings["SP_GESTIONE_SELECT_ZIP_WHITELIST"], null);

                string tipoInvio = ConfigurationManager.AppSettings["TIPO_INVIO"];

                string _path = (tipoInvio.ToUpper() == "G") ? ConfigurationManager.AppSettings["pathIDX"] : ConfigurationManager.AppSettings["pathIDX_PERIODICO"];
                
                while (rpts.Read())
                {
                    int lotto = Convert.ToInt32(rpts["lotto"]);
                    string nomeFile = rpts["nomeFile"].ToString();
                    Console.WriteLine("Lotto n: "+lotto.ToString() + " Processamento id: " + rpts["IdZip"].ToString());
                    creaFileFlussoDiAccompagnamentoFTP(_path, int.Parse(rpts["IdZip"].ToString()),lotto,nomeFile);                                                         
                }

                SendFTP(_path);
                
                Console.WriteLine("FINE White List");

                return 0;
            }
            catch (DataBaseException ex)
            {
                try
                {
                  
                    ScriviErroreNelDB(-292929, "Errore nel Gestore FTP: " + getDataBaseException(ex), -292929, "Gestore FTP", "Gestore FTP");  
                }
                catch
                {
                }

                //argomentiCawToErrore += funzione + " terminata con ERRORE";
                //StartTng(ambiente, cawTo_Bin, argomentiCawToErrore);
                return 1;
            }
            catch (Exception ex)
            {
                try
                {
                    
                    ScriviErroreNelDB(-292929, "Errore nel Gestore FTP: " + getException(ex), -292929, "Gestore FTP", "Gestore FTP");
                 
                }
                catch
                {
                }

                //argomentiCawToErrore += funzione + " terminata con ERRORE";
                //StartTng(ambiente, cawTo_Bin, argomentiCawToErrore);
                return 1;
            }
            finally
            {
                //rimetto il proxy
                WebRequest.DefaultWebProxy = proxy;
            }

        }

       


        private static void CreateDir(string pathDir)
        {
            if (!Directory.Exists(pathDir))
                Directory.CreateDirectory(pathDir);
        }

        //To be removed
        /*
        private static void SendFTP(string nomeCartella, string nomeFile, int id)
        {
            short FTP = Convert.ToInt16(ConfigurationManager.AppSettings["FTP"]);
            if (FTP == 1)
                SendZipToSelecta(nomeCartella, nomeFile, id);
            else
                CopiaInLocale(id, nomeCartella, nomeFile);
        }
        */

        private static void SendFTP(string nomeCartella)
        {
            short FTP = Convert.ToInt16(ConfigurationManager.AppSettings["FTP"]);
            if (FTP == 1)
            {
                CopiaInLocale(nomeCartella);
                SendIDXToSelecta(nomeCartella);
            }
            else
                CopiaInLocale(nomeCartella);
        }


        private static void CopiaInLocale(string nomeCartella)
        {
            string tipoInvio = ConfigurationManager.AppSettings["TIPO_INVIO"];
            string inputPath = (tipoInvio.ToUpper() == "G") ? ConfigurationManager.AppSettings["pathIDX"] : ConfigurationManager.AppSettings["pathIDX_PERIODICO"];
            string outputPath = (tipoInvio.ToUpper() == "G") ? ConfigurationManager.AppSettings["path_OUTPUT_IDX"] : ConfigurationManager.AppSettings["path_OUTPUT_IDX_PERIODICO"];
            if (!Directory.Exists(outputPath))
                Directory.CreateDirectory(outputPath);
            //if (!fileName.ToLower().Contains(".idx"))
            //    fileName += ".idx";
            string[] files = Directory.GetFiles(inputPath);
            string temp;
            foreach (string file in files)
            {
                temp = file.Replace(inputPath, outputPath);
                File.Copy(file, temp, true);
            }
            
        }

       
        private static void SendIDXToSelecta(string path)
        {
            Console.WriteLine("Invio dei file generati via FTP al server -->" + ConfigurationManager.AppSettings["FTPServer"].ToString());
            string tipoInvio = ConfigurationManager.AppSettings["TIPO_INVIO"];

            string[] files = Directory.GetFiles(path);

            foreach (string file in files)
            {

                byte[] flussoInByte = File.ReadAllBytes(file);

                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ConfigurationManager.AppSettings["FTPServer"] + file);
                request.Method = WebRequestMethods.Ftp.UploadFile;
                request.ContentLength = flussoInByte.Length;
                request.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["FTPUser"], ConfigurationManager.AppSettings["FTPPassword"]);
                byte[] buffer = new byte[4096];
                using (Stream writer = request.GetRequestStream())
                using (MemoryStream ms = new MemoryStream(flussoInByte))
                {
                    int bytesRead = 0;
                    int totalBytes = 0;

                    do
                    {
                        bytesRead = ms.Read(buffer, 0, buffer.Length);
                        if (bytesRead > 0)
                        {
                            writer.Write(buffer, 0, bytesRead);
                            totalBytes += bytesRead;
                        }
                    } while (bytesRead > 0);

                    //Directory.Delete(path, true);
                }

                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                Console.WriteLine("Files inviati con response: " + response.ToString());
                response.Close();
            }

        }


        private static void creaFileFlussoDiAccompagnamentoFTP(string path, int IdZip, int lotto,string nomeFile)
        {
            //Singolo FTP del FLUSSO Di Accompagnamento
            DateTime dataFlusso = DateTime.Now;
            string temp;
            if (IdZip < 10)
                temp = "0" + IdZip.ToString();
            else
                temp = IdZip.ToString();
            
            string nomeFileFlusso = nomeFile + "_" + "LOTTO_" + lotto.ToString() + "_PACK_" + temp + ".";
           
            nomeFileFlusso += ConfigurationManager.AppSettings["EstensioneFile"];

            List<Parametro> parametri = new List<Parametro>();
            Parametro parametro = new Parametro();
            parametro.DbType = DbType.Int32;
            parametro.ParameterName = "IdZip";
            parametro.Value = IdZip;
            parametri.Add(parametro);

            SqlDataReader filesWhiteList = (SqlDataReader)DataAccess.ExecuteDataReaderStoredProcedure(DBProvider.SqlServerStampeC6, ConfigurationManager.AppSettings["SP_GESTIONE_SELECT_FTP_WHITELIST"], parametri);
            //V if all customer are excluded from whitelist the whitelist file must be empty
            //if (filesWhiteList.HasRows)
            //{
                StringBuilder flussoAccompagnamento = new StringBuilder();
                while (filesWhiteList.Read())
                {

                    flussoAccompagnamento.Append(filesWhiteList["riga"].ToString() + "\r\n");
                }

                File.WriteAllText(path + "\\" + nomeFileFlusso, flussoAccompagnamento.ToString());

            //}
        }
       
        private static byte[] StrToByteArray(string str)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            return encoding.GetBytes(str);
        }

        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);
                //}
            }
        }
        
  
    }
}