
package source;

import java.io.IOException;
import java.io.InputStream;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;

/**
 *
 * @author Radoslaf
 */
public class Bluetooth implements DiscoveryListener {

    /*=========================================
     * ===== Bluetooth search =================
     * ===== Connect to GPS receiver ==========
     * ========================================
     */
    // Inicializace globalnich promennych
    private RemoteDevice[] devList = new RemoteDevice[10]; // pole nalezenych zařízení
    private LocalDevice ld = null; // Lokální BT adaptér, JSR-82 přdpokládá jen jeden
    private String[] connURL = new String[10]; // pole získaných adres BT zařízení
    private int numDevice = 0; // pocet nalezenych zarizeni
    private Navigator navi = null;
    private DataHandler handler = null;


    // Konstruktor pro MIDlet Navigator
    public Bluetooth(Navigator navi, DataHandler handler) {
        this.navi = navi;
        this.handler = handler;
    }

    // Filtrace nazvu
    // Povolene znaky GPS v poradi za sebou
    private boolean isGPS(String name) {
        int len = name.length();
        int g = 0, p = 0, s = 0;
        char[] cname = new char[len];
        cname = name.toCharArray();
        for (int i = 0; i < len; i++) {
            if (cname[i] == 'G' || cname[i] == 'g') {
                g = i;
            }
            if (cname[i] == 'P' || cname[i] == 'p') {
                p = i;
            }
            if (cname[i] == 'S' || cname[i] == 's') {
                s = i;
            }
        }
        if (g < p & g < s & p < s) {
            int px = g + 1;
            int sx = g + 2;
            if (px == p & sx == s) {
                return true;
            }
        } else {
            return false;
        }
        return false;
    }

    public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
        String name = null;         // Jmeno BT zarizeni
        try {
            name = btDevice.getFriendlyName(false); // Zjisteni BT jmena
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        // Přidání zarízeni na seznam
        // Filtrace zařízení
        if (isGPS(name) == true) {
            this.devList[this.numDevice] = btDevice; // Pridání zarizeni do pole
            this.numDevice++;
        }
        throw new UnsupportedOperationException("Chyba při vyhledávání BT zařízení");
    }

    // Vyhledání služby
    public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
        if (servRecord != null && servRecord.length > 0) {
            for (int i = 0; i < servRecord.length; i++) {
                connURL[i] = servRecord[i].getConnectionURL(0, false); // Získaní BT adresy zarizeni a prirazeni do pole adres
            }
        }
        throw new UnsupportedOperationException("Chyba při vyhledávání služby BT zařízení");
    }

    // Skonceni vyhledávání sluzeb zarizeni
    public void serviceSearchCompleted(int transID, int respCode) {
        navi.getInfo().setString("Vyhledávání služby dokončeno.");
        navi.switchDisplayable(null, navi.getInfo()); // Zobrazeni informace o prubehu
        throw new UnsupportedOperationException("Chyba při dokončení hledání služby");
    }

    // Skonceni vyhledavaní zarizeni
    public void inquiryCompleted(int discType) {
        navi.getInfo().setString("Hledání zařízení dokončeno");
        navi.switchDisplayable(null, navi.getInfo()); // Zobrazeni informace o prubehu
        if (devList[0] == null) {
            navi.getInfo().setString("Nebylo nalezeno žádné GPS zařízení v dosahu.");
            navi.switchDisplayable(null, navi.getInfo()); // Zobrazeni informace ze nebylo nalezeno zadne zarizeni GPS
        } else {
            for (int i = 0; i < numDevice; i++) {
                try {
                    navi.getInfo().setString("Bylo nalezeno " + numDevice + " GPS zařízení v dosahu.");
                    navi.switchDisplayable(null, navi.getInfo()); // Zobrazeni informace o prubehu
                    navi.getChoosedevices().append(devList[i].getFriendlyName(false), navi.getMBT24()); // Zobrazeni zarizeni do seznamu
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            // Po skonceni vyhledavani je nutne vyhledat sluzby, ktere poskytujou nalezena zarizeni
            /* ---------------------------------------
            Hledání služby poskytované BT zařízením
             * ---------------------------------------*/
            // Definování parametru služby
            UUID[] uuidSet = new UUID[3];
            uuidSet[0] = new UUID(0x1101);  // Serial port
            uuidSet[1] = new UUID(0x0100);  // L2CAP
            uuidSet[2] = new UUID(0x0003);  // RFCOMM
            // Spuštění hledání
            for (int j = 0; j < numDevice; j++) {
                try {
                    RemoteDevice rd = devList[j];
                    // Spuštění hledání
                    ld.getDiscoveryAgent().searchServices(null, uuidSet, rd, this);
                } catch (BluetoothStateException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    // Spustění procesu vyhledávání
    public synchronized void discoverGPS() throws BluetoothStateException {
        navi.getInfo().setTimeout(4000);
        navi.getInfo().setString("Hledám Bluetooth zařízení v dosahu prosím počkejte ..."); // Zobrazeni informace o prubehu
        navi.switchDisplayable(null, navi.getInfo());
        navi.getChoosedevices().deleteAll(); // Vymazani seznamu nalezenych zarizeni na dipleji
        ld = LocalDevice.getLocalDevice(); // Metoda získavá lokální adaptér
        DiscoveryAgent da = ld.getDiscoveryAgent(); // Metoda získá DA
        this.numDevice = 0;
        try {
            da.startInquiry(DiscoveryAgent.GIAC, this); // Začátek hledání, GIAC-všechny zařízení
        } catch (BluetoothStateException ex) {
            ex.printStackTrace();
        }
    }

    /* ---------------------------------------------------
     *          Vytvoreni spojeni s GPS modulem
     * ------------------------------------------------*/
    public StreamConnection conn = null; // spojeni se zarizenim
    public InputStream is = null; // vstupni tok dat
    public boolean isConnect = false; // stav spojeni
    private int selected = 0;

    // Getters meotda pro isConnect
    public boolean getIsConnect() {
        return isConnect;
    }

    // Setters metoda pro isConnect
    public void setIsConnect(boolean isConnect) {
        this.isConnect = isConnect;
    }



    // Spusteni procesu parovani
    public synchronized void connect() throws IOException {
        selected = navi.getChoosedevices().getSelectedIndex();
        if (selected != -1) {
            this.statusBTinfo();
            // RFCOMM connection
            // vytvoreni spojeni na zadany soket
            if (conn == null) {
                conn = (StreamConnection) Connector.open(connURL[selected]);
            }
            // Otevreni vstupniho streamu dat
            if (is == null) {
                is = conn.openInputStream();
            }
            this.setIsConnect(true);
            this.handler.setIs(is);
            // Spuštění vláken pro čtení a překlad NMEA 0183 dat
            try {
                navi.sync();
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    // Odpojeni zarizeni BT
    public void disConnect() throws IOException {
      this.setIsConnect(false);
       if (navi.greader.isAlive() == true)
           navi.greader.interrupt();
       if (navi.gparser.isAlive() == true)
           navi.gparser.interrupt();
       if (is != null)
           is.close();
       if(conn != null)
           conn.close();
       // Vyčištěni paměti
       is = null;
       conn = null;
       navi.gparser = null;
       navi.greader = null;
    }


    // Informace o BT spojeni
    public void statusBTinfo() throws IOException {
        selected = navi.getChoosedevices().getSelectedIndex();
        if (selected != -1) {

            navi.getStatus().deleteAll();

            // Inicializace
            String protocol = "";
            String address = "";
            String auten = "";
            String encrypt = "";
            String devname = "";

            // Parsování informací

            String s = connURL[selected];
            int e = 0;
            int a = 0;
            e = s.indexOf(":");
            protocol = s.substring(0, e);
            s = s.substring(e + 3, s.length());
            e = s.indexOf(":");
            address = s.substring(0, e);
            s = s.substring(e + 3, s.length());
            a = s.indexOf("=");
            e = s.indexOf(";");
            auten = s.substring(a + 1, e);
            s = s.substring(e + 1, s.length());
            a = s.indexOf("=");
            e = s.indexOf(";");
            encrypt = s.substring(a + 1, e);
            devname = this.devList[selected].getFriendlyName(false);




            String text = "BLUETOOTH INFORMACE \n\n" +
                    "Bluetooth jméno zařízení\n" +
                    devname + "\n\n" +
                    "Použitý protokol spojení\n" + protocol + "\n\n" +
                    "Bluetooth adresa zařízení\n" + address + "\n\n" +
                    "Ověření \n" + auten + "\n\n" +
                    "Šifrovaný přenos \n" + encrypt;

            this.navi.getStatus().append(text);
        }
    }
}
