using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IOB_UT
{
  public class RedisIobCache
  {
    #region gestione valori in RedisCache

    /// <summary>
    /// Restituisce un pò di info sul server redis connesso
    /// </summary>
    /// <returns></returns>
    public string getRedisInfoData()
    {
      string answ = "";
      StringBuilder sb = new StringBuilder();
      try
      {
        sb.AppendLine($"Configuration: {connRedis.Configuration}");
        sb.AppendLine($"Connected: {connRedis.IsConnected}");
        sb.AppendLine($"ClientName: {connRedis.ClientName}");
        sb.AppendLine($"Total Ops: {connRedis.OperationCount}");
        sb.AppendLine($"Status: {connRedis.GetStatus()}");
        answ = sb.ToString();
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"getRedisInfoData {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Oggetto currentDb locale
    /// </summary>
    private IDatabase _currDB { get; set; }
    /// <summary>
    /// Oggetto DB REDIS corrente
    /// </summary>
    public IDatabase cache //currDB
    {
      get
      {
        IDatabase answ;
        // se già valorizzato uso oggetto private...
        if (_currDB != null)
        {
          answ = _currDB;
        }
        else
        {
          // init DB (sullo 0)
          answ = connRedis.GetDatabase();
          // gestione override...
          if (baseUtils.CRI("redisDb") >= 0)
          {
            // in questo caso uso il DB configurato in app.config...
            answ = connRedis.GetDatabase(baseUtils.CRI("redisDb"));
          }
          _currDB = answ;
        }
        // restituisco oggetto DB
        return answ;
      }
    }
    /// <summary>
    /// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto...
    /// </summary>
    public string redHash(string keyName)
    {
      keyName = keyName.Replace("\\", "_");
      string answ = keyName;
      try
      {
        answ = string.Format($"{baseUtils.CRS("appName")}:{keyName}");
      }
      catch(Exception exc)
      {
        Logging.Instance.Error($"redHash {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Serializzazione di un oggetto generico
    /// </summary>
    /// <param name="origVal"></param>
    /// <returns></returns>
    public string serializeVal(object origVal)
    {
      string answ = "";
      try
      {
        answ = JsonConvert.SerializeObject(origVal);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"serializeVal {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Deserializzazione di un valore string in oggetto generico
    /// </summary>
    /// <param name="serVal"></param>
    /// <returns></returns>
    public object deserializeVal(string serVal)
    {
      object answ = "";
      try
      {
        answ = JsonConvert.DeserializeObject(serVal);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"deserializeVal {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Connessione lazy a redis...
    /// </summary>
    private Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
    {
      string RedisConn = baseUtils.CRS("RedisConn");
      if (string.IsNullOrEmpty(RedisConn))
      {
        RedisConn = "localhost,abortConnect=false,ssl=false";
      }

      return ConnectionMultiplexer.Connect(RedisConn);
    });
    /// <summary>
    /// Connessione lazy a redis...
    /// </summary>
    private Lazy<ConnectionMultiplexer> lazyConnectionAdmin = new Lazy<ConnectionMultiplexer>(() =>
    {
      string RedisConnAdmin = baseUtils.CRS("RedisConnAdmin");
      if (string.IsNullOrEmpty(RedisConnAdmin))
      {
        RedisConnAdmin = "localhost,abortConnect=false,ssl=false,allowAdmin=true";
      }

      return ConnectionMultiplexer.Connect(RedisConnAdmin);
    });
    /// <summary>
    /// Oggetto statico connessione redis
    /// </summary>
    public ConnectionMultiplexer connRedis
    {
      get
      {
        return lazyConnection.Value;
      }
    }
    /// <summary>
    /// Oggetto statico connessione redis
    /// </summary>
    public ConnectionMultiplexer connRedisAdmin
    {
      get
      {
        return lazyConnectionAdmin.Value;
      }
    }
    /// <summary>
    /// Restituisce info dei server connessi...
    /// </summary>
    /// <returns></returns>
    public IServer[] redServInfo()
    {
      IServer[] answ = new IServer[1];
      try
      {
        answ = new IServer[connRedisAdmin.GetEndPoints().Length];
        int i = 0;
        foreach (var ep in connRedisAdmin.GetEndPoints())
        {
          var server = connRedisAdmin.GetServer(ep);
          answ[i] = server;
          i++;
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redServInfo {exc}"); 
      }
      return answ;
    }
    /// <summary>
    /// Restituisce una chiave salvata in RedisCache
    /// </summary>
    /// <param name="chiave"></param>
    /// <returns></returns>
    public string getRSV(string chiave)
    {
      string answ = "";
      try
      {
        answ = cache.StringGet(chiave);
      }
      catch (Exception exc)
      {
        Logging.Instance.Info($"getRSV {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Salva una chiave in RedisCache
    /// </summary>
    /// <param name="chiave"></param>
    /// <param name="valore"></param>
    /// <returns></returns>
    public bool setRSV(string chiave, string valore)
    {
      bool answ = false;
      try
      {
        cache.StringSet(chiave, valore);
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"setRSV {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Salva una chiave in RedisCache
    /// </summary>
    /// <param name="chiave"></param>
    /// <param name="valore"></param>
    /// <param name="TTL_sec">in secondi</param>
    /// <returns></returns>
    public bool setRSV(string chiave, string valore, int TTL_sec)
    {
      bool answ = false;
      try
      {
        TimeSpan expT = new TimeSpan(0, 0, TTL_sec);
        // salvo con expyry...
        cache.StringSet(chiave, valore, expT);
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"setRSV {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Incrementa un contatore in Redis
    /// </summary>
    /// <param name="chiave"></param>
    /// <returns></returns>
    public long setRCntI(string chiave)
    {
      long answ = 0;
      try
      {
        answ = cache.StringIncrement(chiave, 1);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"setRCntI {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Decrementa un contatore in Redis
    /// </summary>
    /// <param name="chiave"></param>
    /// <returns></returns>
    public long setRCntD(string chiave)
    {
      long answ = 0;
      try
      {
        answ = cache.StringDecrement(chiave, 1);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"setRCntD {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Restituisce una chiave COUNTER in RedisCache
    /// </summary>
    /// <param name="chiave"></param>
    /// <returns></returns>
    public int getRCnt(string chiave)
    {
      int answInt = 0;
      string answ = "";
      try
      {
        answ = cache.StringGet(chiave);
        answInt = Convert.ToInt32(answ);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"getRCnt {exc}");
      }
      return answInt;
    }
    /// <summary>
    /// Resetta (elimina) un contatore in Redis
    /// </summary>
    /// <param name="chiave"></param>
    /// <returns></returns>
    public bool resetRCnt(string chiave)
    {
      bool answ = false;
      try
      {
        answ = cache.KeyDelete(chiave);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"resetRCnt {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Restituisce un set KVP (Key Value Pair) salvati in RedisCache
    /// </summary>
    /// <param name="chiavi"></param>
    /// <returns></returns>
    public RedisValue[] getRKeys(RedisKey[] chiavi)
    {
      RedisValue[] answ = null;
      try
      {
        answ = cache.StringGet(chiavi);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"getRKeys {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Salva  un set KVP (Key Value Pair) in RedisCache
    /// </summary>
    /// <param name="valori">Set KVP chiave-valore da salvare</param>
    /// <returns></returns>
    public bool setRKeys(KeyValuePair<RedisKey, RedisValue>[] valori)
    {
      bool answ = false;
      try
      {
        cache.StringSet(valori);
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"setRKeys {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Verifica se ci siano valori nella KEY indicata...
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool redKeyPresent(RedisKey key)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        answ = cache.KeyExists(key);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redKeyPresent {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Verifica se ci siano valori nella KEY indicata (string)
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool redKeyPresentSz(string key)
    {
      bool answ = false;
      try
      {
        RedisKey chiave = key;
        answ = redKeyPresent(chiave);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redKeyPresentSz {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Verifica se ci siano valori nella hash indicata...
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool redHashPresent(RedisKey key)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        answ = cache.HashGetAll(key).Length > 0;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redHashPresent {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Verifica se ci siano valori nella hash indicata (string)
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool redHashPresentSz(string key)
    {
      bool answ = false;
      try
      {
        RedisKey chiave = key;
        answ = redHashPresent(chiave);
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redHashPresentSz {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Recupera tutti i valori dalla hash
    /// </summary>
    /// <param name="hashKey"></param>
    /// <returns></returns>
    public KeyValuePair<string, string>[] redGetHash(string hashKey)
    {
      KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[1];
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        HashEntry[] valori = cache.HashGetAll(chiave);
        answ = new KeyValuePair<string, string>[valori.Length];
        int i = 0;
        foreach (HashEntry item in valori)
        {
          answ[i] = new KeyValuePair<string, string>(item.Name, item.Value);
          i++;
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redGetHash {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Recupera tutti i valori dalla hash in formato Dictionary
    /// </summary>
    /// <param name="hashKey"></param>
    /// <returns></returns>
    public Dictionary<string, string> redGetHashDict(string hashKey)
    {
      Dictionary<string, string> answ = new Dictionary<string, string>();
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        HashEntry[] valori = cache.HashGetAll(chiave);
        foreach (HashEntry item in valori)
        {
          answ.Add(item.Name, item.Value);
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redGetHashDict {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Recupera UN SINGOLO VALORE dalla hash per un dato field
    /// </summary>
    /// <param name="hashKey"></param>
    /// <param name="hashField"></param>
    /// <returns></returns>
    public string redGetHashField(string hashKey, string hashField)
    {
      string answ = "";
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        RedisValue campo = hashField;
        RedisValue valOut = cache.HashGet(chiave, campo);
        answ = valOut.ToString();
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redGetHashField {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Salvataggio di una hash di valori
    /// </summary> 
    /// <param name="hashKey">chiave</param>
    /// <param name="hashFields">valori</param>
    /// <returns></returns>
    public bool redSaveHash(string hashKey, KeyValuePair<string, string>[] hashFields)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        HashEntry[] valori = new HashEntry[hashFields.Length];
        int i = 0;
        foreach (KeyValuePair<string, string> kvp in hashFields)
        {
          valori[i] = new HashEntry(kvp.Key, kvp.Value);
          i++;
        }
        cache.HashSet(chiave, valori);
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redSaveHash {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Salvataggio di una hash di valori in formato Dictionary
    /// </summary> 
    /// <param name="hashKey">chiave</param>
    /// <param name="hashFields">valori</param>
    /// <returns></returns>
    public bool redSaveHashDict(string hashKey, Dictionary<string, string> hashFields)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        HashEntry[] valori = new HashEntry[hashFields.Count];
        int i = 0;
        foreach (KeyValuePair<string, string> kvp in hashFields)
        {
          valori[i] = new HashEntry(kvp.Key, kvp.Value);
          i++;
        }
        cache.HashSet(chiave, valori);
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redSaveHashDict {exc}");
      }
      return answ;
    }

    /// <summary>
    /// Salvataggio di una hash di valori
    /// </summary> 
    /// <param name="hashKey">chiave</param>
    /// <param name="hashListKVP">valori come lista KVP</param>
    /// <returns></returns>
    public bool redSaveHashList(string hashKey, List<KeyValuePair<string, string>> hashListKVP)
    {
      bool answ = false;
      if (connRedis.IsConnected)
      {
        // cerco se ci sia valore in redis...
        IDatabase cache = connRedis.GetDatabase();
        try
        {
          RedisKey chiave = hashKey;
          HashEntry[] valori = new HashEntry[hashListKVP.Count];
          int i = 0;
          foreach (KeyValuePair<string, string> kvp in hashListKVP)
          {
            valori[i] = new HashEntry(kvp.Key, kvp.Value);
            i++;
          }
          cache.HashSet(chiave, valori);
          answ = true;
        }
        catch (Exception exc)
        {
          Logging.Instance.Error($"redSaveHashList {exc}");
        }
      }
      return answ;
    }
    /// <summary>
    /// Salvataggio di una hash di valori
    /// </summary> 
    /// <param name="hashKey">chiave</param>
    /// <param name="hashFields">valori</param>
    /// <param name="expireSeconds">scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)</param>
    /// <returns></returns>
    public bool redSaveHash(string hashKey, KeyValuePair<string, string>[] hashFields, double expireSeconds = -1)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        answ = redSaveHash(hashKey, hashFields);
        if (expireSeconds > 0)
        {
          cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds));
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redSaveHash {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Salvataggio di una hash di valori in formato Dictionary
    /// </summary> 
    /// <param name="hashKey">chiave</param>
    /// <param name="hashFields">valori</param>
    /// <param name="expireSeconds">scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)</param>
    /// <returns></returns>
    public bool redSaveHashDict(string hashKey, Dictionary<string, string> hashFields, double expireSeconds = -1)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = hashKey;
        answ = redSaveHashDict(hashKey, hashFields);
        if (expireSeconds > 0)
        {
          cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds));
        }
        //answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redSaveHashDict {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Elimina una key (hash, string)
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public bool redDelKey(string key)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      try
      {
        RedisKey chiave = key;
        cache.KeyDelete(chiave);
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redDelKey {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Flush completo cache redis
    /// </summary>
    /// <param name="keyPattern">** = tutti</param>
    /// <returns></returns>
    public bool redFlushKey(string keyPattern)
    {
      bool answ = false;
      // cerco se ci sia valore in redis...
      // se vuoto = ALL...
      keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern;
      try
      {
        foreach (var ep in connRedis.GetEndPoints())
        {
          var server = connRedis.GetServer(ep);
          var keys = server.Keys(database: baseUtils.CRI("redisDb"), pattern: $"{keyPattern}*");
          foreach (var key in keys)
          {
            cache.KeyDelete(key);
          }
        }
        answ = true;
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redFlushKey {exc}");
      }
      return answ;
    }
    /// <summary>
    /// Conta num oggetti cache redis che rispondono a pattern
    /// </summary>
    /// <param name="keyPattern">** = tutti</param>
    /// <returns></returns>
    public int redCountKey(string keyPattern)
    {
      int answ = 0;
      // cerco se ci sia valore in redis...
      // se vuoto = ALL...
      keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern;
      try
      {
        foreach (var ep in connRedis.GetEndPoints())
        {
          var server = connRedis.GetServer(ep);
          foreach (var key in server.Keys(pattern: keyPattern))
          {
            answ++;
          }
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redCountKey {exc}");
      }
      return answ;
    }

    /// <summary>
    /// Restituisce numero record in Redis DB
    /// </summary>
    public long numRecRedis
    {
      get
      {
        long answ = 0;
        try
        {
          foreach (var ep in connRedis.GetEndPoints())
          {
            var server = connRedis.GetServer(ep);
            answ += server.DatabaseSize();
          }
        }
        catch (Exception exc)
        {
          Logging.Instance.Error($"numRecRedis {exc}");
        }
        return answ;
      }
    }
    /// <summary>
    /// Restituisce oggetti cache redis che rispondono a pattern
    /// </summary>
    /// <param name="keyPattern">** = tutti</param>
    /// <param name="orderBy">Tipo di ordinamento per kvp</param>
    /// <returns></returns>
    public List<KeyValuePair<string, int>> redGetCounterByKey(string keyPattern, kvpOrderBy orderBy)
    {
      int numAnsw = redCountKey(keyPattern);
      RedisKey[] chiavi = new RedisKey[numAnsw];
      List<KeyValuePair<string, int>> answ = new List<KeyValuePair<string, int>>();
      // se vuoto = ALL...
      keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern;

      // recupero in primis elenco chiavi
      try
      {
        int i = 0;
        foreach (var ep in connRedis.GetEndPoints())
        {
          var server = connRedis.GetServer(ep);
          foreach (var key in server.Keys(pattern: keyPattern))
          {
            chiavi[i] = key;
            i++;
          }
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redGetCounterByKey 01 {exc}");
      }
      // ora recupero valori!
      var valori = getRKeys(chiavi);
      int currVal = 0;
      // popolo rispsota
      try
      {
        for (int i = 0; i < numAnsw; i++)
        {
          Int32.TryParse(valori[i], out currVal);
          answ.Add(new KeyValuePair<string, int>(chiavi[i], currVal));
        }
      }
      catch (Exception exc)
      {
        Logging.Instance.Error($"redGetCounterByKey 02 {exc}");
      }
      // se richiesto riordino...
      switch (orderBy)
      {
        case kvpOrderBy.KeyAsc:
          answ.Sort(CompareKey);
          break;
        case kvpOrderBy.KeyDesc:
          answ.Sort(CompareKeyDesc);
          break;
        case kvpOrderBy.ValAsc:
          answ.Sort(CompareVal);
          break;
        case kvpOrderBy.ValDesc:
          answ.Sort(CompareValDesc);
          break;
        default:
          break;
      }
      return answ;
    }
    /// <summary>
    /// Effettua comaprazione x CHIAVE in KVP ASC
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    private int CompareKey(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
    {
      return x.Key.CompareTo(y.Key);
    }
    /// <summary>
    /// Effettua comaprazione x VALORE in KVP ASC
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public int CompareVal(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
    {
      return x.Value.CompareTo(y.Value);
    }
    /// <summary>
    /// Effettua comaprazione x CHIAVE in KVP DESC
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    private int CompareKeyDesc(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
    {
      return y.Key.CompareTo(x.Key);
    }
    /// <summary>
    /// Effettua comaprazione x VALORE in KVP DESC
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public int CompareValDesc(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
    {
      return y.Value.CompareTo(x.Value);
    }

    /// <summary>
    /// Tipologia di ordinamento x liste KVP
    /// </summary>
    public enum kvpOrderBy
    {
      /// <summary>
      /// Ordinamento ASCending per KEY
      /// </summary>
      KeyAsc,
      /// <summary>
      /// Ordinamento DESCending per KEY
      /// </summary>
      KeyDesc,
      /// <summary>
      /// Ordinamento ASCending per VAL
      /// </summary>
      ValAsc,
      /// <summary>
      /// Ordinamento DESCending per VAL
      /// </summary>
      ValDesc
    }



    #endregion

    #region gestione redis specifica

    /// <summary>
    /// Cod IOB
    /// </summary>
    protected string CodIob = "000";
    /// <summary>
    /// Hash redis x dati server
    /// </summary>
    protected string redServKey = "";
    /// <summary>
    /// Hash redis x dati IOB
    /// </summary>
    protected string redIobKey = "";
    /// <summary>
    /// init classe "implicita"
    /// </summary>
    /// <param name="codServer"></param>
    /// <param name="codIob"></param>
    public RedisIobCache()
    {
      // init dati di base...
      redServKey = redHash($"MP");
      redIobKey = redHash($"IOB:{CodIob}");
    }
    /// <summary>
    /// init classe gestione dati IOB su Redis
    /// </summary>
    /// <param name="codServer"></param>
    /// <param name="codIob"></param>
    public RedisIobCache(string codServer, string codIob)
    {
      // init dati di base...
      CodIob = codIob;
      redServKey = redHash($"MP");
      redIobKey = redHash($"IOB:{CodIob}");
      // init oggetti gestiti
      ServerMpStatus newSrvStatus = new ServerMpStatus()
      {
        IP = codServer,
        online = false
      };
      // init oggetto IOB
      IobWinStatus newIobStatus = new IobWinStatus()
      {
        CodIob = CodIob,
        online = false
      };
      // salvo in area REDIS
      servStatus = newSrvStatus;
      iobStatus = newIobStatus;
    }
    /// <summary>
    /// Accesso all'oggetto stato server da esterno
    /// </summary>
    public ServerMpStatus servStatus
    {
      get
      {
        ServerMpStatus answ = null;
        // cerco in REDIS
        string rawData = getRSV(redServKey);
        // se non ci fosse creo e salvo
        if (string.IsNullOrEmpty(rawData))
        {
          answ = new ServerMpStatus()
          {
            online = false
          };
          // salvo serializzando...
          rawData = JsonConvert.SerializeObject(answ);
          setRSV(redServKey, rawData);
        }
        else
        {
          // deserializzo
          answ = JsonConvert.DeserializeObject<ServerMpStatus>(rawData);
        }
        return answ;
      }
      set
      {
        string rawData = JsonConvert.SerializeObject(value);
        setRSV(redServKey, rawData);
      }
    }
    /// <summary>
    /// Accesso all'oggetto stato IOB da esterno
    /// </summary>
    public IobWinStatus iobStatus
    {
      get
      {
        IobWinStatus answ = null;
        // cerco in REDIS
        string rawData = getRSV(redIobKey);
        // se non ci fosse creo e salvo
        if (string.IsNullOrEmpty(rawData))
        {
          answ = new IobWinStatus()
          {
            CodIob = CodIob,
            online = false
          };
          // salvo serializzando...
          rawData = JsonConvert.SerializeObject(answ);
          setRSV(redIobKey, rawData);
        }
        else
        {
          // deserializzo
          answ = JsonConvert.DeserializeObject<IobWinStatus>(rawData);
        }
        return answ;
      }
      set
      {
        string rawData = JsonConvert.SerializeObject(value);
        setRSV(redIobKey, rawData);
      }
    }
    #endregion
  }
}
