using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;
using System.Xml.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.Globalization;

namespace XMLExtractor
{
    public class Data
    {
        // Lists of objects, extracted from the XML
        public List<Chapter> chapterList { get; set; }
        public List<Section> sectionList { get; set; }
        public List<Paragraph> paragraphList { get; set; }
        public List<Page> pageList { get; set; }
        public List<Chart> chartList { get; set; }
        public List<ChartMediaDeiPrezzi> chartMediaDeiPrezziList { get; set; }
        public List<Image> imageList { get; set; }
        public List<TableCittaPrincipali> cityList { get; set; }
        public List<AspettativeValoriImmobili> aspettativeValoriImmobiliList { get; set; }
        public List<AspettativeVariazioneValore> aspettativeVariazioneValoreList { get; set; }
        public List<TableEvoluzione> tableEvoluzioneList { get; set; }
        public List<TableImposta> tableImpostaList { get; set; }


        /// <summary>
        /// Constructor.
        /// </summary>
        public Data() {
            this.chapterList = new List<Chapter>();
            this.sectionList = new List<Section>();
            this.paragraphList = new List<Paragraph>();
            this.pageList = new List<Page> ();
            this.chartList = new List<Chart>();
            this.chartMediaDeiPrezziList = new List<ChartMediaDeiPrezzi>();
            this.imageList = new List<Image>();
            this.cityList = new List<TableCittaPrincipali>();
            this.aspettativeValoriImmobiliList = new List<AspettativeValoriImmobili>();
            this.aspettativeVariazioneValoreList = new List<AspettativeVariazioneValore>();
            this.tableEvoluzioneList = new List<TableEvoluzione>();
            this.tableImpostaList = new List<TableImposta>();
        }

        /// <summary>
        /// SQL Table writer
        /// </summary>
        public void writeTables() {
            int ordinamento = 10;
            DBConnection connection = new DBConnection();
            List<TemplateStrutturaModelli> templateStrutturaModelliList = new List<TemplateStrutturaModelli>();
            List<TemplateStrutturaModelli> templateStrutturaModelliNucleoList = new List<TemplateStrutturaModelli>();
            using (SqlConnection sqlConnection = new SqlConnection(Utility.connectionString))
            {
                sqlConnection.Open();

                addSections();

                deleteEntries(sqlConnection);

                //  Scrolling section ordered by chapter id and then by section id
                foreach (Section sezione in (this.sectionList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<Section>()))
                {
                    TemplateStrutturaModelli templateStrutturaModelli = new TemplateStrutturaModelli();
                    templateStrutturaModelli.idReport = 11;
                    templateStrutturaModelli.idModello = 12;
                    templateStrutturaModelli.ordinamento = ordinamento;

                    //  Section, Chapter, Paragraph are created in the this order. For each section, chapter and paragraph are created.
                    sezione.writeDB(sqlConnection, this, templateStrutturaModelli);
                    templateStrutturaModelliList.Add(templateStrutturaModelli);
                    ordinamento += 10;
                }

                if (templateStrutturaModelliList != null)
                        writeTemplateStrutturaModelli(sqlConnection, templateStrutturaModelliList);

                addSchedeNucleo(sqlConnection, templateStrutturaModelliList);

                foreach (Section sezione in (this.sectionList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<Section>()))
                {
                    foreach (Page pagina in (this.pageList.Where(z => z.idCapitolo == sezione.idCapitolo && z.idSezione == sezione.idSezione).OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<Page>()))
                        pagina.writeDB(sqlConnection);
                    Utility.ID_SECTION++;
                }

                foreach (Paragraph paragraph in this.paragraphList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<Paragraph>())
                    paragraph.writeDB(sqlConnection);

                foreach (Image image in this.imageList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<Image>())
                    image.writeDB(sqlConnection);

                foreach (Chart chart in this.chartList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<Chart>())
                    chart.writeDB(sqlConnection);

                foreach (ChartMediaDeiPrezzi chart in this.chartMediaDeiPrezziList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<ChartMediaDeiPrezzi>())
                    chart.writeDB(sqlConnection);

                foreach (AspettativeValoriImmobili aspettativeValoriImmobili in this.aspettativeValoriImmobiliList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<AspettativeValoriImmobili>())
                    aspettativeValoriImmobili.writeDB(sqlConnection);

                foreach (AspettativeVariazioneValore aspettativeVariazioneValore in this.aspettativeVariazioneValoreList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<AspettativeVariazioneValore>())
                    aspettativeVariazioneValore.writeDB(sqlConnection);

                foreach (TableCittaPrincipali table in this.cityList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<TableCittaPrincipali>())
                    table.writeDB(sqlConnection);

                foreach (TableEvoluzione table in this.tableEvoluzioneList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<TableEvoluzione>())
                    table.writeDB(sqlConnection);

                foreach (TableImposta table in this.tableImpostaList.OrderBy(x => x.idCapitolo).ThenBy(x => x.idSezione).ToList<TableImposta>())
                    table.writeDB(sqlConnection);
            }
        }


        public void addSchedeNucleo(SqlConnection sqlConnection, List<TemplateStrutturaModelli> templateStrutturaModelliList)
        {
            Data dataNucleo = ReadXML.dataNucleo;
            int i = 0;
            foreach (Section section in dataNucleo.sectionList)
            {
                Chapter chapter = (Chapter)dataNucleo.chapterList.AsEnumerable().FirstOrDefault(x => x.idCapitolo == section.idCapitolo);
                templateStrutturaModelliList[i].idReport = 12;
                templateStrutturaModelliList[i].idModello = 13;
                
                var updInsCommand = new SqlCommand("INSERT into ClassiLayout (IdChiaveLayout, Classe, Namespace, Descrizione) VALUES (@idChiaveLayout, "
                + "@classe, @NameSpace, @Descrizione)", sqlConnection);
                updInsCommand.Parameters.AddWithValue("@IdChiaveLayout", Utility.CHIAVE_LAYOUT_SECTION + 3500);
                if (!chapter.titoloCapitolo.Contains("Indice"))
                {
                    updInsCommand.Parameters.AddWithValue("@classe", "S" + Utility.CHIAVE_LAYOUT_SECTION_NUCLEO);
                    updInsCommand.Parameters.AddWithValue("@NameSpace", "Consulenza.ReportWriter.Manager.Section.Immobiliare.MonitoraggioNucleo");
                    updInsCommand.Parameters.AddWithValue("@Descrizione", "S" + Utility.CHIAVE_LAYOUT_SECTION_NUCLEO + "." + chapter.titoloCapitolo + " - Nucleo Immobiliare Monitoraggio");
                }
                else 
                {
                    updInsCommand.Parameters.AddWithValue("@classe", "S" + chapter.idCapitolo);
                    updInsCommand.Parameters.AddWithValue("@NameSpace", "Consulenza.ReportWriter.Manager.Section.Immobiliare.MonitoraggioNucleo");
                    updInsCommand.Parameters.AddWithValue("@Descrizione", "S" + chapter.idCapitolo + "." + chapter.titoloCapitolo + " - Nucleo Immobiliare Monitoraggio");
                
                }
                int rowsUpdatedInserted = updInsCommand.ExecuteNonQuery();
                templateStrutturaModelliList[i].sezioneChiaveLayout = Utility.CHIAVE_LAYOUT_SECTION + 3500;

                updInsCommand = new SqlCommand("INSERT into ClassiLayout (IdChiaveLayout, Classe, Namespace, Descrizione) VALUES (@idChiaveLayout, "
                + "@classe, @NameSpace, @Descrizione)", sqlConnection);

                updInsCommand.Parameters.AddWithValue("@IdChiaveLayout", Utility.CHIAVE_LAYOUT_CHAPTER + 3000);
                if (!chapter.titoloCapitolo.Contains("Indice"))
                {
                    updInsCommand.Parameters.AddWithValue("@classe", "S" + Utility.CHIAVE_LAYOUT_CHAPTER_NUCLEO);
                    updInsCommand.Parameters.AddWithValue("@NameSpace", "Consulenza.ReportWriter.Manager.Chapter.Immobiliare.MonitoraggioNucleo");
                    updInsCommand.Parameters.AddWithValue("@Descrizione", "S" + Utility.CHIAVE_LAYOUT_CHAPTER_NUCLEO + "." + chapter.titoloCapitolo + " - Nucleo Immobiliare Monitoraggio");
                    templateStrutturaModelliList[i].capitoloChiaveLayout = Utility.CHIAVE_LAYOUT_CHAPTER + 3000;
                }
                else 
                {
                    updInsCommand.Parameters.AddWithValue("@classe", "S" + chapter.idCapitolo);
                    updInsCommand.Parameters.AddWithValue("@NameSpace", "Consulenza.ReportWriter.Manager.Chapter.Immobiliare.MonitoraggioNucleo");
                    updInsCommand.Parameters.AddWithValue("@Descrizione", "S" + chapter.idCapitolo + "." + chapter.titoloCapitolo + " - Nucleo Immobiliare Monitoraggio");
                    templateStrutturaModelliList[i].capitoloChiaveLayout = Utility.CHIAVE_LAYOUT_CHAPTER + 3000;
                }
                
                rowsUpdatedInserted = updInsCommand.ExecuteNonQuery();
                Utility.CHIAVE_LAYOUT_CHAPTER_NUCLEO++;
                Utility.CHIAVE_LAYOUT_SECTION_NUCLEO++;
                Utility.CHIAVE_LAYOUT_CHAPTER++;
                Utility.CHIAVE_LAYOUT_SECTION++;
                i++;
            }

            writeTemplateStrutturaModelli(sqlConnection, templateStrutturaModelliList);
        }

        /// <summary>
        /// It creates 'TemplateStrutturaModelli'  entries if they do not exist.
        /// </summary>
        public void writeTemplateStrutturaModelli(SqlConnection sqlConnection, List<TemplateStrutturaModelli> templateStrutturaModelliList)
        {
            List<REP_IMM_MON_Template> _REP_IMM_MON_Template = new List<REP_IMM_MON_Template>();
            foreach(TemplateStrutturaModelli templateStrutturaModelli in templateStrutturaModelliList) {
                templateStrutturaModelli.writeDB(sqlConnection);
                _REP_IMM_MON_Template.Add(new REP_IMM_MON_Template(Utility.ID_REP_IMM_MON_TEMPLATE, Utility.TEMPLATE_STRUTTURA_MODELLO, 1, ""));
                Utility.TEMPLATE_STRUTTURA_MODELLO++;
            }

            foreach (REP_IMM_MON_Template template in _REP_IMM_MON_Template)
                template.writeDB(sqlConnection);
        }

        /// <summary>
        /// It creates 'Report' type if it does not exist.
        /// </summary>
        public void writeReport(SqlConnection sqlConnection)
        {
            int idReport = 11;
            SqlCommand cmdCount = new SqlCommand ("SELECT ID FROM Report WHERE ID="+idReport, sqlConnection);
            // ID Report = 11 => 'Immobiliare Monitoraggio'
            if (Convert.ToInt32(cmdCount.ExecuteScalar()) != idReport)
            {
                cmdCount = new SqlCommand("INSERT into Report (ID, Nome, Descrizione) " +
                    "VALUES (" + idReport + ", 'Monitoraggio Immobiliare', 'Report di monitoraggio del Patrimonio Immobiliare')", sqlConnection);
                int rowsUpdatedInserted = cmdCount.ExecuteNonQuery();
            }
        }

        /// <summary>
        /// It creates 'Modello' type if it does not exist.
        /// </summary>
        public void writeModelli(SqlConnection sqlConnection)
        {
            int idModello = 12;
            SqlCommand cmdCount = new SqlCommand ("SELECT ID FROM Modelli WHERE ID="+idModello, sqlConnection);
            // ID Modelli = 12 => 'Immobiliare Monitoraggio'
            if (Convert.ToInt32(cmdCount.ExecuteScalar()) != idModello)
            {
                cmdCount = new SqlCommand("INSERT into Modelli (ID, Nome, Descrizione) " +
                    "VALUES (" + idModello + ", 'Monitoraggio Immobiliare', 'Modello per report di monitoraggio del Patrimonio Immobiliare')", sqlConnection);
                int rowsUpdatedInserted = cmdCount.ExecuteNonQuery();
            }
        }

        /// <summary>
        /// It adds sections who does not belong to the XML.
        /// </summary>
        public void addSections() 
        {
            aggiungiCopertina();
            aggiungiIndice();
            aggiungiGlossario();
        }

        /// <summary>
        /// It adds Copertina.
        /// </summary>
        public void aggiungiCopertina() {
            
            //  Add Copertina section
            List<Section> newSectionList = new List<Section>();
            Section copertinaSection = new Section();
            copertinaSection.id = "Copertina";
            copertinaSection.idCapitolo = 1;
            copertinaSection.idSezione = 1;
            newSectionList.Add(copertinaSection);
            newSectionList.AddRange(this.sectionList);
            this.sectionList = newSectionList;

            //  Add Copertina Chapter
            List<Chapter> newChapterList = new List<Chapter>();
            Chapter copertinaChapter = new Chapter();
            copertinaChapter.id = "Copertina";
            copertinaChapter.idCapitolo = 1;
            copertinaChapter.titoloCapitolo = "Copertina";
            newChapterList.Add(copertinaChapter);
            newChapterList.AddRange(this.chapterList);
            this.chapterList = newChapterList;

            //  Add Copertina Page
            List<Page> newPageList = new List<Page>();
            Page copertinaPage = new Page();
            copertinaPage.idPagina = 1;
            copertinaPage.idSezione = 1;
            copertinaPage.idCapitolo = 1;
            copertinaPage.titoloPagina = "Copertina";
            newPageList.Add(copertinaPage);
            newPageList.AddRange(this.pageList);
            this.pageList = newPageList;
        }

        /// <summary>
        /// It adds Glossario.
        /// </summary>
        public void aggiungiGlossario()
        {
            //  Add Glossario section
            Section copertinaSection = new Section();
            copertinaSection.id = "Glossario";
            copertinaSection.idCapitolo = ReadXML.idCapitolo;
            copertinaSection.idSezione = 1;
            this.sectionList.Add(copertinaSection);

            //  Add Glossario Chapter
            Chapter copertinaChapter = new Chapter();
            copertinaChapter.id = "Glossario";
            copertinaChapter.idCapitolo = ReadXML.idCapitolo;
            copertinaChapter.titoloCapitolo = "Glossario";
            this.chapterList.Add(copertinaChapter);

            //  Add Glossario Page
            Page copertinaPage = new Page();
            copertinaPage.idPagina = ReadXML.idPagina;
            copertinaPage.idSezione = 1;
            copertinaPage.idCapitolo = ReadXML.idCapitolo;
            copertinaPage.titoloPagina = "Glossario";
            this.pageList.Add(copertinaPage);

            ReadXML.idCapitolo++;
            ReadXML.idPagina++;

            //  Add Indice section
            copertinaSection = new Section();
            copertinaSection.id = "Indice Fiscalità";
            copertinaSection.idCapitolo = 23;
            copertinaSection.idSezione = 2;
            this.sectionList.Add(copertinaSection);

            //  Add Indice Chapter
            copertinaChapter = new Chapter();
            copertinaChapter.id = "Indice Fiscalità";
            copertinaChapter.idCapitolo = 23;
            copertinaChapter.titoloCapitolo = "Indice";
            this.chapterList.Add(copertinaChapter);

            //  Add Indice Page
            copertinaPage = new Page();
            copertinaPage.idPagina = ReadXML.idPagina;
            copertinaPage.idSezione = 2;
            copertinaPage.idCapitolo = 23;
            copertinaPage.titoloPagina = "Indice";
            this.pageList.Add(copertinaPage);

            ReadXML.idCapitolo++;
            ReadXML.idPagina++;

            //  Add Indice section
            copertinaSection = new Section();
            copertinaSection.id = "Indice Glossario";
            copertinaSection.idCapitolo = 24;
            copertinaSection.idSezione = 2;
            this.sectionList.Add(copertinaSection);

            //  Add Indice Chapter
            copertinaChapter = new Chapter();
            copertinaChapter.id = "Indice Glossario";
            copertinaChapter.idCapitolo = 24;
            copertinaChapter.titoloCapitolo = "Indice";
            this.chapterList.Add(copertinaChapter);

            //  Add Indice Page
            copertinaPage = new Page();
            copertinaPage.idPagina = ReadXML.idPagina;
            copertinaPage.idSezione = 2;
            copertinaPage.idCapitolo = 24;
            copertinaPage.titoloPagina = "Indice";
            this.pageList.Add(copertinaPage);
        }

        /// <summary>
        /// It adds Indice.
        /// </summary>
        public void aggiungiIndice()
        {
            //  Add Indice section
            Section copertinaSection = new Section();
            copertinaSection.id = "Indice";
            copertinaSection.idCapitolo = 2;
            copertinaSection.idSezione = 1;
            this.sectionList.Add(copertinaSection);

            //  Add Indice Chapter
            Chapter copertinaChapter = new Chapter();
            copertinaChapter.id = "Indice";
            copertinaChapter.idCapitolo = 2;
            copertinaChapter.titoloCapitolo = "Indice";
            this.chapterList.Add(copertinaChapter);

            //  Add Indice Page
            Page copertinaPage = new Page();
            copertinaPage.idPagina = 2;
            copertinaPage.idSezione = 1;
            copertinaPage.idCapitolo = 2;
            copertinaPage.titoloPagina = "Indice";
            this.pageList.Add(copertinaPage);
        }

        /// <summary>
        /// It deletes all data in the DB.
        /// </summary>
        public void deleteEntries(SqlConnection sqlConnection)
        {
            var deleteCount = new SqlCommand(Utility.DELETE_DB, sqlConnection);
            try
            {
                int rowsUpdatedInserted = deleteCount.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                //TO-DO LOG
            }
        }
    }
}
