using SteamWare;
using System;

namespace GMW_data
{
  /// <summary>
  /// classe gestione operazioni con terminalino
  /// </summary>
  public class TermClass
  {
    #region area table adapters

    /// <summary>
    /// init dei table adapters
    /// </summary>
    protected void initTA()
    {
      // istanzio oggetto
    }
    /// <summary>
    /// effettua setup dei connection strings da web.config delal singola applicazione
    /// </summary>
    protected virtual void setupConnectionStringBase()
    {
      // connections del db
    }

    #endregion

    #region Inizializzazione

    protected TermClass()
    {
      // init oggetto
      initTA();
      setupConnectionStringBase();
    }

    /// <summary>
    /// oggetto static per fare chiamate sul magazzino
    /// </summary>
    public static TermClass Ter = new TermClass();

    #endregion

    #region metodi protected

#if false
        /// <summary>
        /// aggiunge le righe liste di prelievo necessarie a soddisfare la richiesta in logica FIFO dato un elenco di cartellini, la qta totale da allocare e la lista attuale
        /// </summary>
        /// <param name="QtaTot"></param>
        /// <param name="codListaAttuale"></param>
        /// <param name="tabellaElencoCartellini"></param>
        private void allocaRigheListaPrelievo(decimal QtaTot, string codListaAttuale, DS_magazzino.ElencoCartelliniDataTable tabellaElencoCartellini)
        {
            //ricavo il valore UDC della riga del più vecchio
            string udcAttuale;
            bool qtaOk = false;
            bool dataFinished = false;
            int progrUdc = 0;
            int numUdcDisponibili = tabellaElencoCartellini.Rows.Count;
            // contiene la quantità della riga attuale
            decimal qtaRiga;
            // somma progressiva della qta allocata - calcolo da db!
            decimal qtaAllocata = taElencoListePrelievo.getByCodLista(codListaAttuale)[0].Prelevato;
            //ciclo WHILE per lo riempimento FIFO con UDC secondo richiesta a partire da elenco fornito
            while (!qtaOk && !dataFinished)
            {
                /*
                 * crea una riga in righelistaprelievo passando come valori 
                 * il codlista attuale ricavato da sopr
                 * l'UDC dal primo della tabella getOlderUDC 
                 * 
                 * 
                 * recupero quantità dalla riga corrente;
                 * 
                 * imposto proposto a 1;
                 * imposto prelevato 0;
                 * taRighelistePreliveo.Insert;
                 * 
                 * qtaAllocata = qtaAllocata + Qta di questa riga (riuso il valore della colonna QTA
                 * tabella[contatore]; contatore++; 
                 * qtaOk = (qtaAllocata >= qtaRichiesta)
                 * dataFinished = (contatore >= numRighe);
                 * 
                 * */
                // ricavo la riga più vecchia
                qtaRiga = tabellaElencoCartellini[progrUdc].Qta;
                udcAttuale = tabellaElencoCartellini[progrUdc].UDC;
                // eseguo query di insert
                taRigheListePrelievo.Insert(codListaAttuale, udcAttuale, qtaRiga, true, false);

                //incremento qta allocata
                qtaAllocata = (qtaAllocata + qtaRiga);
                //incremento contatore
                progrUdc++;

                // verifico le condizioni, false se non cambia nulla true se cambia e si esce dal while
                qtaOk = (qtaAllocata >= QtaTot);
                dataFinished = (progrUdc >= numUdcDisponibili);
            }
        } 
#endif

    #endregion

    #region Metodi esposti

    /// <summary>
    /// Verifica il login utente andando a controllare il CodSoggetto da RilPro e salvando in sessione un oggetto user_std x l'utente corrispondente al cod soggetto secondo la tab soggetti2utente
    /// </summary>
    /// <param name="CodSoggetto"></param>
    /// <returns>tipo di errore codificato</returns>
    public esitoLoginTerm doUserLogin(string CodSoggetto)
    {
      esitoLoginTerm answ = esitoLoginTerm.errore;
      try
      {
        // verifico che il cod operatore passato sia valido per RilPro.AnagOperatori e Soggetti2Utente
        int trovatiAnagOp = DataProxy.obj.taAnagOperatore.getByCodSoggetto(CodSoggetto).Rows.Count;
        int trovatiS2U = DataProxy.obj.taSogg2Oper.getByCodSoggetto(CodSoggetto).Rows.Count;
        if (trovatiAnagOp == 1)
        {
          if (trovatiS2U == 1)
          {
            // è ok, proseguo facendo avvio user
            DS_Applicazione.Soggetti2UtenteRow rigaOp = DataProxy.obj.taSogg2Oper.getByCodSoggetto(CodSoggetto)[0];
            // inizializzo utente con dati operatore
            user_std _utente = new user_std();
            user_std.UtSn.isForcedUser = true;
            bool fatto = _utente.startUpUtente(rigaOp.DOMINIO, rigaOp.USER_NAME);
            if (fatto)
            {
              answ = esitoLoginTerm.ok;
              logger.lg.scriviLog(String.Format("Forced user identity ok: logged as \t {0}\\{1}", user_std.UtSn.dominio, user_std.UtSn.utente), tipoLog.STARTUP);
            }
          }
          else
          {
            logger.lg.scriviLog(string.Format("Attenzione: trovati {0} utenti in RilPro AnagOperatori e {1} utenti in Soggetti2Utente per il CodSoggetto {2}: login impossibile!", trovatiAnagOp, trovatiS2U, CodSoggetto), tipoLog.ERROR);
            answ = esitoLoginTerm.errore_noUser;
          }
        }
        else
        {
          logger.lg.scriviLog(string.Format("Attenzione: trovati {0} utenti in RilPro AnagOperatori e {1} utenti in Soggetti2Utente per il CodSoggetto {2}: login impossibile!", trovatiAnagOp, trovatiS2U, CodSoggetto), tipoLog.ERROR);
          answ = esitoLoginTerm.errore_noCodSogg;
        }
      }
      catch (Exception e)
      {
        logger.lg.scriviLog(string.Format("Errore in TermClass.doUserLogin per il CodSoggetto {0}: eccezione {1}", CodSoggetto, e), tipoLog.FATAL);
      }
      return answ;
    }
    /// <summary>
    /// verifica se il codice barcode letto sia un particolare con codice tipo "P"
    /// </summary>
    /// <param name="barcodeIN"></param>
    /// <returns></returns>
    public bool isParticolare(string barcodeIN)
    {
      bool answ = false;
      try
      {
        answ = utils.obj.taSelParticolari.getByConditioValue(barcodeIN, "P").Rows.Count == 1;
      }
      catch
      { }
      return answ;
    }
    /// <summary>
    /// verifica se il codice barcode letto sia un anima
    /// </summary>
    /// <param name="valore"></param>
    /// <returns></returns>
    public bool isAnima(string valore)
    {
      bool answ = false;
      try
      {
        answ = utils.obj.taSelParticolari.getByConditioValue(valore, "A").Rows.Count == 1;
      }
      catch
      { }
      return answ;
    }
    /// <summary>
    /// verifica se il codice barcode letto sia 
    /// - FinitoLiquidi
    /// - NON consumato ( maggiore di 0 )
    /// - NON spedito ( minore di 200 )
    /// </summary>
    /// <param name="UDC">UDC da verificare</param>
    /// <returns></returns>
    public bool isFinitoLiquidiOK(string UDC)
    {
      bool answ = false;
      try
      {
        answ = DataProxy.obj.taCartellini.getByUdcStatoPosiz(UDC, "FinLiq", 1, 199).Rows.Count == 1;
      }
      catch
      { }
      return answ;
    }
    /// <summary>
    /// Hash Redis contenente i dati MP di una specifico TYPE (es StatusMacchina, StateMachineIngressi, ...)
    /// </summary>
    /// <param name="dataType"></param>
    /// <returns></returns>
    public static string mHash(string dataType)
    {
      return memLayer.ML.redHash(dataType);
    }
    /// <summary>
    /// Hash dati DECODIFICA BCode
    /// </summary>
    /// <param name="idxMacchina"></param>
    /// <returns></returns>  
    public static string BCDecodeHash(string idxMacchina)
    {
      return mHash(string.Format("BCDecode:{0}", idxMacchina));
    }
    /// <summary>
    /// verifica il codice barcode letto e restituisce il tipo di valore corrisponente
    /// </summary>
    /// <param name="barcodeIN"></param>
    /// <returns></returns>
    public tipoCodiceBarcode riconosciBarcode(string barcodeIN)
    {
      tipoCodiceBarcode answ = tipoCodiceBarcode.ND;
      if (barcodeIN != "")
      {
        // cerco in sessione redis il valore con quella chiave...
        string rCall = "";
        bool dataFound = false;
        try
        {
          rCall = memLayer.ML.getRSV(BCDecodeHash(barcodeIN));
          if (rCall != "" && rCall != null)
          {
            dataFound = true;
          }
        }
        catch
        { }
        if (dataFound && memLayer.ML.CRB("EnableDecodeCache"))
        {
          tipoCodiceBarcode.TryParse(rCall, out answ);
        }
        else
        {
          // salvo richiesta barcode in cache..
          memLayer.ML.setCacheVal("lastBarcodeIN", barcodeIN);
          // cerco se sia un particolare...
          if (utils.obj.taSelParticolari.getByConditioValue(barcodeIN, "*").Rows.Count == 1)
          {
            answ = tipoCodiceBarcode.Particolare;
          }
          // se non lo è continuo
          if (answ == tipoCodiceBarcode.ND)
          {
            switch (barcodeIN.Substring(0, 1))
            {
              case "O":
                answ = tipoCodiceBarcode.Operatore;
                break;
              case "K":
                // se è "KITAN" allora è tipo KIT...
                if (barcodeIN.Substring(0, 5) == "KITAN")
                {
                  answ = tipoCodiceBarcode.KitAnime;
                }
                else
                {
                  answ = tipoCodiceBarcode.ListaPrelievo;
                }
                break;
              //case "P":
              //case "A":
              //    answ = tipoCodiceBarcode.Particolare;
              //    break;
              case "U":
                answ = tipoCodiceBarcode.UDC;
                break;
              case "S":
                answ = tipoCodiceBarcode.Cella;
                break;
              default:
                // cerco se la stringa intera abbia un match con le celle...
                if (MagClass.magazzino.taCelle.getByCodCella(barcodeIN).Rows.Count == 1)
                {
                  answ = tipoCodiceBarcode.Cella;
                }
                // 2018.07.04 aggiunta decodifica magClass x AL...
                else
                {
                  answ = MagClass.tipoBCode_L4(barcodeIN);
                }
                break;
            }
          }
          // salvo in cache decodifica
          int BCDecodeDurationSec = memLayer.ML.CRI("BCDecodeDurationSec") > 0 ? memLayer.ML.CRI("BCDecodeDurationSec") : 30;
          memLayer.ML.setRSV(BCDecodeHash(barcodeIN), answ.ToString(), BCDecodeDurationSec);
        }
      }
      return answ;
    }
    /// <summary>
    /// effettua il reset di tutti i valori in sessione salvati a valle della scansione di un barcode
    /// </summary>
    /// <param name="resetUdc">true/false se resettare UDC selezionato</param>
    /// <param name="resetCella">true/false se resettare Cella selezionata</param>
    /// <param name="resetPArticolare">true/false se resettare Particolare selezionato</param>
    public void resetScanBarcode(bool resetUdc, bool resetCella, bool resetParticolare)
    {
      if (resetUdc)
      {
        memLayer.ML.emptySessionVal("UDC_sel");
      }
      if (resetCella)
      {
        memLayer.ML.emptySessionVal("IdxCella_sel");
        memLayer.ML.emptySessionVal("codCella_sel");
      }
      if (resetParticolare)
      {
        memLayer.ML.emptySessionVal("Particolare_sel");
      }
    }

    #endregion
  }
}

/// <summary>
/// Classe per decodifica barcode gestita tramite REDIS session values
/// </summary>
public class BCDecode
{
  /// <summary>
  /// init classe
  /// </summary>
  protected BCDecode()
  {
  }

  /// <summary>
  /// oggetto static per fare chiamate sul magazzino
  /// </summary>
  public static BCDecode obj = new BCDecode();
  /// <summary>
  /// Decodifica il barcode e ne determina il tipo, tramite lista decodifica REDIS oppure tramite controllo DB (e poi salva in redis x un tempo predefinito)
  /// </summary>
  /// <param name="BCode"></param>
  /// <returns></returns>
  public tipoCodiceBarcode getType(string BCode)
  {
    tipoCodiceBarcode answ = tipoCodiceBarcode.ND;
    // durata validità cache REDIS x decodifica
    int BCDecodeDurationSec = memLayer.ML.CRI("BCDecodeDurationSec");
    if (BCDecodeDurationSec <= 0)
    {
      BCDecodeDurationSec = 30;
    }
    // cerco nella cache REDIS
    return answ;
  }
}

/// <summary>
/// definisce i tipi di codice che il barcode può leggere
/// </summary>
public enum tipoCodiceBarcode
{
  /// <summary>
  /// Tipo non riconosciuto
  /// </summary>
  ND,
  /// <summary>
  /// [O] - il barcode rappresenta un codice operatore 
  /// </summary>
  Operatore,
  /// <summary>
  /// [K] - il barcode rappresenta una lista di prelievo
  /// </summary>
  ListaPrelievo,
  /// <summary>
  /// [U] - il barcode rappresenta un UDC
  /// </summary>
  UDC,
  /// <summary>
  /// il barcode rappresenta un particolare
  /// </summary>
  Particolare,
  /// <summary>
  /// Cella [S]
  /// </summary>
  Cella,
  /// <summary>
  /// codice gitterbox
  /// </summary>
  Gitterbox,
  /// <summary>
  /// Codice PartNumber come calcolato e valido sottoinsieme di codice datamatrix (BMW, Magneti Marelli, Porsche, ...) 
  /// </summary>
  DataMatrixDecodificato,
  /// <summary>
  /// Codice datamatrix
  /// </summary>
  DataMatrixTrovato,
  /// <summary>
  /// codice che indica un comando (prefisso da web.config)
  /// </summary>
  Comando,
  /// <summary>
  /// Assieme Logico
  /// </summary>
  AL,
  /// <summary>
  /// Trattamento Termico
  /// </summary>
  TT,
  /// <summary>
  /// Codice di imballo
  /// </summary>
  Imballo,
  /// <summary>
  /// Marcatore DataOra
  /// </summary>
  DateTime,
  /// <summary>
  /// Marcatore BarCodeCMD
  /// </summary>
  BarCodeCMD,
  /// <summary>
  /// Marcatore DataOra e Linea
  /// </summary>
  DateTimeLine,
  /// <summary>
  /// Tipologia di KIT ANIME
  /// </summary>
  KitAnime
}
/// <summary>
/// elenco degli esiti per una sessione di login da terminalino
/// </summary>
public enum esitoLoginTerm
{
  /// <summary>
  /// tutto ok, come true
  /// </summary>
  ok,
  /// <summary>
  /// non è andata, errore generico
  /// </summary>
  errore,
  /// <summary>
  /// errore x mancanza record in tab operatori di RilPro x CodSoggetto
  /// </summary>
  errore_noCodSogg,
  /// <summary>
  /// errore mancanza username corrisponende all'operatore il cui cod soggetto è stato passato
  /// </summary>
  errore_noUser
}