using System;
using Consulenza.ReportWriter.Business.OBJ_PDF;
using Consulenza.ReportWriter.Business;
using ceTe.DynamicPDF;
using System.Data;
using System.Linq;
using Consulenza.ReportCommon;
using System.Collections.Generic;
using Consulenza.ReportWriter.Business.Entity;

namespace Consulenza.ReportWriter.Manager.Section.Immobiliare.MappaturaPreliminare
{
    /// <summary>
    /// Dettaglio fabbricati (id 132)
    /// </summary>
    public class S3 : Entity.Section
    {
        public S3(EnvironmentFacade environmentFacade, int idSection)
            : base(environmentFacade, idSection)
        {
            try
            {
                Draw();
            }
            catch (Exception ex)
            {
                SectionLogger.Write("S3", ex.Message, SectionLoggerMessageLevel.E, EnvironmentFacade.ReportEnvironment);
            }
        }

        /// <summary>
        /// Scheda3. Dettaglio fabbricati (elenco dei fabbricati e dei principali dati catastali, quote e valore stimato del cliente e dei cointestatari)
        /// </summary>
        protected override sealed void Draw()
        {
            var dati = GetDataSet();

            if (dati == null || dati.Tables[0].Rows.Count == 0) return;

            var testi = GetText();

            // Immobili con anomalie catastali       
            var immobiliConAnomalieCatastali = dati.Tables["Dati"].AsEnumerable().Where(r => r.Field<bool>("AnomaliaCatastale"));

            // Immobili selezionati dall'utente          
            var immobiliSelezionati = dati.Tables["Dati"].AsEnumerable().Where(r => EnvironmentFacade.ReportEnvironment.MappaturaPreliminare.IdImmobileCatasto.Contains(r.Field<string>("IdImmobileCatasto")));

            // Immobili non a catasto
            var immobiliNonACatasto = dati.Tables["Dati"].AsEnumerable().Where(r => r.Field<bool>("Catasto") == false);


            #region Recupero il numero massimo di colonne di tipo immagine da aggiungere

            var numeroColonneImmagine = 0;

            var listaCompletaIndici = new List<Int32>();
            listaCompletaIndici.AddRange(immobiliConAnomalieCatastali.Select(o => o.Field<Int32>("Indice")));
            listaCompletaIndici.AddRange(immobiliSelezionati.Select(o => o.Field<Int32>("Indice")));
            listaCompletaIndici.AddRange(immobiliNonACatasto.Select(o => o.Field<Int32>("Indice")));
           
            if (listaCompletaIndici.Any())
            {
                numeroColonneImmagine = (from indice in listaCompletaIndici
                                         group indice by indice into grouping
                                         select new
                                         {
                                             Key = grouping.Key,
                                             Count = grouping.Count()
                                         }).Max(x => x.Count);
            }

            #endregion

            var icona = new ImagePDF(EnvironmentFacade.RendererFacade.XLeftLimit, 0.20F, "Fabbricati.png") { AutoIncrementYWritable = false };
            var titolo = new FormattedTextAreaPDF(testi.Rows[0]["testo1"].ToString(), 82, 600) { FontSize = 10, FontColor = ColorPDF.Immobiliare_Grigio_TestoStandard, DeltaY = 5 };

            #region Tabella

            var tabella = new TablePDF(EnvironmentFacade.RendererFacade.XLeftLimit, dati.Tables["Dati"])
            {
                Style = Style.Immobiliare,
                RowsPadding = 3,
                Footer = false,
                HeaderHeight = 130,
                MinimumRowHeight = 12,
                ShowBorderLastLine = true
            };

            #region definizione larghezza colonne

            const int larghezzaTabella = 755; // massima larghezza tabella
            var larghezzaImmagine = immobiliConAnomalieCatastali.Any() || immobiliSelezionati.Any() || immobiliNonACatasto.Any() ? 17 : 0;
            const int larghezzaSingoloCliente = 65;
            const int larghezzaCategoriaCatastale = 22;
            const int larghezzaSuperficieStimata = 25;
            const int larghezzaRenditaCatastale = 50;
           

            //La colonna descrizione è l'unica variabile.
            var larghezzaDescrizione = larghezzaTabella - larghezzaImmagine - larghezzaCategoriaCatastale - larghezzaSuperficieStimata - larghezzaRenditaCatastale   - (larghezzaSingoloCliente * dati.Tables[1].Rows.Count);

            // Colonne di tipo Immagine
            for (int i = 1; i <= numeroColonneImmagine; i++)
            {
                larghezzaDescrizione -= larghezzaImmagine;
                tabella.Columns.Add(new ColumnPDF(string.Format("immagine{0}", i), larghezzaImmagine, HorizontalAlignmentType.Sinistra, false, false, 7, ColumnType.Immagine, string.Empty, string.Empty) { ScaleColumnTypeImage = 0.1F });
            }

            #endregion

            #region colonne

            tabella.Columns.Add(new ColumnPDF("descrizione", larghezzaDescrizione, HorizontalAlignmentType.Sinistra, false, false, 7, ColumnType.Testo, "Descrizione", "Descrizione") { HeaderVerticalAlignment = VerticalAlignmentType.Basso, HeaderFontBold = true, PaddingLeft = 5 });
            tabella.Columns.Add(new ColumnPDF("categoriacatastale", larghezzaCategoriaCatastale, HorizontalAlignmentType.Centrato, false, false, 7, ColumnType.Testo, "CategoriaCatastale", "Categoria catastale") { HeaderTextVerticalDirection = true, HeaderFontBold = false });
            tabella.Columns.Add(new ColumnPDF("superficiestimata", larghezzaSuperficieStimata, HorizontalAlignmentType.Centrato, false, false, 7, ColumnType.Testo, "SuperficieStimataStringa", "Superficie stimata (mq)") { HeaderTextVerticalDirection = true, HeaderFontBold = false });
            tabella.Columns.Add(new ColumnPDF("renditacatastale", larghezzaRenditaCatastale, HorizontalAlignmentType.Destra, false, false, 7, ColumnType.Testo, "RenditaCatastaleStringa", "Rendita catastale") { HeaderTextVerticalDirection = true, HeaderFontBold = false, PaddingRight = 5 });


            var iColonna = 2;
            foreach (DataRow cliente in dati.Tables["Clienti"].Rows)
            {
                var iCliente = Convert.ToInt32(cliente["PosizioneCliente"]);
                var campoStringa = string.Format("Cliente{0}Stringa", iCliente);

                tabella.Columns.Add(new ColumnPDF(campoStringa, larghezzaSingoloCliente, HorizontalAlignmentType.Destra, false, false, 7, ColumnType.Testo, campoStringa, cliente["Cliente"].ToString())
                {
                    HeaderVerticalAlignment = VerticalAlignmentType.Basso,
                    HeaderTextVerticalDirection = true,
                    HeaderBackgroundColor = iColonna == 2 ? ColorPDF.Immobiliare_Marrone : null,
                    HeaderFontColor = iColonna == 2 ? ColorPDF.Bianco : null,
                    HeaderFontBold = iColonna == 2,
                    BackgroundColor = iColonna == 2 ? ColorPDF.Immobiliare_Marrone : null,
                    FontColor = iColonna == 2 ? ColorPDF.Bianco : null,
                    FontBold = iColonna == 2,
                    HeaderPaddingLeft =0//iColonna == 2 ? -5 : 0
                });

                // verifico se il cliente ha solo fabbricati in usufrutto
                var clienteSoloUsufrutto = dati.Tables["Dati"]
                    .AsEnumerable()
                    .Select(r => r.Field<decimal>(string.Format("Cliente{0}", iCliente)))
                    .Distinct().Sum().Equals(-100);
                //var totalePerCliente = clienteSoloUsufrutto ? 0 : Convert.ToDecimal(dati.Tables["Dati"].Compute(string.Format("{0}{1}{2}", "SUM(Cliente", iCliente, ")"), string.Format("Cliente{0} <> -100", iCliente))); // escludo i -100 dal computo del totale
                //tabella.FooterCell[iColonna].Value = totalePerCliente.Equals(0) || totalePerCliente.Equals(-100) ? "-" : totalePerCliente.ToString(); //-100 = usufrutto 

                iColonna++;
            }

            #endregion

            #region immagini e border nelle colonne di tipo immagine

            // Da specifica le immagini devo essere disegnate sempre nella colonna più vicina possibile al testo (in modo da ottenere allineamento a destra)

            int indiceColonna = -1;

            #region Immobili con anomalia catastale
            // Immagine per immobile con anomalie catastali
            foreach (var item in immobiliConAnomalieCatastali)
            {
                int indiceRiga = Convert.ToInt32(item["indice"]);

                for (int i = numeroColonneImmagine - 1; i >= 0; i--)
                {
                    if (string.IsNullOrEmpty(tabella.Cells[i, indiceRiga].Value))
                    {
                        indiceColonna = i;
                        break;
                    }
                }

                tabella.Row[indiceRiga].FontColor = new ColorPDF(205, 0, 6); // Rosso     
                tabella.Row[indiceRiga].ForceStyleFontColor = true;
                tabella.Cells[indiceColonna, indiceRiga].Value = "warning.png";
            }
            #endregion

            #region Immobili non a catasto
            // Immagine per immobile non a catasto
            foreach (var item in immobiliNonACatasto)
            {
                int indiceRiga = Convert.ToInt32(item["indice"]);

                for (int i = numeroColonneImmagine - 1; i >= 0; i--)
                {
                    if (string.IsNullOrEmpty(tabella.Cells[i, indiceRiga].Value))
                    {
                        indiceColonna = i;
                        break;
                    }
                }

                tabella.Cells[indiceColonna, indiceRiga].Value = "info.png";
            }
            #endregion

            #endregion

            #region note della tabella

            var campiAsterisco = new[] { "Cliente1Stringa", "Cliente2Stringa", "Cliente3Stringa", "Cliente4Stringa", "Cliente5Stringa" }; // campi del datasource su cui aggiungere gli asterischi.
            var campiCondizione = new[] { "Cliente1StringaAsterischi", "Cliente2StringaAsterischi", "Cliente3StringaAsterischi", "Cliente4StringaAsterischi", "Cliente5StringaAsterischi" };

            var condizioneNota1 = string.Empty;
            var condizioneNota2 = string.Empty;
            var condizioneNota3 = string.Empty;
            var condizioneNota4 = string.Empty;//più diritti di proprietà. non esce da db ma con il 3 datatable una lista di idimmobili e posizionecliente corrispondenti alle colonne con più diritti.
            //var condizioneNota5 = string.Empty;

            const int condizioneNota1Valore = 1;
            const int condizioneNota2Valore = 2;
            const int condizioneNota3Valore = 9;
            
            const int condizioneNota4Valore = 88;
           // const int condizioneNota5Valore = 89;

            for (int j = 0; j < campiCondizione.Length; j++)
            {
                if (j != campiCondizione.Length - 1)
                {
                    condizioneNota1 += string.Format("{0}={1} OR ", campiCondizione[j], condizioneNota1Valore);
                    condizioneNota2 += string.Format("{0}={1} OR ", campiCondizione[j], condizioneNota2Valore);
                    condizioneNota3 += string.Format("{0}={1} OR ", campiCondizione[j], condizioneNota3Valore);
                    condizioneNota4 += string.Format("{0}={1} OR ", campiCondizione[j], condizioneNota4Valore);
                    //condizioneNota5 += string.Format("{0}={1} OR ", campiCondizione[j], condizioneNota5Valore);
                }
                else
                {
                    condizioneNota1 += string.Format("{0}={1}", campiCondizione[j], condizioneNota1Valore);
                    condizioneNota2 += string.Format("{0}={1}", campiCondizione[j], condizioneNota2Valore);
                    condizioneNota3 += string.Format("{0}={1}", campiCondizione[j], condizioneNota3Valore);
                    condizioneNota4 += string.Format("{0}={1}", campiCondizione[j], condizioneNota4Valore);
                    //condizioneNota5 += string.Format("{0}={1}", campiCondizione[j], condizioneNota5Valore);
                }
            }

            // Determino quale nota aggiungere
            var notaNudaProprieta = dati.Tables["Dati"].Select(condizioneNota1).Any();
            var notaDirittoProprieta = dati.Tables["Dati"].Select(condizioneNota2).Any();
            var notaDirittoProprietaAltri = dati.Tables["Dati"].Select(condizioneNota3).Any();

            var notaPiuDiritti = dati.Tables["Dati"].Select(condizioneNota4).Any();
           // var notaPiuDirittiAltri = dati.Tables["Dati"].Select(condizioneNota5).Any();
            // Nota nuda proprietà
            if (notaNudaProprieta)
            {
                tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo2"].ToString(), campiAsterisco, condizioneNota1, TableNotePDF.TableNoteAsteriskPositionType.CorpoTabella)
                {
                    FontSize = 7,
                    MappingType = TableNotePDF.TableNoteMappingType.Dinamico,
                    MappingKey = "Indice",
                    ConditionFields = campiCondizione,
                    ConditionValue = condizioneNota1Valore
                });
            }

            // Nota diritto proprietà
            if (notaDirittoProprieta)
            {
                tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo3"].ToString(), campiAsterisco, condizioneNota2, TableNotePDF.TableNoteAsteriskPositionType.CorpoTabella)
                {
                    FontSize = 7,
                    MappingType = TableNotePDF.TableNoteMappingType.Dinamico,
                    MappingKey = "Indice",
                    ConditionFields = campiCondizione,
                    ConditionValue = condizioneNota2Valore
                });
            }
            // Nota  diritto proprietà qualora differente da proprietà, usufrutto, nuda proprietà, proprietà per area e superficie.
            if (notaDirittoProprietaAltri)
            {
                tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo7"].ToString(), campiAsterisco, condizioneNota3, TableNotePDF.TableNoteAsteriskPositionType.CorpoTabella)
                {
                    FontSize = 7,
                    MappingType = TableNotePDF.TableNoteMappingType.Dinamico,
                    MappingKey = "Indice",
                    ConditionFields = campiCondizione,
                    ConditionValue = condizioneNota3Valore
                });
            }
            // Nota piu' diritti
            if (notaPiuDiritti)
            {
                tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo8"].ToString(), campiAsterisco, condizioneNota4, TableNotePDF.TableNoteAsteriskPositionType.CorpoTabella)
                {
                    FontSize = 7,
                    MappingType = TableNotePDF.TableNoteMappingType.Dinamico,
                    MappingKey = "Indice",
                    ConditionFields = campiCondizione,
                    ConditionValue = condizioneNota4Valore
                });
            }
            //// Nota piu' diritti Altri
            //if (notaPiuDirittiAltri)
            //{
            //    tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo8"].ToString(), campiAsterisco, condizioneNota5, TableNotePDF.TableNoteAsteriskPositionType.CorpoTabella)
            //    {
            //        FontSize = 7,
            //        MappingType = TableNotePDF.TableNoteMappingType.Dinamico,
            //        MappingKey = "Indice",
            //        ConditionFields = campiCondizione,
            //        ConditionValue = condizioneNota5Valore
            //    });
            //}
            // Nota immagine 1
            if (immobiliConAnomalieCatastali.Any())
                tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo4"].ToString()) { FontSize = 7, DeltaY = 3, Image = new ImagePDF(EnvironmentFacade.RendererFacade.XLeftLimit, 0.1F, "warning.png") });
          
            // Nota immagine 3
            if (immobiliNonACatasto.Any())
                tabella.Notes.Add(new TableNotePDF(TableNotePDF.TableNotePositionType.PièDiTabella, testi.Rows[0]["testo6"].ToString()) { FontSize = 7, DeltaY = 3, Image = new ImagePDF(EnvironmentFacade.RendererFacade.XLeftLimit, 0.1F, "info.png") });


            #endregion

            #endregion

            #region Oggetti da ripetere al salto pagina della tabella

            var listaOggettiDaRipetere = new List<ObjectPDF> { new SpacePDF(40), icona, titolo, new SpacePDF(20) };
            AddElement(new RepeaterPDF(listaOggettiDaRipetere));

            #endregion

            AddElement(new SpacePDF(40));
            AddElement(icona);
            AddElement(titolo);
            AddElement(new SpacePDF(20));
            AddElement(tabella);
        }

        /// <summary>
        /// Recupera i dati necessari alla Section restituendo un DataTable.
        /// </summary>
        /// <returns></returns>
        protected sealed override DataTable GetDataTable()
        {
            return null;
        }

        /// <summary>
        /// Recupera i dati necessari alla Section restituendo un DataSet.
        /// </summary>
        /// <returns></returns>
        protected sealed override DataSet GetDataSet()
        {

            #region Definizione dei parametri

            var parametri = new List<Parametro>
            {
                new Parametro
                {
                    Direction = ParameterDirection.Input,
                    DbType = DbType.Int64,
                    ParameterName = "ChiaveClientePB",
                    Value = EnvironmentFacade.ReportEnvironment.Cliente.Chiave
                }
            };

            #endregion

            var dsOriginal = EnvironmentFacade.ReportEnvironment.MappaturaPreliminare.ImmobiliareCEUnica ? DataAccess.ExecuteDataSetStoredProcedure(DBProvider.SqlServerConsulenzaUnica, "REP_MappaturaPreliminare_S3_DettaglioFabbricati", parametri)
                : DataAccess.ExecuteDataSetStoredProcedure(DBProvider.SqlServerConsulenzaEvoluta, "REP_MappaturaPreliminare_S3_DettaglioFabbricati", parametri);
            if (dsOriginal.Tables[0].Rows.Count == 0)
                return null;

            var dt1 = dsOriginal.Tables[0].Copy();
            dt1.TableName = "Dati";

            // Colonne aggiuntive per formattazione in stringa
            dt1.Columns.Add("Indice", typeof(int));
            dt1.Columns.Add("SuperficieStimataStringa", typeof(string));
            dt1.Columns.Add("RenditaCatastaleStringa", typeof(string));
            dt1.Columns.Add("Cliente1Stringa", typeof(string));
            dt1.Columns.Add("Cliente2Stringa", typeof(string));
            dt1.Columns.Add("Cliente3Stringa", typeof(string));
            dt1.Columns.Add("Cliente4Stringa", typeof(string));
            dt1.Columns.Add("Cliente5Stringa", typeof(string));

            foreach (DataRow item in dt1.Rows)
            {
                item["SuperficieStimataStringa"] = Convert.ToInt32(item["SuperficieStimata"]) == 0 ? "n.d." : Helper.FormatInteger(item["SuperficieStimata"].ToString());
                item["RenditaCatastaleStringa"] = item["RenditaCatastale"] == DBNull.Value ? "-" : Helper.FormatCurrency(item["RenditaCatastale"].ToString());
                for (int i = 1; i <= 5; i++)
                {
                    var campo = string.Format("Cliente{0}", i);
                    var campoStringa = string.Format("Cliente{0}Stringa", i);
                    var campoStringaAs = string.Format("Cliente{0}StringaAsterischi", i);
                    if (dsOriginal.Tables[2].AsEnumerable()
                        .FirstOrDefault(l => l.Field<string>("IdImmobileCatasto") == item["IdImmobileCatasto"].ToString()
                            && l.Field<int>("posizionecliente") == i) != null)
                    {
                        item[campo] = item[campoStringaAs] = 88;
                      
                    }
                    if (Convert.ToInt32(item[campoStringaAs]) == 13) { 
                        item[campo] =item[campoStringaAs]= 88;  
                    }
                    item[campoStringa] = Convert.ToInt32(item[campoStringaAs]) == 9 || Convert.ToInt32(item[campoStringaAs]) == 88 || Convert.ToInt32(item[campoStringaAs]) == 13  ? "n.d." : Convert.ToInt32(item[campoStringaAs]) == 10 ? "Usufrutto" : Convert.ToDecimal(item[campo]) > 100 ? "n.d." : Helper.Decodifiche.DecodificaQuotaProprieta(Convert.ToDecimal(item[campo]));
                   
              }

             
            }

            // Clienti
            var dt2 = dsOriginal.Tables[1];
            dt2.TableName = "Clienti";

            #region Ordinamento

            //L’odinamento dei fabbricati elencati nella tabella è costruito con le seguenti regole:
            // 1.	Immobile di residenza (se indicato)
            // 2.	Pertinenza dell’immobile di residenza (se indicata)
            // 3.	Fabbricati del comune di residenza:
            //      	Abitazioni (per indirizzo);
            //      	Box/posti auto (per indirizzo);
            //      	Altre categorie fabbricati (per indirizzo).
            // 4.	Fabbricati di altri comuni (per indirizzo):
            //      	Abitazioni (per indirizzo);
            //      	Box/posti auto (per indirizzo);
            //      	Altre categorie fabbricati (per indirizzo).

            var codiceComuneResidenza = dt2.Rows[0]["codComuneResidenza"] != DBNull.Value ? dt2.Rows[0]["codComuneResidenza"].ToString() : string.Empty;
            DataTable dtOrdinamentoStep1;
            DataTable dtOrdinamentoStep2;

            if (string.IsNullOrEmpty(codiceComuneResidenza))
            {
                dtOrdinamentoStep1 = dt1.AsEnumerable()
                .OrderByDescending(o => o.Field<int>("ordResidenza"))
                .ThenByDescending(o => o.Field<int>("ordPertinenza"))
                .ThenByDescending(o => o.Field<int>("ordindirizzo"))
                .ThenByDescending(o => o.Field<decimal>("controvaloreComune"))
                .ThenBy(o => o.Field<string>("indirizzo"))
                .ThenByDescending(o => o.Field<int>("ordFabbricati"))
                .ThenByDescending(o => o.Field<decimal>("Totale"))
                .CopyToDataTable();

                dtOrdinamentoStep2 = dtOrdinamentoStep1;
            }
            else
            {
                dtOrdinamentoStep1 = dt1.AsEnumerable().CopyToDataTable();

                // prima recupero i CodComune = codiceComuneResidenza
                // - verifico che siano presenti prima di ordinare
                if (dtOrdinamentoStep1.AsEnumerable().Any(o => o.Field<string>("CodComune").Equals(codiceComuneResidenza)))
                {
                    dtOrdinamentoStep2 = dtOrdinamentoStep1.AsEnumerable().Where(o => o.Field<string>("CodComune").Equals(codiceComuneResidenza))
                        .OrderByDescending(o => o.Field<int>("ordResidenza"))
                        .ThenByDescending(o => o.Field<int>("ordPertinenza"))
                        .ThenByDescending(o => o.Field<int>("ordindirizzo"))
                        .ThenByDescending(o => o.Field<decimal>("controvaloreComune"))
                         .ThenBy(o => o.Field<string>("indirizzo"))
                        .ThenByDescending(o => o.Field<int>("ordFabbricati"))
                        .ThenByDescending(o => o.Field<decimal>("Totale"))
                        .CopyToDataTable();
                }
                else
                    dtOrdinamentoStep2 = dtOrdinamentoStep1;

                // poi recupero tutti gli altri
                // - verifico che siano presenti prima di ordinar
                if (dtOrdinamentoStep1.AsEnumerable().Any(o => o.Field<string>("CodComune") != codiceComuneResidenza))
                {
                    dtOrdinamentoStep2.Merge(dtOrdinamentoStep1.AsEnumerable().Where(o => o.Field<string>("CodComune") != codiceComuneResidenza)
                        
                        //.OrderByDescending(o => o.Field<decimal>("controvaloreComune"))
                        .OrderBy(o => o.Field<string>("indirizzo"))
                         .ThenByDescending(o => o.Field<int>("ordFabbricati"))
                         .ThenByDescending(o => o.Field<decimal>("Totale"))
                         .CopyToDataTable());
                }
            }

            // Riordino l'indice
            var indice = 0;
            foreach (DataRow item in dtOrdinamentoStep2.Rows)
            {
                item["Indice"] = indice;
                indice++;
            }

            //Rinomino dt di output
            dtOrdinamentoStep2.TableName = "Dati";

            #endregion
         
            // Dataset di ritorno
            var dsResult = new DataSet();
            dsResult.Tables.Add(dtOrdinamentoStep2.Copy());
            dsResult.Tables.Add(dt2.Copy());
           // dsResult.Tables.Add(dt3);
            return dsResult;
        }
    }
}
