using EgwProxy.Gomba.GombaServ;
using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using MapoSDK;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net.NetworkInformation;

namespace IOB_WIN_WS.IobWs
{
    /// <summary>
    /// Adapter specializzato per GOMBA e le chiamate tramite WS Soap alla bilancia, libreria EgwProxy.Gomba
    /// </summary>
    public class Gomba : Iob.GenericNext
    {
        #region Public Constructors

        /// <summary>
        /// Costruttore dell'IOB SOAP della bilancia GOMBA
        /// </summary>
        /// <param name="caller">Form chiamante</param>
        /// <param name="IOBConf">Configurazione (legacy)</param>
        /// <param name="IobConfFull">Configurazione (v 4.x)</param>
        public Gomba(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            lgInfo($"Richiesto Adapter IobSoap.Gomba con i parametri seguenti | ADDR: {IOBConfFull.Device.Connect.IpAddr} | PORT: {IOBConfFull.Device.Connect.Port}");
            redKeyPesate = redisMan.redHash($"IOB:Status:{IOBConfFull.General.CodIOB}:ListPesate");
            lastPING = DateTime.Now.AddHours(-1);
            // verifico se sia attiva gestione riduzione FluxLog...
            if (!string.IsNullOrEmpty(getOptJsonKVP("numLastWeight")))
            {
                int.TryParse(getOptJsonKVP("numLastWeight"), out numLastWeight);
                lgInfo($"Gomba: setup specifico | numLastWeight: {numLastWeight}");
            }
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Implementazione custom esecuzione task specifici
        /// </summary>
        /// <param name="task2exe"></param>
        /// <returns></returns>
        public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe, string codTav)
        {
            /*---------------------------------------
             * gestione execute task SPECIFICI x pesa:
             * - salva i parametri richiesta (RM, cod1..cod6)
             * - esegue metodo richiesta (IN/OUT)
             *---------------------------------------*/

            // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
            Dictionary<string, string> taskDone = new Dictionary<string, string>();
            if (task2exe != null)
            {
                lgTrace($"executeTasks: richiesta esecuzione {task2exe.Count} task");
                // controllo se memMap != null...
                if (memMap != null)
                {
                    bool taskOk = false;
                    string taskVal = "";
                    // cerco task specifici: qui sono NON standard...
                    foreach (var item in task2exe)
                    {
                        lgInfo($"TASK | {item.Key} --> {item.Value}");
                        taskOk = false;
                        taskVal = "";
                        // converto richiesta in enum...
                        taskType tName = taskType.nihil;
                        Enum.TryParse(item.Key, out tName);
                        // controllo sulla KEY...
                        switch (tName)
                        {
                            case taskType.setParameter:
                                // richiedo da URL i parametri WRITE da popolare
                                lgInfo("Chiamata setParameter --> processMemWriteRequests");
                                taskVal = processMemWriteRequests();
                                // se restituiscce "" faccio altra prova...
                                if (string.IsNullOrEmpty(taskVal))
                                {
                                    // i parametri me li aspetto come stringa composta paramName|paramvalue
                                    if (item.Value.Contains("|"))
                                    {
                                        string[] paramsJob = item.Value.Split('|');
                                        taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}";
                                    }
                                    else
                                    {
                                        taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value";
                                    }
                                }
                                break;

                            default:
                                taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
                                lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
                                break;
                        }
                        // aggiungo task!
                        taskDone.Add(item.Key, taskVal);
                    }
                }
                else
                {
                    lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
                }
            }

            return taskDone;
        }

        /// <summary>
        /// Recupero dati dinamici...
        /// </summary>
        public override Dictionary<string, string> getDynData()
        {
            // valore non presente in vers default... se gestito fare override
            Dictionary<string, string> outVal = new Dictionary<string, string>();
            // controllo se ho indicato ancora che ci siano pesate già lette da inviare...
            if (num2send() > 0)
            {
                // preparo oggetti x confronto ...
                List<WeightRec> listaArch = listPesateArchivio;

                // se non ho nulla in archivio prendo ultima pesata (essendo DESC è la prima cronologicamente)
                if (listaArch.Count == 0)
                {
                    WeightRec lastRec = listPesateCurr.LastOrDefault();
                    // aggiungo...
                    SavePesata(ref outVal, lastRec);
                }
                // ora il confronto è cronologico sulle pesate + recenti...
                else
                {
                    // prendo prima della lista pesate archiviate = più recente come dt da cui partire...
                    DateTime dtRif = listaArch.FirstOrDefault().DtEvent;
                    var firstRec = listPesateCurr
                                            .Where(x => x.DtEvent > dtRif)
                                            .OrderBy(x => x.DtEvent)
                                            .FirstOrDefault();
                    if (firstRec != null)
                    {
                        SavePesata(ref outVal, firstRec);
                    }
                }

                // processo comunque le aree memoria READ...
                if (memMap.mMapRead.Count > 0)
                {
                    foreach (var item in memMap.mMapRead)
                    {
                        var currVal = getCurrProdData(item.Key, "");
                        if (!outVal.ContainsKey(item.Key))
                        {
                            outVal.Add(item.Key, $"{currVal}");
                        }
                        // se fosse logReq --> resetto...
                        if (item.Key == "logReq" && !string.IsNullOrEmpty(currVal))
                        {
                            upsertKey(item.Key, "");
                        }
                    }
                }
            }
            // altrimenti rileggo e cerco se ci siano
            else
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                try
                {
                    // test lettura elenco pesate... se NON nullo --> OK!
                    var weightArray = gombaConn.reqWeightList("ALL", dataFrom, dataTo);
                    // riordino DESC
                    listPesateCurr = WeightRec.ConvertPesate(weightArray.OrderByDescending(x => x.dateIn).ToList());
                }
                catch (Exception exc)
                {
                    lgError($"Eccezione in gombaConn.reqWeightList{Environment.NewLine}{exc}");
                }
                sw.Stop();
                lgInfo($"getDynData | SOAP: effettuata chiamata reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo} | {listPesateCurr.Count} rec");
            }
            // indico esecuzione e proseguo
            lastReadPLC = DateTime.Now;
            return outVal;
        }

        /// <summary>
        /// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
        /// aggiornare x display in form</paramref>
        /// </summary>
        public override void readSemafori(ref newDisplayData currDispData)
        {
            if (connectionOk)
            {
                B_input = 1;
                currDispData.semIn = Semaforo.SV;

                // se ho pesate in memoria nel periodo richiesto --> RUN
                if (listPesateCurr != null && listPesateCurr.Count > 0)
                {
                    B_input += (1 << 1);
                }
                // metto manuale
                else
                {
                    B_input += (1 << 4);
                }

                // accodo NON emergenza
                B_input += (1 << 7);
            }
            else
            {
                B_input = 0;
                currDispData.semIn = Semaforo.SR;
            }
        }

        /// <summary>
        /// Override connessione
        /// </summary>
        public override void tryConnect()
        {
            if (!connectionOk)
            {
                // controllo che il ping sia stato tentato almeno pingTestSec fa...
                if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
                {
                    if (verboseLog || periodicLog)
                    {
                        lgInfo("Gomba: ConnKO - tryConnect");
                    }
                    // in primis salvo data ping...
                    lastPING = DateTime.Now;
                    // se passa il ping faccio il resto...
                    if (testPingMachine == IPStatus.Success)
                    {
                        string szStatusConnection = "";
                        try
                        {
                            // ora provo connessione...
                            parentForm.commPlcActive = true;

                            // init del proxy!!!
                            string endpointAddr = $"https://{IOBConfFull.Device.Connect.IpAddr}:{IOBConfFull.Device.Connect.Port}/ws";
                            lgInfo($"Tentativo avvio SOAP su endpoint {endpointAddr}");
                            Stopwatch sw = new Stopwatch();
                            sw.Start();

                            // salto verifica certificato
                            System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };

                            // riprovo connessione SE non fosse andata...
                            int maxTry = 5;
                            int nTry = 1;
                            // tento avvio WS SOAP!
                            gombaConn = new EgwProxy.Gomba.GombaServ.lwpServiceClient("lwpServicePort", new System.ServiceModel.EndpointAddress(endpointAddr));
                            while (gombaConn == null || (nTry <= maxTry && !checkStateOk(gombaConn.State)))
                            {
                                lgInfo($"Tentativo connessione Gomba: | endpointAddr: {endpointAddr} | nTry: {nTry}");
                                // tento avvio WS SOAP!
                                gombaConn = new EgwProxy.Gomba.GombaServ.lwpServiceClient("lwpServicePort", new System.ServiceModel.EndpointAddress(endpointAddr));
                                nTry++;
                            }
                            if (checkStateOk(gombaConn.State))
                            {
                                connectionOk = true;
                                List<gestWeightOut> weightArray = new List<gestWeightOut>();
                                try
                                {
                                    // test lettura elenco pesate... se NON nullo --> OK!
                                    weightArray = gombaConn.reqWeightList("ALL", dataFrom, dataTo).OrderByDescending(x => x.dateIn).ToList();
                                    // riordino DESC
                                    listPesateCurr = WeightRec.ConvertPesate(weightArray);
                                }
                                catch (Exception exc)
                                {
                                    lgError($"Eccezione in gombaConn.reqWeightList{Environment.NewLine}{exc}");
                                }
                                sw.Stop();
                                lgInfo($"SOAP: effettuata chiamata connessione + reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo}");
                                if (listPesateCurr != null && listPesateCurr.Count >= 0)
                                {
                                    lgInfo($"szStatusConnection Gomba, recuperato elenco di {listPesateCurr.Count} pesate");
                                    parentForm.commPlcActive = false;
                                    connectionOk = true;
                                    // sistemo data da cui iniziare recuperi successivi se ho + di numLastWeight
                                    if (weightArray.Count > numLastWeight)
                                    {
                                        var lastRec = weightArray
                                                        .OrderByDescending(x => x.dateIn)
                                                        .Skip(numLastWeight).FirstOrDefault();
                                        // metto giorno antecedente
                                        dtStartLive = lastRec.dateIn.Date.AddDays(-1);
                                    }
                                    // processo pesate!
                                    demFactDynData = 1;
                                    processDynData();
                                }
                            }
                            // refresh stato connessione!!!
                            if (connectionOk)
                            {
                                queueInEnabCurr = true;
                                if (adpRunning)
                                {
                                    lgInfo("Connessione OK");
                                }
                            }
                            else
                            {
                                lgError("Impossibile procedere, connessione mancante...");
                            }
                        }
                        catch (Exception exc)
                        {
                            lgFatal($"Errore nella connessione all'adapter Gomba: {szStatusConnection}{Environment.NewLine}{exc}");
                            connectionOk = false;
                            lgInfo($"Eccezione in TryConnect, Adapter Gomba NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione");
                        }
                    }
                    else
                    {
                        // loggo no risposta ping ...
                        connectionOk = false;
                        if (verboseLog || periodicLog)
                        {
                            lgInfo($"Attenzione: Gomba controllo PING fallito per IP {IOBConfFull.Device.Connect.PingIpAddr}");
                        }
                    }
                }
            }
            else
            {
                needRefresh = true;
            }
        }

        public override void tryDisconnect()
        {
            // registro solo che è disconnesso
            connectionOk = false;
            queueInEnabCurr = false;
        }

        #endregion Public Methods

        #region Protected Fields

        /// <summary>
        /// Proxy per connessione al SOAP webservice GOMBA
        /// </summary>
        protected EgwProxy.Gomba.GombaServ.lwpServiceClient gombaConn;

        protected int numLastWeight = 100;

        #endregion Protected Fields

        #region Protected Methods

        /// <summary>
        /// verifica stato ok ovvero connected oppure open
        /// </summary>
        /// <param name="currState"></param>
        /// <returns></returns>
        protected bool checkStateOk(System.ServiceModel.CommunicationState currState)
        {
            return currState == System.ServiceModel.CommunicationState.Opened || currState == System.ServiceModel.CommunicationState.Created;
        }

        /// <summary>
        /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
        /// </summary>
        /// <param name="updatedPar"></param>
        protected override void plcWriteParams(ref List<objItem> updatedPar)
        {
            lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params");
            foreach (var item in updatedPar)
            {
                lgInfo($"ITEM | {item.uid} | {item.value}");
                // salvo i valori di setup x prox pesata...
                upsertKey(item.uid, item.value);
                bool fatto = false;
                bool isPesata = false;
                bool isIN = false;
                gestWeightOut answ = new gestWeightOut();
                // se è richiesta pesata IN/OUT --> mando chiamata
                if (item.uid == "reqPesata")
                {
                    isPesata = true;
                    isIN = item.reqValue.ToUpper() == "IN";
                    //isIN = item.value.ToUpper() == "IN";
                    try
                    {
                        answ = reqWeight(isIN);
                    }
                    catch (Exception exc)
                    {
                        lgError($"Eccezione in plcWriteParams.reqWeight | isIn: {isIN}{Environment.NewLine}{exc}");
                    }
                }
                else if (item.uid == "RM" || item.uid.StartsWith("Cod"))
                {
                    // comunque segno fatto x altri casi
                    fatto = true;
                }

                // se è pesata...
                if (isPesata)
                {
                    // se è OK
                    if (answ.feedback == "C")
                    {
                        lgInfo($"reqWeight | Effettuato richiesta | {answ.feedback} | {answ.notes}");
                        // resetto pesata
                        upsertKey(item.uid, "");
                    }
                    else
                    {
                        lgError($"reqWeight | Errore in richiesta peso GOMBA | {answ.feedback} | {answ.notes}");
                    }
                    item.value = "";
                    item.reqValue = "";
                    item.lastRead = DateTime.Now;
                    item.UM = "";
                    // salvo esito richiesta comunque
                    upsertKey("logReq", $"{answ.feedback} | {answ.notes}");
                    // faccio in modo di eseguire subito getDynData
                    demFactDynData = 1;
                    processDynData();
                }
                else
                {
                    // se fatto --> aggiorno!
                    if (fatto)
                    {
                        //item.value = item.reqValue;
                        item.reqValue = "";
                        item.lastRead = DateTime.Now;
                        item.UM = "";
                    }
                }
            }
        }

        /// <summary>
        /// Esegue richiesta PESO
        /// </summary>
        /// <param name="reqIN">Tipo richiesta: IN (true) / OUT (false)</param>
        /// <returns></returns>
        protected gestWeightOut reqWeight(bool reqIN)
        {
            lgInfo($"reqWeight | IN: {reqIN}");
            gestWeightOut answ = null;
            try
            {
                Stopwatch sw = new Stopwatch();
                sw.Start();
                // preparo parametri
                string tipoRic = reqIN ? "IN" : "OUT";
                string rm = getCurrProdData("RM", $"{DateTime.Now:yyyyMMdd-HHmmss}");// string.IsNullOrEmpty(currProdData["RM"]) ? $"{DateTime.Now:yyyyMMdd-HHmmss}" : currProdData["RM"];
                string Cod1 = getCurrProdData("Cod1", ""); //string.IsNullOrEmpty(currProdData["Cod1"]) ? "" : currProdData["Cod1"];
                string Cod2 = getCurrProdData("Cod2", ""); //string.IsNullOrEmpty(currProdData["Cod2"]) ? "" : currProdData["Cod2"];
                string Cod3 = getCurrProdData("Cod3", ""); //string.IsNullOrEmpty(currProdData["Cod3"]) ? "" : currProdData["Cod3"];
                string Cod4 = getCurrProdData("Cod4", ""); //string.IsNullOrEmpty(currProdData["Cod4"]) ? "" : currProdData["Cod4"];
                string Cod5 = getCurrProdData("Cod5", ""); //string.IsNullOrEmpty(currProdData["Cod5"]) ? "" : currProdData["Cod5"];
                string Cod6 = getCurrProdData("Cod6", ""); //string.IsNullOrEmpty(currProdData["Cod6"]) ? "" : currProdData["Cod6"];
                // faccio chiamata
                answ = gombaConn.memWeight(tipoRic, rm, Cod1, Cod2, Cod3, Cod4, Cod5, Cod6);
                sw.Stop();
                lgInfo($"reqWeight: effettuata chiamata SOAP in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo}");
            }
            catch (Exception exc)
            {
                lgError($"reqWeight | errore richiesta pesatura{Environment.NewLine}{exc}");
            }
            return answ;
        }

        protected void SavePesata(ref Dictionary<string, string> currDict, WeightRec newRec)
        {
            DictUpsert(ref currDict, "RM", newRec.RM ?? "");
            string tag = newRec.isIn ? "In" : "Out";
            DictUpsert(ref currDict, $"lastWeight{tag}", $"{newRec.weight:N2}");
            // registro record completo ultima pesata
            DictUpsert(ref currDict, $"lastRec{tag}", formatPesata(newRec));
            // la aggiungo alle pesate archiviate...
            AppendPesata(newRec);
        }

        #endregion Protected Methods

        #region Protected Classes

        protected class WeightRec
        {
            #region Public Properties

            public string cod1 { get; set; } = "";

            public string cod2 { get; set; } = "";

            public string cod3 { get; set; } = "";

            public string cod4 { get; set; } = "";

            public string cod5 { get; set; } = "";

            public string cod6 { get; set; } = "";

            public DateTime DtEvent { get; set; } = DateTime.Today;

            public bool isIn { get; set; } = true;

            public string RM { get; set; } = "ND";

            public double weight { get; set; } = 0;

            #endregion Public Properties

            #region Public Methods

            /// <summary>
            /// Effettua converione come lista cronologica pesate (singoli record IN/OUT)
            /// </summary>
            /// <param name="pesateOrig"></param>
            /// <returns></returns>
            public static List<WeightRec> ConvertPesate(List<gestWeightOut> pesateOrig)
            {
                List<WeightRec> answ = new List<WeightRec>();
                foreach (var item in pesateOrig)
                {
                    // verifico se ci sia record IN...
                    if (item.dateInSpecified)
                    {
                        var newRec = new WeightRec()
                        {
                            RM = item.rm,
                            DtEvent = item.dateIn,
                            isIn = true,
                            cod1 = item.cod1,
                            cod2 = item.cod2,
                            cod3 = item.cod3,
                            cod4 = item.cod4,
                            cod5 = item.cod5,
                            cod6 = item.cod6,
                            weight = double.Parse(item.weightIn, NumberStyles.Any, CultureInfo.InvariantCulture)
                        };
                        answ.Add(newRec);
                    }
                    // verifico se ci sia record IN...
                    if (item.dateOutSpecified)
                    {
                        var newRec = new WeightRec()
                        {
                            RM = item.rm,
                            DtEvent = item.dateOut,
                            isIn = false,
                            cod1 = item.cod1,
                            cod2 = item.cod2,
                            cod3 = item.cod3,
                            cod4 = item.cod4,
                            cod5 = item.cod5,
                            cod6 = item.cod6,
                            weight = double.Parse(item.weightOut, NumberStyles.Any, CultureInfo.InvariantCulture)
                        };
                        answ.Add(newRec);
                    }
                }
                // riordino...
                answ = answ.OrderByDescending(x => x.DtEvent).ToList();
                // restituisco!
                return answ;
            }

            #endregion Public Methods
        }

        #endregion Protected Classes

        #region Private Properties

        /// <summary>
        /// Data inizio periodo dati Bilancia:
        /// - al boot impostato a -6 mesi
        /// - dopo lettura impostato a data ultimi 5 record
        /// </summary>
        private string dataFrom
        {
            get => dtStartLive.ToString("dd/MM/yyyy");
        }

        /// <summary>
        /// Data fine periodo dati Bilancia: oggi + 1gg
        /// </summary>
        private string dataTo
        {
            get => DateTime.Today.AddDays(1).ToString("dd/MM/yyyy");
        }

        /// <summary>
        /// Data riferimento x avvio processo controllo
        /// </summary>
        private DateTime dtStartLive { get; set; } = DateTime.Today.AddMonths(-6);

        /// <summary>
        /// Gestione archivio serializzato delle pesate già processate
        /// </summary>
        private List<WeightRec> listPesateArchivio
        {
            get
            {
                List<WeightRec> answ = new List<WeightRec>();
                string redKey = $"{redKeyPesate}:ALL";
                string rawData = redisMan.getRSV(redKey);
                if (!string.IsNullOrEmpty(rawData))
                {
                    try
                    {
                        answ = JsonConvert.DeserializeObject<List<WeightRec>>(rawData);
                        lgInfo($"Rilettura status listPesateArchivio: trovati {answ.Count} record");
                        answ = answ.OrderByDescending(x => x.DtEvent).ToList();
                    }
                    catch (Exception exc)
                    {
                        lgError($"Errore in deserializzazione listPesateArchivio{Environment.NewLine}{exc}");
                        answ = new List<WeightRec>();
                    }
                }
                // rendo
                return answ;
            }
            set
            {
                // riordino prima di procedere...
                var tempList = value.OrderByDescending(x => x.DtEvent).ToList();
                // ...trimmo se fossero + di xxx record...
                if (tempList.Count > numLastWeight)
                {
                    tempList = tempList.Take(numLastWeight).ToList();
                }
                string redKey = $"{redKeyPesate}:ALL";
                string rawVal = JsonConvert.SerializeObject(tempList);
                redisMan.setRSV(redKey, rawVal);
                lgInfo($"Salvataggio status listPesateArchivio | {tempList.Count} record");
            }
        }

        /// <summary>
        /// Elenco pesate attuali
        /// </summary>
        private List<WeightRec> listPesateCurr { get; set; } = new List<WeightRec>();

        private string redKeyPesate { get; set; } = "";

        #endregion Private Properties

        #region Private Methods

        private static string formatCode(string currCode)
        {
            string code = string.IsNullOrEmpty(currCode) ? "-" : currCode;
            return $" | {code}";
        }

        /// <summary>
        /// Formatta record completo pesata
        /// </summary>
        /// <param name="rec">record completo pesate Gomba</param>
        /// <param name="isIN">Indica se deve formattare i dati tipo IN (true) o OUT (false)</param>
        /// <returns></returns>
        private static string formatPesata(WeightRec rec)
        {
            string currVal = $"RM: {rec.RM} | ";
            try
            {
                if (rec.isIn)
                {
                    currVal += $"IN | ";
                }
                else
                {
                    currVal += $"OUT | ";
                }
                currVal += $"{rec.DtEvent:yyyy-MM-dd HH:mm:ss} | {rec.weight:N2} kg";
            }
            catch
            { }
            currVal += formatCode(rec.cod1);
            currVal += formatCode(rec.cod2);
            currVal += formatCode(rec.cod3);
            currVal += formatCode(rec.cod4);
            currVal += formatCode(rec.cod5);
            currVal += formatCode(rec.cod6);
            return currVal;
        }

        private void AppendPesata(WeightRec newRec)
        {
            var tmpPesate = listPesateArchivio;
            tmpPesate.Add(newRec);
            listPesateArchivio = tmpPesate;
        }

        /// <summary>
        /// Calcola numero pesate da inviare confrontando lista curr ed arch
        /// </summary>
        private int num2send()
        {
            int answ = 0;
            if (listPesateCurr.Count > 0)
            {
                var listaArch = listPesateArchivio.OrderByDescending(x => x.DtEvent).ToList();
                // se NON ne ho in archivio --> tutte!
                if (listaArch.Count == 0)
                {
                    answ = listPesateCurr.Count;
                }
                // altrimenti solo nuove
                else
                {
                    // prendo prima della lista pesate archiviate = più recente come dt da cui partire...
                    DateTime dtRif = listaArch.FirstOrDefault().DtEvent;
                    answ = listPesateCurr
                                .Where(x => x.DtEvent > dtRif)
                                .Count();
                }
            }
            return answ;
        }

        #endregion Private Methods
    }
}