/* 
* Copyright 2016 Agencia Estatal de Administración Tibutaria
*
* Licencia con arreglo a la EUPL, Versión 1.1 o –en cuanto
* sean aprobadas por la Comisión Europea– versiones
* posteriores de la EUPL (la «Licencia»);
* Solo podrá usarse esta obra si se respeta la Licencia.
* Puede obtenerse una copia de la Licencia en:
*  
* https://joinup.ec.europa.eu/software/page/eupl
*  
* Salvo cuando lo exija la legislación aplicable o se acuerde
* por escrito, el programa distribuido con arreglo a la
* Licencia se distribuye «TAL CUAL», SIN GARANTÍAS NI CONDICIONES
* DE NINGÚN TIPO, ni expresasni implícitas.
*
* Véase la Licencia en el idioma concreto que rige los permisos y 
* limitaciones que establece la Licencia.
*/ 

package servidor.datos;

import java.sql.*;
import java.util.*;
import java.util.logging.Level;
import servidor.Configuracion;
import servidor.datos.base.*;
import servidor.utiles.*;

public class Resucitador {

   ArrayList<RegistroCandidatos> lista = new ArrayList<RegistroCandidatos>();
   TablaColas colas;
   public boolean enRecarga = false;
   private LogGenerico logResucitables = new LogGenerico("logs", Global.main.logResucitables, "Registros resucitables");        
   public Resucitador(TablaColas colas) {
      this.colas = colas;
   }

   public void vaciar() {
      lista.clear();
   }

   private boolean estaEnLista(RegistroCandidatos reg) {
      for (RegistroCandidatos r : lista) {
         if (r.getId() == reg.getId()) {
            return true;
         }
      }
      return false;
   }
  
   private boolean esResucitable(RegistroCandidatos reg) {
      try {
         // si ya está o ha estado en la lista no vale
         if (reg.resucitable) {
            return false;
         }
         // esto no debería ocurrir nunca
         if (!lista.contains(reg) && estaEnLista(reg)) {
            return false;
         }
         // si no es cita previa no vale
         RegistroColas rc = colas.buscarCola(reg.getCola());
         if (rc != null && !rc.isCitaPrevia()) {
            return false;
         }
         // es un registro reenviado, no vale
         if(reg.getCodigoGestor().startsWith("#")) {            
            return false;
         }
         // si ya pasó su hora de cita no vale
         if (Fecha.ahora().after(reg.getHoraCita())) {
            return false;
         }
         // si no tiene ticket debe ser un vinculado, no deberia llegar aqui, y no vale
         if (reg.getNumeroTicket().length() < 2) {
            return false;
         }
         String estado = reg.getEstado();
         // si el estado es D o A SI vale
         if (estado.equals("D")) {    //  retirado tentativamente || estado.equals("A")) {
            return true;
         }
         if (estado.equals("S")) {
            long segundos = (reg.getHoraFinalizado().getTime() - reg.getHoraPresente2().getTime()) / 1000;
            if (segundos < 6) {
               segundos = (reg.getHoraPresente2().getTime() - reg.getHoraAtendido().getTime()) / 1000;
               if (segundos < 240) {
                  return true;
               }
            }
         }
      } catch (Exception exc) {
         servidor.ServidorMain.logException("Error en calculo de resucitables para el tique " + reg.getId(), exc);
      }
      return false;
   }

   public boolean add(RegistroCandidatos reg) {
      return add(reg, true);
   }
   
   public boolean add(RegistroCandidatos reg, boolean log) {
      if (reg == null) {
         return false;
      }
      if (esResucitable(reg)) {
         lista.add(reg);
         reg.resucitable = true;
         if(log) {
            System.out.println(mensajeVisor(true, reg));
            String lineaLog = Fecha.formatoHoraHMS(new java.util.Date()) + "|" + reg.toString();
            logResucitables.escribir(lineaLog);
         }
         return true;
      }
      return false;
   }

   public void quitar(RegistroCandidatos reg) {
      if(!enRecarga) {
         if(lista.remove(reg)) {
            System.out.println(mensajeVisor(false, reg));
         }
      }
   }
   
   public String mensajeVisor(boolean cargado, RegistroCandidatos reg) {
      StringBuilder sb = new StringBuilder();
      if(cargado) {
         sb.append("Cargado en");
      } else {
         sb.append("Eliminado del");
      }
      sb.append(" resucitador ").append(reg.getNif()).append(" ").append(reg.getNumeroTicket());
      sb.append("  (pend. ").append(lista.size()).append(")");
      return sb.toString();
   }

   public ArrayList<RegistroCandidatos> resucitables() {
      try {
         if (!enRecarga && !lista.isEmpty()) {
            ArrayList<RegistroCandidatos> listaDev = new ArrayList<>();
            Timestamp ahora = Fecha.ahora();
            for(RegistroCandidatos rc : lista) {
               Timestamp primera = rc.getHoraCita();
               if (ahora.after(primera)) {
                  long segundos = (ahora.getTime() - primera.getTime()) / 1000;
                  if(segundos > 120 && Configuracion.getConfiguracion().modoVerboso) {
                     System.err.println("Atención: el siguiente registro ha estado mas de 2 minutos pendiente de resucitar: ");
                     System.err.println(rc.toStringResu());
                  }
                  listaDev.add(rc);
               }
            }
            if(listaDev.size() > 0) {
               for(RegistroCandidatos rc : listaDev) {
                  eliminarDeLista(rc);
               }
               return listaDev;
            }
         }
      } catch(Exception exc) {
         servidor.ServidorMain.log.log(Level.WARNING, "Excepcion al obtener lista de resucitables:{0}", exc.getMessage());
      }
      return null;
   }

   private void eliminarDeLista(RegistroCandidatos rc) {
      if(!lista.remove(rc)) {
         for(RegistroCandidatos rcb : lista) {
            if(rcb.getNumeroTicket().equals(rc.getNumeroTicket())) {
               if(Configuracion.getConfiguracion().modoVerboso) {
                  System.err.println("ATENCIÓN: ");
                  System.err.println("  En lista de resucitables: " + rcb.getId() + " - " + rcb.getNumeroTicket());
                  System.err.println("  Buscado: " + rc.getId() + " - " + rc.getNumeroTicket());
               }
               lista.remove(rcb);
               return;
            }
         }
      }
   }
   
   public int numeroPendientes() {
      return lista.size();
   }

   public void listar() {
      ArrayList<String> res = pendientes();
      if (res.isEmpty()) {
         System.out.println(" ** No hay candidatos pendientes de resucitar **");
      } else {
         System.out.println(" ** " + res.size() +" candidatos resucitables: ");
         for (String s : res) {
            System.out.println(s);
         }
      }
   }

   private ArrayList<String> pendientes() {
      ArrayList<String> al = new ArrayList<>();
      for (RegistroCandidatos rc : lista) {
         al.add(rc.toStringResu());
      }
      return al;
   }
}
