/* 
* 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 gestor.datos;

import gestor.utiles.*;
import java.sql.Timestamp;
import java.util.*;
import gestor.utiles.Fecha;
import gestor.Configuracion;
import java.util.logging.Level;

public class TablaHuecos {

   protected final List<RegistroHuecos> datos;
   protected int posActual;
   private static TablaHuecos yo = null;
   public boolean cargada = false;
   Configuracion conf;
   HashMap<String, String> rangos;

   protected TablaHuecos() {
      datos = Collections.synchronizedList(new ArrayList<RegistroHuecos>());
      conf = Configuracion.instanciaUnica();
      rangos = new HashMap<String, String>();
   }

   public static TablaHuecos getTablaHuecos() {
      if (yo == null) {
         yo = new TablaHuecos();
      }
      return yo;
   }
    public void cargarRangoHuecos(String listarango) {
      rangos.clear();
      String[] lineas = Global.split(listarango, '|');
       for (String linea : lineas) {
           String[] campos = Global.split(linea, '=');
           if (campos.length == 2) {
               rangos.put(campos[0], campos[1]);
           }
       }
   }

   public String buscarRangoHuecos(String cola) {
      if (rangos.containsKey(cola)) {
         return rangos.get(cola);
      }
      return cola;
   }


   public void vaciar() {
      datos.clear();
      cargada = false;
   }

   public void ordenar() {
      Collections.sort(datos);
   }

   public int recordsCount() {
      return datos.size();
   }

   public void nuevoHueco(Timestamp hora, String cola, String turno) {
      RegistroHuecos r = new RegistroHuecos();
      r.horaCita = hora;
      r.turno = turno;
      r.cola = cola;
      datos.add(r);
   }

     public void eliminar(String msg) {
      String[] params = Global.split(msg, '|');
      try {
         String cola = params[0];
         String colaR =  buscarRangoHuecos(cola);
         Timestamp hora = Timestamp.valueOf(params[1]);
         int cuantos = Integer.parseInt(params[2]);
         synchronized (datos) {
            for (ListIterator<RegistroHuecos> it = datos.listIterator(); it.hasNext();) {
               RegistroHuecos rb = it.next();
               if (rb.cola.equals(colaR) && rb.horaCita.equals(hora)) {
                  it.remove();
                  cuantos--;
                  if (cuantos == 0) {
                     break;
                  }
               }
            }
         }
      } catch (Exception exc) {
      }
   }

   public void eliminarTodos(String cola, Timestamp hora) {
      synchronized (datos) {
         String colaR =  buscarRangoHuecos(cola);
         for (ListIterator<RegistroHuecos> it = datos.listIterator(); it.hasNext();) {
            RegistroHuecos rb = it.next();
            if (rb.cola.equals(colaR) && rb.horaCita.equals(hora)) {
               it.remove();
            }
         }
      }
   }

   public RegistroHuecos[] buscarDisponibles(String cola, Timestamp hora, int minutosMargen) {
      int n = datos.size();
      if (n == 0) {
         return null;
      }
      String colaR =  buscarRangoHuecos(cola);
      HashMap<RegistroHuecos, RegistroHuecos> encontrados = new HashMap<>();
      Timestamp horaTope = null;
      String turno = Global.mainForm.getTurno();
      synchronized (datos) {
         for (int i = 0; i < n; i++) {
            RegistroHuecos rb = datos.get(i);
            if (rb.cola.equals(colaR) && rb.turno.equals(turno) && rb.horaCita.compareTo(hora) >= 0) {
               if (horaTope == null) {
                  horaTope = new Timestamp(rb.horaCita.getTime() + (long) minutosMargen * 60000L);
               }
               if (rb.horaCita.compareTo(horaTope) <= 0) {
                  encontrados.put(rb, rb);
               }
            }
         }
      }
      if (encontrados.size() > 0) {
         RegistroHuecos[] regs = new RegistroHuecos[encontrados.size()];
         regs = encontrados.values().toArray(regs);
         Arrays.sort(regs);
         return regs;
      }
      return null;
   }

   public boolean sigueDisponible(String cola, Timestamp hora) {
      synchronized (datos) {
         String colaR =  buscarRangoHuecos(cola);
          for (RegistroHuecos rb : datos) {
              if (rb.cola.equals(colaR) && rb.horaCita.equals(hora)) {
                  return true;
              }
          }
      }
      return false;
   }

   public void incorporarCitas(String cola, String turno, String mapa) {
      Calendar cal = new GregorianCalendar();
      cal.set(Calendar.HOUR_OF_DAY, 0);
      cal.set(Calendar.MINUTE, 0);
      cal.set(Calendar.SECOND, 0);
      cal.set(Calendar.MILLISECOND, 0);
      long lasSeis = cal.getTimeInMillis();
      synchronized (datos) {
         for (int i = 0; i < mapa.length(); i += 6) {
            String sm = "", sn = "";
            try {
               sm = mapa.substring(i, i + 4);
               long delta = Long.parseLong(sm) * 60000L;
               Timestamp hora = new Timestamp(lasSeis + delta);
               sn = mapa.substring(i + 4, i + 6);
               int numero = Integer.parseInt(sn);
               for (int j = 0; j < numero; j++) {
                  nuevoHueco(hora, cola, turno);
               }
            } catch (Exception ex) {
               gestor.Main.log.log(Level.SEVERE, "Error al incorporar Hueco: {0} {1}\n{2}", new Object[]{sm, sn, ex.getMessage()});
               ex.printStackTrace();
            }
         }
         ordenar();
      }
   }

   public RegistroHuecos nuevoRegistro(String reg) {
      synchronized (datos) {
         try {
            RegistroHuecos r = new RegistroHuecos();
            r.leerRegistroCompleto(reg);
            datos.add(r);
            return r;
         } catch (Exception exc) {
            exc.printStackTrace();
            return null;
         }
      }
   }

   // SOLO para comprobacion y depuracion
   LogGenerico logHuecos = null;

   public void listarHuecos() {
      try {
         if (logHuecos == null) {
            logHuecos = new LogGenerico("ListadoHuecos.log", "");
            logHuecos.aligerar(12, 6);
         }
         logHuecos.abrir();
         logHuecos.escribirRapido("Huecos a " + Fecha.ahora().toString());
         logHuecos.escribirRapido("--------------------------------------------");
         synchronized (datos) {
             for (RegistroHuecos rb : datos) {
                 logHuecos.escribirRapido(rb.toString());
             }
         }
         logHuecos.cerrar();
      } catch (Exception exc) {
         exc.printStackTrace();
      }
   }

   public void finCarga() {
      cargada = true;
      ordenar();
   }
}

