/* 
* 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.io.*;
import java.sql.*;
import java.util.ArrayList;
import servidor.Configuracion;
import servidor.datos.base.*;
import servidor.utiles.*;

public class TablaCandidatos extends MemTablaCandidatos {

    public TablaColas tablaColas;
    String centroFijo;

    public TablaCandidatos() {
        centroFijo = Configuracion.getConfiguracion().codigoCentro;
    }

    public void grabarNota(int id, String texto) {
        if (BaseDatos.bd().recuperacionActivada) {
            return;
        }
        try {
            PreparedStatement stmt = BaseDatos.bd().conexion.prepareStatement("UPDATE candidatos SET Notas=? WHERE Id=? ");
            stmt.setString(1, texto);
            stmt.setInt(2, id);
            stmt.executeUpdate();
            stmt.close();
        } catch (SQLException exc) {
            exc.printStackTrace();
        }
    }

    public void ponerEstadoDescartado(int id, String operador, String mesa, String centro) throws Exception {
        RegistroCandidatos reg = buscarId(id);
        if (reg != null) {
            reg.setEstado("D");
            reg.setHoraAtendido(Fecha.ahora());
            reg.setOperador(operador);
            reg.setMesa(mesa);
            if (centro.trim().equals("")) {
                centro = centroFijo;
            }
            reg.setCentro(centro);
            update(reg);
        }
    }

    public void ponerEstadoAtendido(int id) throws Exception {
        RegistroCandidatos reg = buscarId(id);
        if (reg != null) {
            reg.setEstado("A");
            reg.setHoraPresente2(Fecha.ahora());
            //para quitar bonificaciones
            //if (reg.getNiu().length() < 8) {
            // reg.setHoraCalculada(reg.getHoraPresente());
            //}
            update(reg);
        }
    }

    public void ponerEstadoFinalizado(int id, boolean vinculado) {
        RegistroCandidatos reg = buscarId(id);
        if (reg == null) {
            return;
        }
        reg.setEstado("S");
        reg.setHoraFinalizado(Fecha.ahora());
//      reg.setImpresas(impresas);
//      reg.setIntranet(intranet);
//      reg.setNumRentas(numRentas);
//      reg.setNumBorradoresConfirmados(numBorradoresConfirmados);
//      reg.setNumBorradoresRectificados(numBorradoresRectificados);
        try {
            update(reg);
        } catch (Exception exc) {
        }
    }

    public RegistroCandidatos cambiaEstado(RegCandidato rc) throws SQLException {
        if (rc.ticket.length() < 1) {
            rc.ticket = " ";
        }
        RegistroCandidatos reg = buscarId(rc.Id);
        if (reg == null) {
            return null;
        }
        reg.setEstado(rc.estado);
        reg.setHoraCalculada(rc.horaCalculada);
        reg.setHoraCalculada2(rc.horaCalculada2);
        reg.setHoraPresente(Fecha.ahora());
        reg.setHoraPresente2(horaPorCola(reg.getCola()));
        reg.setCitaMultiple(rc.numCitas);
        reg.setNumeroTicket(rc.ticket);
        reg.setCodigoGestor(rc.codigoGestor);
        reg.setMesa(rc.mesa);
        reg.setCitaVinculada(rc.citaVinculada);
        if (rc.estado.equals("P")) {
            if (reg.provieneDeCitaPrevia()) {
                reg.setGestionHuecos(true);
            }
            if (rc.usoDNIe) {
                reg.setDNIe(true);
            }
        }
        update(reg);
        return reg;
    }

    public java.sql.Timestamp horaPorCola(String cola) {
        int p = tablaColas.getTiemposRetraso(cola);
        return new java.sql.Timestamp(System.currentTimeMillis() + p);
    }

    public java.sql.Timestamp horaPorColaReenvio(String cola) {
        int p = tablaColas.getTiemposRetraso(cola);
        return new java.sql.Timestamp(System.currentTimeMillis() + p + 60000);
    }

    public void PresentesSegundaCita(String numeroTicket, String id) {
        int ID = Integer.parseInt(id);
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getId() == ID && r.getEstado().equals(" ")) {
                r.setEstado("P");
                r.setHoraCalculada(r.getHoraCita());
                r.setHoraCalculada2(r.getHoraCita());
                r.setNumeroTicket(numeroTicket);
                r.setHoraPresente(Fecha.ahora());
                r.setHoraPresente2(horaPorCola(r.getCola()));
                try {
                    update(r);
                } catch (Exception exc) {
                }
                return;
            }
        }
    }

    public void modificaColaMesaCandidato(RegCandidato rc) throws SQLException {
        RegistroCandidatos reg = buscarId(rc.Id);
        boolean cambiarCodEstadistico = false;
        String nuevoCodEstadistico = "";
        if (!reg.provieneDeCitaPrevia()) {
            cambiarCodEstadistico = true;
            nuevoCodEstadistico = tablaColas.codigoEstadistico(rc.colaDeseada);
        }

        if (reg.getCitaMultiple() > 1) {
            for (int i = 0; i < filas.size(); i++) {
                RegistroCandidatos r = registro(i);
                if (r.getCitaVinculada().equals(reg.getCitaVinculada()) && r.getCitaMultiple() > 1) {
                    r.setMesa(rc.mesa);
                    r.setCola(rc.colaDeseada);
                    r.setNombreCola(tablaColas.getDescripcion(rc.colaDeseada));
                    if (cambiarCodEstadistico) {
                        r.setCodigoEstadistico(nuevoCodEstadistico);
                    }
                    update(r);
                }
            }
        } else {
            reg.setMesa(rc.mesa);
            reg.setCola(rc.colaDeseada);
            reg.setNombreCola(tablaColas.getDescripcion(rc.colaDeseada));
            if (cambiarCodEstadistico) {
                reg.setCodigoEstadistico(nuevoCodEstadistico);
            }
            update(reg);
        }
    }

    public void cambiarCategoriaEstadistica(int id, String categoria) {
        RegistroCandidatos reg = buscarId(id);
        if (reg != null) {
            reg.setCodigoEstadistico(categoria);
            update(reg);
        }
    }

    public void bonificarPresentesDeCola(String cola, long bonificacion) {
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getCola().equals(cola) && r.getEstado().equals("P")) {
                long hora = r.getHoraCalculada2().getTime() - bonificacion;
                r.setHoraCalculada(new Timestamp(hora));
                try {
                    update(r);
                } catch (Exception exc) {
                }
            }
        }
    }

    public RegistroCandidatos buscarMasCitasPorNif(String nif) {
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getNif().equals(nif) && r.getEstado().equals(" ") && (r.getNiu().length() > 8)) {
                return r;
            }
        }
        return null;
    }

    public RegistroCandidatos nuevoCandidatoPresente(String nif, String nombre, Timestamp horaCita,
            String turno, String ticket, String cola, String colaEstadistica,
            String codigoGestor, String niu, Timestamp horaBonificada, boolean usoGestionHuecos, boolean usoDNIe, String centro) throws SQLException {
        RegistroCandidatos reg = (RegistroCandidatos) this.nuevoRegistro();
        reg.setNif(nif);
        reg.setNombre(nombre);
        reg.setEstado("P");
        reg.setTurno(turno);
        reg.setCitaMultiple(1);
        reg.setNumeroTicket(ticket);
        reg.setCola(cola);
        reg.setNombreCola(tablaColas.getDescripcion(cola));
        reg.setHoraCita(horaCita);
        reg.setHoraCalculada(horaBonificada);
        reg.setHoraPresente(Fecha.ahora());
        reg.setGestionHuecos(usoGestionHuecos);
        reg.setDNIe(usoDNIe);
        if (reg.getHoraPresente().before(horaCita) && niu.length() > 8) {
            reg.setHoraCalculada2(horaCita);
        } else {
            reg.setHoraCalculada2(reg.getHoraPresente()); // ahora...
        }

        reg.setCodigoEstadistico(colaEstadistica);
        reg.setCodigoGestor(codigoGestor);
        reg.setHoraPresente2(horaPorCola(reg.getCola()));
        reg.setNiu(niu);
        if (centro.trim().equals("")) {
            centro = centroFijo;
        }
        reg.setCentro(centro);
        insert(reg);
        return reg;
    }

    public RegistroCandidatos nuevoCandidatoPresenteReenvio(String nif, String nombre, Timestamp horaCita,
            String turno, String ticket, String cola, String colaEstadistica,
            String codigoGestor, String niu, Timestamp horaBonificada, boolean usoGestionHuecos, boolean usoDNIe, String mesa, String centro) throws SQLException {
        RegistroCandidatos reg = (RegistroCandidatos) this.nuevoRegistro();
        reg.setNif(nif);
        reg.setNombre(nombre);
        reg.setEstado("P");
        reg.setTurno(turno);
        reg.setCitaMultiple(1);
        reg.setNumeroTicket(ticket);
        reg.setCola(cola);
        reg.setNombreCola(tablaColas.getDescripcion(cola));
        reg.setHoraCita(horaCita);
        reg.setHoraCalculada(horaBonificada);
        reg.setHoraPresente(Fecha.ahora());
        reg.setGestionHuecos(usoGestionHuecos);
        reg.setDNIe(usoDNIe);
        if (reg.getHoraPresente().before(horaCita) && niu.length() > 8) {
            reg.setHoraCalculada2(horaCita);
        } else {
            reg.setHoraCalculada2(reg.getHoraPresente()); // ahora...
        }

        reg.setCodigoEstadistico(colaEstadistica);
        reg.setCodigoGestor(codigoGestor);
        reg.setHoraPresente2(horaPorColaReenvio(reg.getCola()));
        reg.setNiu(niu);
        reg.setMesa(mesa);
        if (centro.trim().equals("")) {
            centro = centroFijo;
        }
        reg.setCentro(centro);
        insert(reg);
        return reg;
    }

    public RegistroCandidatos nuevoCandidatoReserva(String nif, String nombre, Timestamp horaCita,
            String turno, String cola, String colaEstadistica, boolean usoDNIe) throws SQLException {
        RegistroCandidatos reg = (RegistroCandidatos) this.nuevoRegistro();
        reg.setNif(nif);
        reg.setNombre(nombre);
        reg.setEstado(" ");
        reg.setTurno(turno);
        reg.setCitaMultiple(1);
        reg.setCola(cola);
        reg.setNombreCola(tablaColas.getDescripcion(cola));
        reg.setHoraCita(horaCita);
        reg.setCodigoEstadistico(colaEstadistica);
        reg.setNiu(nif);
        reg.setGestionHuecos(true);
        reg.setDNIe(usoDNIe);
        reg.setCentro(centroFijo);
        insert(reg);
        return reg;
    }

    public String buscarRegistroPorId(int id) {
        RegistroCandidatos rc = buscarId(id);
        if (rc == null) {
            return null;
        }
        return buscarId(id).registro();
    }

    public RegistroCandidatos[] datosPorNif(String NifBuscado) {
        ArrayList<RegistroCandidatos> regs = new ArrayList<>();
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getNif().equals(NifBuscado)) {
                regs.add(r);
            }
        }
        return regs.toArray(new RegistroCandidatos[regs.size()]);
    }

    public String datosNotaFichero(String tabla, String id) {
        try {
            if (BaseDatos.bd().recuperacionActivada) {
                return null;
            }
            Statement s = BaseDatos.bd().conexion.createStatement();
            ResultSet rs = s.executeQuery("SELECT Id, Nif, Notas From " + tabla + " where Id = " + id);
            String nn = "";
            while (rs.next()) {
                nn = rs.getString("Nif") + "##" + rs.getString("Id") + "##" + rs.getString("Notas");
                //  if (rs.getString("Notas").length() > 3 )
            }
            rs.close();
            return nn;
        } catch (Exception exc) {
            exc.printStackTrace();
            return null;
        }
    }

    // Esta version tiene en cuenta los registros con NOTAS grabadas
    public RegistroCandidatos[] datosPorNif2(String NifBuscado) {
        try {
            if (BaseDatos.bd().recuperacionActivada) {
                return null;
            }
            ArrayList<RegistroCandidatos> regs = new ArrayList<>();
            Statement s = BaseDatos.bd().conexion.createStatement();
            ResultSet rs = s.executeQuery("SELECT * From Candidatos where Nif = '" + NifBuscado + "'");
            while (rs.next()) {
                RegistroCandidatos rc = new RegistroCandidatos();
                rc.cargar(rs);
                String nn = rs.getString("Notas");
                //  if (rs.getString("Notas").length() > 3 )
                if (nn != null && nn.length() > 3) {
                    rc.setNiu("S");
                }
                regs.add(rc);
            }
            rs.close();
            return regs.toArray(new RegistroCandidatos[regs.size()]);
        } catch (Exception exc) {
            exc.printStackTrace();
            return null;
        }
    }

    // Esta version tiene en cuenta los registros con NOTAS grabadas
    public RegistroCandidatos[] datosPorTicket2(String ticketBuscado) {
        try {
            if (BaseDatos.bd().recuperacionActivada) {
                return null;
            }
            ArrayList<RegistroCandidatos> regs = new ArrayList<>();
            Statement s = BaseDatos.bd().conexion.createStatement();
            ResultSet rs = s.executeQuery("SELECT * From Candidatos where NumeroTicket = '" + ticketBuscado + "'");
            while (rs.next()) {
                RegistroCandidatos rc = new RegistroCandidatos();
                rc.cargar(rs);
                String nn = rs.getString("Notas");
                //  if (rs.getString("Notas").length() > 3 )
                if (nn != null && nn.length() > 3) {
                    rc.setNiu("S");
                    //  rc.setNombre("Mod");
                }
                regs.add(rc);
            }
            rs.close();
            return regs.toArray(new RegistroCandidatos[regs.size()]);
        } catch (Exception exc) {
            exc.printStackTrace();
            return null;
        }

    }

    public RegistroCandidatos[] datosPorNif2Historico(String nif) {
        try {
            if (BaseDatos.bd().recuperacionActivada) {
                return null;
            }
            ArrayList<RegistroCandidatos> regs = new ArrayList<>();
            Statement s = BaseDatos.bd().conexion.createStatement();
            ResultSet rs = s.executeQuery("SELECT * From HistoricoCandidatos where Nif = '" + nif + "'");
            while (rs.next()) {
                RegistroCandidatos rc = new RegistroCandidatos();
                rc.cargar(rs);
                String nn = rs.getString("Notas");
                if (nn != null && nn.length() > 3) {
                    rc.setNiu("S");
                }
                regs.add(rc);
            }
            rs.close();
            return regs.toArray(new RegistroCandidatos[regs.size()]);
        } catch (Exception exc) {
            exc.printStackTrace();
            return null;
        }
    }

    public RegistroCandidatos[] datosPorTicket(String ticketBuscado) {
        ArrayList<RegistroCandidatos> regs = new ArrayList<>();
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getNumeroTicket().equals(ticketBuscado)) {
                regs.add(r);
            }
        }
        return regs.toArray(new RegistroCandidatos[regs.size()]);
    }

    public ArrayList<String> candidatosEnTransito(TablaColas tablaColas, servidor.clientes.Operadores operadores) {
        long ahora = (new java.util.Date()).getTime();
        ArrayList<String> lista = new ArrayList<>();
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            // Si están en tránsito, desde hace menos de diez minutos
            if (r.tieneTicket() && r.getEstado().equals("D") && (ahora - r.getHoraAtendido().getTime()) < 600000) {
                String sala = tablaColas.getSalaEspera(r.getCola());
                servidor.clientes.Operador op = operadores.get(r.getMesa());
                if (op != null) {
                    String localizacion = op.getLocalizacion();
                    lista.add("xxx" + "|" + r.getNumeroTicket() + "|" + r.getMesa() + "|" + sala + "|" + r.getHoraCalculada2() + "|" + localizacion);
                }
            }
        }
        return lista;
    }

    public void resucitar(RegistroCandidatos reg, servidor.clientes.Gestores gestores) {
        reg.setEstado("P");
        reg.setMesa("");
        try {
            update(reg);
        } catch (Exception exc) {
            exc.printStackTrace();
            return;
        }
        gestores.enviarCambioEstadoCandidato(reg.registro());
        if (reg.getCitaMultiple() < 2) {
            return;
        }
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getCitaVinculada().equals(reg.getCitaVinculada()) && r.getId() != reg.getId() && r.getCitaMultiple() > 1) {
                r.setEstado("X");
                r.setMesa("");
                try {
                    update(r);
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
                gestores.enviarCambioEstadoCandidato(r.registro());
            }
        }
    }

    public void restaurarResucitados(Resucitador resucitador) {
        if (resucitador == null) {
            return;
        }
        resucitador.vaciar();
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            resucitador.add(r);
        }
    }

    public boolean hayCandidatoPosterior(java.util.Date hora) {
        for (int i = 0; i < filas.size(); i++) {
            RegistroCandidatos r = registro(i);
            if (r.getHoraCita().after(hora)) {
                return true;
            }
        }
        return false;
    }

    public void salvarDatos(String path) {
        try {
            PrintStream salida = new PrintStream(new FileOutputStream(path, false));
            for (MemRegistro r : filas) {
                salida.println(r.registroSBuff().toString());
            }
            salida.close();
        } catch (Exception exc) {
        }
    }
}
