<commit_before>﻿//-----------------------------------------------------------------------
// <copyright file="ComposizioneSquadreQueryHandler.cs" company="CNVVF">
// Copyright (C) 2017 - CNVVF
//
// This file is part of SOVVF.
// SOVVF is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// SOVVF is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// </copyright>
//-----------------------------------------------------------------------

using CQRS.Queries;
using Google_API;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SO115App.API.Models.Classi.Condivise;
using SO115App.API.Models.Classi.Soccorso;
using SO115App.API.Models.Classi.Utenti;
using SO115App.Models.Classi.Composizione;
using SO115App.Models.Classi.Condivise;
using SO115App.Models.Classi.Utility;
using SO115App.Models.Servizi.Infrastruttura.Composizione;
using SO115App.Models.Servizi.Infrastruttura.GeoFleet;
using SO115App.Models.Servizi.Infrastruttura.GestioneSoccorso.GestioneTipologie;
using SO115App.Models.Servizi.Infrastruttura.GestioneStatoOperativoSquadra;
using SO115App.Models.Servizi.Infrastruttura.SistemiEsterni.Gac;
using SO115App.Models.Servizi.Infrastruttura.SistemiEsterni.Squadre;
using SO115App.Models.Servizi.Infrastruttura.Turni;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using ComposizioneSquadre = SO115App.API.Models.Classi.Composizione.ComposizioneSquadre;
using ComposizioneMezzi = SO115App.API.Models.Classi.Composizione.ComposizioneMezzi;

namespace SO115App.API.Models.Servizi.CQRS.Queries.GestioneSoccorso.Composizione.ComposizionePartenzaAvanzata
{
    public class ComposizionePartenzaAvanzataQueryHandler : IQueryHandler<ComposizionePartenzaAvanzataQuery, ComposizionePartenzaAvanzataResult>
    {
        #region Servizi

        private readonly IGetListaSquadre _getListaSquadre;
        private readonly IGetMezziUtilizzabili _getMezziUtilizzabili;
        private readonly IGetStatoSquadra _getStatoSquadre;
        private readonly IGetStatoMezzi _getMezziPrenotati;
        private readonly IGetPosizioneFlotta _getPosizioneFlotta;

        private readonly IGetTipologieByCodice _getTipologieByCodice;
        private readonly IConfiguration _configuration;
        private readonly IMemoryCache _memoryCache;
        private readonly IGetTurno _getTurno;

        #endregion

        public ComposizionePartenzaAvanzataQueryHandler(
            IGetListaSquadre getListaSquadre,
            IGetStatoSquadra getStatoSquadre,
            IGetStatoMezzi getMezziPrenotati,
            IGetMezziUtilizzabili getMezziUtilizzabili,
            IGetPosizioneFlotta getPosizioneFlotta,

            IGetTipologieByCodice getTipologieByCodice,
            IConfiguration configuration,
            IMemoryCache memoryCache,
            IGetTurno getTurno)
        {
            _getListaSquadre = getListaSquadre;
            _getMezziPrenotati = getMezziPrenotati;
            _getMezziUtilizzabili = getMezziUtilizzabili;
            _getStatoSquadre = getStatoSquadre;
            _getPosizioneFlotta = getPosizioneFlotta;

            _getTipologieByCodice = getTipologieByCodice;
            _configuration = configuration;
            _memoryCache = memoryCache;
            _getTurno = getTurno;
        }

        public ComposizionePartenzaAvanzataResult Handle(ComposizionePartenzaAvanzataQuery query)
        {
            Log.Debug("Inizio elaborazione Composizione partenza avanzata Handler");

            var lstSedi = query.CodiceSede.ToList();
            var tipologia90 = _getTipologieByCodice.Get(new List<string> { "90" }).First();

            var turnoCorrente = _getTurno.Get();
            var turnoPrecedente = _getTurno.Get(turnoCorrente.DataOraInizio.AddMilliseconds(-1));
            var turnoSuccessivo = _getTurno.Get(turnoCorrente.DataOraFine.AddMinutes(1));

            //REPERISCO I DATI, FACCIO IL MAPPING ED APPLICO I FILTRI (MEZZI E SQUADRE)
            var lstSquadre = _getListaSquadre.Get(lstSedi)
                .ContinueWith(lstsquadre =>
                {
                    var statiOperativi = _getStatoSquadre.Get(lstSedi);

                    return lstsquadre.Result.Select(squadra =>
                    {
                        if (statiOperativi.Exists(x => x.IdSquadra.Equals(squadra.Id)))
                            squadra.Stato = MappaStatoSquadraDaStatoMezzo.MappaStato(statiOperativi.Find(x => x.IdSquadra.Equals(squadra.Id)).StatoSquadra);
                        else
                            squadra.Stato = Squadra.StatoSquadra.InSede;

                        var comp =  new Classi.Composizione.ComposizioneSquadre()
                        {
                            Id = squadra.Id,
                            Squadra = squadra
                        };

                        squadra.IndiceOrdinamento = new OrdinamentoSquadre(query.Richiesta).GetIndiceOrdinamento(comp);


                        return comp;
                    });
                })
                .ContinueWith(lstCompSquadre => FiltraSquadre(query, lstCompSquadre.Result, tipologia90, turnoCorrente, turnoPrecedente, turnoSuccessivo));

            var lstMezzi = _getPosizioneFlotta.Get(0)
                .ContinueWith(lstPosizioneFlotta => _getMezziUtilizzabili.Get(lstSedi, posizioneFlotta: lstPosizioneFlotta.Result).Result)
                .ContinueWith(lstmezzi => //Mapping 
                {
                    var composizioneMezzi = (from mezzo in lstmezzi.Result
                                             let kmGen = new Random().Next(1, 60).ToString()
                                             let tempoPer = Convert.ToDouble(kmGen.Replace(".", ",")) / 1.75
                                             select new Classi.Composizione.ComposizioneMezzi()
                                             {
                                                 Id = mezzo.Codice,
                                                 Mezzo = mezzo,
                                                 Km = kmGen,
                                                 TempoPercorrenza = Math.Round(tempoPer, 2).ToString(CultureInfo.InvariantCulture),
                                             }).ToList();

                    var mezziPrenotati = _getMezziPrenotati.Get(query.CodiceSede);

                    decimal totaleKM = 0;
                    decimal totaleTempoPercorrenza = 0;
                    string mediaDistanza;
                    string mediaTempoPercorrenza;

                    return composizioneMezzi.Select(c =>
                    {
                        if (c.IstanteScadenzaSelezione < DateTime.Now)
                            c.IstanteScadenzaSelezione = null;

                        if (mezziPrenotati.Find(x => x.CodiceMezzo.Equals(c.Mezzo.Codice)) != null)
                        {
                            c.Id = c.Mezzo.Codice;
                            c.IstanteScadenzaSelezione = mezziPrenotati.Find(x => x.CodiceMezzo.Equals(c.Mezzo.Codice)).IstanteScadenzaSelezione;

                            if (c.Mezzo.Stato.Equals("In Sede"))
                                c.Mezzo.Stato = mezziPrenotati.Find(x => x.CodiceMezzo.Equals(c.Mezzo.Codice)).StatoOperativo;
                        }

                        //Per i mezzi con coordinate Fake nella property  i Km  e la TempoPercorrenza vengono impostati i  valori medi della collection
                        totaleKM += Convert.ToDecimal(c.Km.Replace(".", ","));
                        totaleTempoPercorrenza += Convert.ToDecimal(c.TempoPercorrenza.Replace(".", ","));

                        mediaDistanza = Math.Round(totaleKM / composizioneMezzi.Count(), 2).ToString(CultureInfo.InvariantCulture);
                        mediaTempoPercorrenza = Math.Round(totaleTempoPercorrenza / composizioneMezzi.Count(), 2).ToString(CultureInfo.InvariantCulture);

                        c.Km = mediaDistanza;
                        c.TempoPercorrenza = mediaTempoPercorrenza;
                        c.IndiceOrdinamento = new OrdinamentoMezzi(query.Richiesta, _getTipologieByCodice, _configuration, _memoryCache).GetIndiceOrdinamento(c, c.Mezzo.CoordinateFake);

                        return c;
                    });
                })
                .ContinueWith(lstCompMezzi => FiltraMezzi(query, lstCompMezzi.Result));

            //PREPARO PAGINAZIONE IN BASE AI FILTRI
            var indexMezzo = query.Filtro.Mezzo != null ? lstMezzi.Result.FindIndex(c => c.Mezzo.Codice.Equals(query.Filtro.Mezzo.Codice)) : 0;
            var indexSquadra = query.Filtro.Squadre != null ? lstSquadre.Result.FindIndex(c => c.Squadra.Codice.Equals(query.Filtro.Squadre.FirstOrDefault().Codice)) : 0;

            if (indexMezzo != 0)<commit_msg>fix: notevole ottimizzazione composizione partenza avanzata<commit_after>﻿//-----------------------------------------------------------------------
// <copyright file="ComposizioneSquadreQueryHandler.cs" company="CNVVF">
// Copyright (C) 2017 - CNVVF
//
// This file is part of SOVVF.
// SOVVF is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// SOVVF is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// </copyright>
//-----------------------------------------------------------------------

using CQRS.Queries;
using Google_API;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SO115App.API.Models.Classi.Condivise;
using SO115App.API.Models.Classi.Soccorso;
using SO115App.API.Models.Classi.Utenti;
using SO115App.Models.Classi.Composizione;
using SO115App.Models.Classi.Condivise;
using SO115App.Models.Classi.Utility;
using SO115App.Models.Servizi.Infrastruttura.Composizione;
using SO115App.Models.Servizi.Infrastruttura.GeoFleet;
using SO115App.Models.Servizi.Infrastruttura.GestioneSoccorso.GestioneTipologie;
using SO115App.Models.Servizi.Infrastruttura.GestioneStatoOperativoSquadra;
using SO115App.Models.Servizi.Infrastruttura.SistemiEsterni.Gac;
using SO115App.Models.Servizi.Infrastruttura.SistemiEsterni.Squadre;
using SO115App.Models.Servizi.Infrastruttura.Turni;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using ComposizioneSquadre = SO115App.API.Models.Classi.Composizione.ComposizioneSquadre;
using ComposizioneMezzi = SO115App.API.Models.Classi.Composizione.ComposizioneMezzi;

namespace SO115App.API.Models.Servizi.CQRS.Queries.GestioneSoccorso.Composizione.ComposizionePartenzaAvanzata
{
    public class ComposizionePartenzaAvanzataQueryHandler : IQueryHandler<ComposizionePartenzaAvanzataQuery, ComposizionePartenzaAvanzataResult>
    {
        #region Servizi

        private readonly IGetListaSquadre _getListaSquadre;
        private readonly IGetMezziUtilizzabili _getMezziUtilizzabili;
        private readonly IGetStatoSquadra _getStatoSquadre;
        private readonly IGetStatoMezzi _getMezziPrenotati;
        private readonly IGetPosizioneFlotta _getPosizioneFlotta;

        private readonly IGetTipologieByCodice _getTipologieByCodice;
        private readonly IConfiguration _configuration;
        private readonly IMemoryCache _memoryCache;
        private readonly IGetTurno _getTurno;

        #endregion

        public ComposizionePartenzaAvanzataQueryHandler(
            IGetListaSquadre getListaSquadre,
            IGetStatoSquadra getStatoSquadre,
            IGetStatoMezzi getMezziPrenotati,
            IGetMezziUtilizzabili getMezziUtilizzabili,
            IGetPosizioneFlotta getPosizioneFlotta,

            IGetTipologieByCodice getTipologieByCodice,
            IConfiguration configuration,
            IMemoryCache memoryCache,
            IGetTurno getTurno)
        {
            _getListaSquadre = getListaSquadre;
            _getMezziPrenotati = getMezziPrenotati;
            _getMezziUtilizzabili = getMezziUtilizzabili;
            _getStatoSquadre = getStatoSquadre;
            _getPosizioneFlotta = getPosizioneFlotta;

            _getTipologieByCodice = getTipologieByCodice;
            _configuration = configuration;
            _memoryCache = memoryCache;
            _getTurno = getTurno;
        }

        public ComposizionePartenzaAvanzataResult Handle(ComposizionePartenzaAvanzataQuery query)
        {
            Log.Debug("Inizio elaborazione Composizione partenza avanzata Handler");

            var lstSedi = query.CodiceSede.ToList();
            var tipologia90 = _getTipologieByCodice.Get(new List<string> { "90" }).First();

            var turnoCorrente = _getTurno.Get();
            var turnoPrecedente = _getTurno.Get(turnoCorrente.DataOraInizio.AddMilliseconds(-1));
            var turnoSuccessivo = _getTurno.Get(turnoCorrente.DataOraFine.AddMinutes(1));

            //REPERISCO I DATI, FACCIO IL MAPPING ED APPLICO I FILTRI (MEZZI E SQUADRE)
            var lstSquadre = Task.Factory.StartNew(() => _getListaSquadre.Get(lstSedi)
                .ContinueWith(lstsquadre =>
                {
                    var statiOperativi = _getStatoSquadre.Get(lstSedi);

                    return lstsquadre.Result.Select(squadra =>
                    {
                        if (statiOperativi.Exists(x => x.IdSquadra.Equals(squadra.Id)))
                            squadra.Stato = MappaStatoSquadraDaStatoMezzo.MappaStato(statiOperativi.Find(x => x.IdSquadra.Equals(squadra.Id)).StatoSquadra);
                        else
                            squadra.Stato = Squadra.StatoSquadra.InSede;

                        var comp =  new Classi.Composizione.ComposizioneSquadre()
                        {
                            Id = squadra.Id,
                            Squadra = squadra
                        };

                        squadra.IndiceOrdinamento = new OrdinamentoSquadre(query.Richiesta).GetIndiceOrdinamento(comp);


                        return comp;
                    });
                })
                .ContinueWith(lstCompSquadre => FiltraSquadre(query, lstCompSquadre.Result, tipologia90, turnoCorrente, turnoPrecedente, turnoSuccessivo)).Result);

            var lstMezzi = Task.Factory.StartNew(() => _getPosizioneFlotta.Get(0)
                .ContinueWith(lstPosizioneFlotta => _getMezziUtilizzabili.Get(lstSedi, posizioneFlotta: lstPosizioneFlotta.Result).Result)
                .ContinueWith(lstmezzi => //Mapping 
                {
                    var composizioneMezzi = (from mezzo in lstmezzi.Result
                                             let kmGen = new Random().Next(1, 60).ToString()
                                             let tempoPer = Convert.ToDouble(kmGen.Replace(".", ",")) / 1.75
                                             select new Classi.Composizione.ComposizioneMezzi()
                                             {
                                                 Id = mezzo.Codice,
                                                 Mezzo = mezzo,
                                                 Km = kmGen,
                                                 TempoPercorrenza = Math.Round(tempoPer, 2).ToString(CultureInfo.InvariantCulture),
                                             }).ToList();

                    var mezziPrenotati = _getMezziPrenotati.Get(query.CodiceSede);

                    decimal totaleKM = 0;
                    decimal totaleTempoPercorrenza = 0;
                    string mediaDistanza;
                    string mediaTempoPercorrenza;

                    return composizioneMezzi.Select(c =>
                    {
                        if (c.IstanteScadenzaSelezione < DateTime.Now)
                            c.IstanteScadenzaSelezione = null;

                        if (mezziPrenotati.Find(x => x.CodiceMezzo.Equals(c.Mezzo.Codice)) != null)
                        {
                            c.Id = c.Mezzo.Codice;
                            c.IstanteScadenzaSelezione = mezziPrenotati.Find(x => x.CodiceMezzo.Equals(c.Mezzo.Codice)).IstanteScadenzaSelezione;

                            if (c.Mezzo.Stato.Equals("In Sede"))
                                c.Mezzo.Stato = mezziPrenotati.Find(x => x.CodiceMezzo.Equals(c.Mezzo.Codice)).StatoOperativo;
                        }

                        //Per i mezzi con coordinate Fake nella property  i Km  e la TempoPercorrenza vengono impostati i  valori medi della collection
                        totaleKM += Convert.ToDecimal(c.Km.Replace(".", ","));
                        totaleTempoPercorrenza += Convert.ToDecimal(c.TempoPercorrenza.Replace(".", ","));

                        mediaDistanza = Math.Round(totaleKM / composizioneMezzi.Count(), 2).ToString(CultureInfo.InvariantCulture);
                        mediaTempoPercorrenza = Math.Round(totaleTempoPercorrenza / composizioneMezzi.Count(), 2).ToString(CultureInfo.InvariantCulture);

                        c.Km = mediaDistanza;
                        c.TempoPercorrenza = mediaTempoPercorrenza;
                        c.IndiceOrdinamento = new OrdinamentoMezzi(query.Richiesta, _getTipologieByCodice, _configuration, _memoryCache).GetIndiceOrdinamento(c, c.Mezzo.CoordinateFake);

                        return c;
                    });
                })
                .ContinueWith(lstCompMezzi => FiltraMezzi(query, lstCompMezzi.Result)).Result);

            //PREPARO PAGINAZIONE IN BASE AI FILTRI
            var indexMezzo = query.Filtro.Mezzo != null ? lstMezzi.Result.FindIndex(c => c.Mezzo.Codice.Equals(query.Filtro.Mezzo.Codice)) : 0;
            var indexSquadra = query.Filtro.Squadre != null ? lstSquadre.Result.FindIndex(c => c.Squadra.Codice.Equals(query.Filtro.Squadre.FirstOrDefault().Codice)) : 0;

            if (indexMezzo != 0)
{'fraction_non_alphanumeric': 0.09128783883556586, 'fraction_numerical': 0.008016032064128256, 'mean_word_length': 2.025366943203574, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '147102', 'n_tokens_mistral': 5736, 'n_tokens_neox': 5387, 'n_words': 960}