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

import java.io.*;
import java.util.*;
import java.util.regex.*;
import servidor.clientes.*;

public class Pinger {

    public final Map<String, String> clientes;
    Pattern regex1;
    Pattern regex2;
    boolean interrumpido = false;
    boolean pinging = false;
    Thread hilo;
    long milisecs;
    long horaComienzo;

    public Pinger() {
        clientes = Collections.synchronizedMap(new HashMap<String, String>());
        regex1 = Pattern.compile("^Respuesta .* TTL=(\\d*)");
        regex2 = Pattern.compile("\\s*Paquetes.*perdidos = (\\d*).*");
    }

    public void comenzar(int segundos) {
        if (pinging) {
            return;
        }
        interrumpido = false;
        milisecs = segundos * 1000;
        hilo = new Thread(() -> {
            pinging = true;
            ejecutar();
            pinging = false;
        });
        hilo.setPriority(Thread.MIN_PRIORITY);
        hilo.setName("Hilo PING");
        hilo.setDaemon(true);
        hilo.start();
    }

    public void comenzar() {
        comenzar(0);
    }

    public void parar() {
        interrumpido = true;
    }

    public boolean nuevoDestino(Cliente cli) {
        String ip = cli.ipAdd;
        if (!clientes.containsKey(ip)) {
            clientes.put(ip, cli.tipo + " ");
        }
        return true;
    }

    public boolean nuevoDestino(Iterator it, String descr) {
        boolean algunos = false;
        while (it.hasNext()) {
            Cliente cliente = (Cliente) it.next();
            if (!clientes.containsKey(cliente.ipAdd)) {
                clientes.put(cliente.ipAdd, descr);
            }
            algunos = true;
        }
        return algunos;
    }

    public void ejecutar() {
        horaComienzo = System.currentTimeMillis();
        while (!interrumpido) {
            if (milisecs > 0 && (System.currentTimeMillis() - horaComienzo) > milisecs) {
                interrumpido = true;
                break;
            }
            try {
                synchronized (clientes) {
                    for (String ip : clientes.keySet()) {
                        String desc = clientes.get(ip);
                        ping(desc, ip);
                    }
                }
            } catch (Exception exc) {
            }
        }
    }

    void ping(String descripcion, String ip) {
        try {
            Process proceso = Runtime.getRuntime().exec("ping " + ip);
            BufferedReader bis = new BufferedReader(new InputStreamReader(proceso.getInputStream()));
            String s;
            servidor.datos.LogGenerico log = Global.main.logMensajesSalientes;
            int tiempoMenor = 9999999;
            int tiempoMayor = 0;
            int perdidos = 0;
            while ((s = bis.readLine()) != null) {
                Matcher match = regex1.matcher(s);
                if (match.matches()) {
                    int tiempo = Integer.parseInt(match.group(1));
                    if (tiempo < tiempoMenor) {
                        tiempoMenor = tiempo;
                    }
                    if (tiempo > tiempoMayor) {
                        tiempoMayor = tiempo;
                    }
                } else {
                    match = regex2.matcher(s);
                    if (match.matches()) {
                        perdidos = Integer.parseInt(match.group(1));
                    }
                }
            }
            if (perdidos > 0) {
                log.escribir(Fecha.formatoHoraHMS(new Date()) + "  " + descripcion + ip);
                log.escribir("  Perdidos: " + perdidos);
                if (perdidos < 4) {
                    log.escribir("  Tiempo entre " + tiempoMenor + " y " + tiempoMayor);
                }
            }
        } catch (Exception exc) {
        }
    }
}
