package BluetoothServer;

import Interfaz.MainPanelBluetooth;
import javax.bluetooth.*;
import java.io.*;
import javax.microedition.io.*;

/**
 * Clase Servidor de Bluetooth.
 * Establece comunicación usando perfil del tipo puerto serie (SPP).
 * El servidor espera por conexiones del tipo SPP y recibe de ellas un string.
 *
 * @author JJDA && JPAL
 */
public class bluetoothServer extends Thread {

    // Perfil SPP
    public static final UUID uuid = new UUID(0x1101);   //SerialPort
    protected int discoveryMode;
    private LocalDevice localDevice;
    private StreamConnectionNotifier notifier;
    private RemoteDevice remoteDevice;
    // Variables para transmisión y recepción de datos.
    StreamConnection connection;
    DataInputStream in;
    DataOutputStream out;
    MainPanelBluetooth mpb;

    
    /**
     * Constructor de la Clase.
     * Inicializa variables del Servidor.
     *
     * @param mpb Referencia al panel para agregar equipos que se conectan.
     */
    public bluetoothServer(MainPanelBluetooth mpb) {
        discoveryMode = DiscoveryAgent.GIAC;    //Modo General/Unlimited Inquiry Access Code
        connection = null;
        in = null;
        out = null;
        this.mpb = mpb;
    }


    /**
     * Método que setea las caracteristicas del servidor.
     * - Lo hace visible.
     * - Genera URL.
     * - Crea el objeto "notifier" con la que se crea la conexión.
     */
    public void setBluetooth() {

        try {
            localDevice = LocalDevice.getLocalDevice();

            //DirecciÃ³n MAC Bluetooth local
            String address = localDevice.getBluetoothAddress();

            //Se setea "descubrible"
            if (!localDevice.setDiscoverable(discoveryMode)) {
                System.out.println("Imposible ofrecer un servicio");
            }

            StringBuffer url = new StringBuffer("btspp://localhost:");  //DirecciÃ³n URL
            url.append(uuid.toString());  //Agrega UUID (toString convierte objeto en cadena de caracteres)
            url.append(";name=Servidor Compras");
            notifier = (StreamConnectionNotifier) Connector.open(url.toString());

            System.out.println("URL:" + url.toString());

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Error: " + e);
        }
    }

    /**
     * Método que espera por conexiones de usuarios y recibe el string que estos envían.
     * Genera un String con la palabra "Retorno: " más el string recibido y lo devuelve
     * al cliente. Luego se cierra la conexiÃ³n.
     */
    @Override
    public void run() {

        System.out.println("Servidor en espera de consultas...");

        //En espera de conexiones clientes
        while (true) {

            try {
                //Se acepta la conexión y apertura de la comunicación
                connection = notifier.acceptAndOpen();
                remoteDevice = RemoteDevice.getRemoteDevice(connection);
                mpb.defaultListModel.addElement("Equipo: "+remoteDevice.getBluetoothAddress());
                mpb.textArea.append("Se ha conectado :"+remoteDevice.getBluetoothAddress()+"\n\n");
                int i = mpb.defaultListModel.getSize() -1;
                in = connection.openDataInputStream();
                out = connection.openDataOutputStream();

                //Server lee mensaje del cliente
                String paqueteIn = in.readUTF();

                // en esta seccion se da el intercambio de datos entre el telefono y el servidor.
                ServeClient cliente = new ServeClient();

                String paqueteOut = cliente.Authenticate(paqueteIn)+"";

               
                //Se responde al cliente
                out.writeUTF(paqueteOut);
                out.flush();
                mpb.defaultListModel.remove(i);
                mpb.textArea.append("Se ha desconectado :"+remoteDevice.getBluetoothAddress()+"\n\n");

            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("Error: " + e);
            } finally { //Cerrar la conexion
                try {
                    if (in != null) {
                        in.close();  //Flujo entrada
                    }
                    if (out != null) {
                        out.close(); //Flujo salida
                    }
                    if (connection != null) {
                        connection.close(); //Conexion
                    }
                } catch (IOException e) {
                }
            }
        }
    }
}
