package edutainmentclient;

import es.tid.osami.xmppclient.XMPPService;
import es.tid.osami.xmppclient.XMPPServiceListener;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.media.Time;
import javax.swing.JInternalFrame;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import tmaestroplayer.AppletTemplateComponentsXML;
import tmaestroplayer.MainWindow;
import tmaestroplayer.MainWindow_portada;
import tmaestroplayer.MediaPanel;
import tmaestroplayer.VentanaSCO;
import tmaestroplayer.VentanaSeleccionUnidad;
import db.DBAccessImplementation;

/**
 *
 * @author Silvia
 */
public class Main {

    //Location server answer types
    static final private int NONE = 0;//Esta valor indica que no estamos esperando ninguna respuesta
    static final private int RULE_CREATION = 1;
    static final private int RULE_DELETION = 2;
    static final private int DEVICE_ATT = 3;
    static final private int DEVICE_DET = 4;
    //Variable que nos indica que tipo de respuesta estamos esperando del servidor de localizacion
    static private int expectedAnswerType = 0;
    static private SystemTray tray;
    static private XMPPService xmppService;
    //IMPORTANTE Indica si el reproductor de cursos está iniciado
    static public boolean started = false;
    static private String currentUser = ""; //de momento un solo usuario
    static private String ruleId;
    static public MainWindow mw;
    static public MainWindow_portada mw_portada;
    static private Properties clientOptions;
    //Estas variables se leen del fichero de configuración
    static private String agentBTId = "00:02:C7:FA:74:48";
    static private String agentBTName = "btuvigo";
    static private String clientXMPPUser = "gonzalo";
    static private String clientXMPPDomain = "osami.tid.es";
    static private String clientXMPPPassword = "osami";
    static private String clientXMPPServer = "osami.tid.es";
    static public String userId = "john"; //En un principio vamos a considerar un solo
    static private String userEmail = "john@osami";
    //static private String locserverAddr = "uvigolocserver@osami.tid.es";
    static private String locserverAddr = "locserver@osami.tid.es";
    static private String edutainmentServerAddr = "silviabastosedutainment@osami.tid.es";
    static private String userBTId = "00:11:22:33:44:55";
    public static final String SUPPORT_JAR_LOCATION = "edutainment-support.jar";
    //inicialmente lo proporcionan los argumentos de entrada
    public static String rutascorm = null, nombrecurso = null;
    public static Vector<String> listaCursos = null;
    public static boolean basededatos = false;
    public static boolean maxim = false;
    public static boolean AutoInicio = false;

    /**
     * @param args the command line arguments
     * Posible entrada de argumentos:
     * vector con lista de cursos
     * o un la ruta Scorm de un curso directamente
     */
    public static void main(String[] args) {
        System.out.println("Número de argumentos " + args.length + ".");


        //Por si no se proporciona
        String aux = "vector=[http://193.146.210.22:8080/Courses/osami/00000000, http://193.146.210.22:8080/Courses/osami/00000001, "
                + "http://193.146.210.22:8080/Courses/osami/00000002, http://193.146.210.22:8080/Courses/osami/00000003, "
                + "http://193.146.210.22:8080/Courses/osami/00000004, http://193.146.210.22:8080/Courses/osami/00000005, "
                + "http://193.146.210.22:8080/Courses/osami/00000006, http://193.146.210.22:8080/Courses/osami/00000007]";

        listaCursos = new Vector<String>();

        listaCursos.add(aux.substring(aux.indexOf("=") + 2, aux.indexOf(",")));
        aux = aux.substring(aux.indexOf(",") + 1, aux.length());
        while (aux.indexOf(",") != -1) {
            listaCursos.add(aux.substring(1, aux.indexOf(",")));
            aux = aux.substring(aux.indexOf(",") + 1, aux.length());
        }
        listaCursos.add(aux.substring(1, aux.length() - 1));

        readArguments(args);
        /*
        System.out.println("portada");
        mw_portada = new MainWindow_portada(userId, listaCursos);
        mw_portada.init();
        started = true;
        try {
        //System.getProperty("os.name").toUpperCase().indexOf("LINUX") != -1  ... Ver más
        Thread.sleep(50000);
        } catch (InterruptedException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
         */

        //le damos valor a las variables a través de un fichero de configuración
        configureXMPPAccount();

        //Creamos una instancia del SystemTray desde la que controlaremos el Edutainment Client
        createSystemTray();



        /*
        System.out.println("Numero de ventanas: " + Window.getWindows().length);
        for (Window win : Window.getWindows()) {
        if (win instanceof Frame) {
        System.out.println("la ventana es una instancia de Frame");
        if (win instanceof JFrame) {
        System.out.println("tambien es una instancia de JFrame");
        } }   }
         */

        InputStream is = Main.class.getResourceAsStream("/config/options.properties");
        //prop.load(is);

        Properties options = new Properties();
        try {
            options.load(is);
            //Leemos la configuracion del fichero
            //options.load( MainWindow.class.getResourceAsStream("/tmaestroplayer/config/options.properties"));

        } catch (IOException ex) {
            ex.printStackTrace();
        }

        String autoinicio = options.getProperty("AutoInicio");
        AutoInicio = Boolean.parseBoolean(autoinicio);
        System.out.println(AutoInicio + " " + autoinicio);
        if ((maxim) & (AutoInicio)) {
            if (!started) {


                Vector allPoints = new Vector();
                allPoints = DBAccessImplementation.getInstance().getAllPoints();

                System.out.println("Todos los datos de la tabla:");
                System.out.println(allPoints);
                if ((((Vector) allPoints.get(0)).size() != 0) || (rutascorm != null)) {
                    if (rutascorm == null) {
                        System.out.println("Hay algún punto almacenado, empiezo desde ahí1");
                        Vector punto = (Vector) allPoints.get(5);
                         int ultimo=punto.size()-1;
                        String courseURL = (String) punto.get(ultimo);
                        String r1 = courseURL.substring(0, courseURL.length() - 1);
                        rutascorm = r1.substring(0, r1.lastIndexOf("/") + 1);
                        System.out.println("r1 " + r1);
                        nombrecurso = r1.substring(r1.lastIndexOf("/") + 1, r1.length()) + "/";
                        System.out.println("//118-11-2010 a");
                        basededatos = true;
                    }

                    System.out.println("rutascorm " + rutascorm + " nombrecurso " + nombrecurso);
                    mw = new MainWindow(userId, false);
                    mw.init();

                } else {
                    System.out.println("Entramos por portada");
                    mw_portada = new MainWindow_portada(userId, listaCursos);
                    mw_portada.init();

                }
                started = true;
            }
        }

        createXMPPConnection();

    }

    private static void sendRulMessage() {
        //Creamos la regla en el servidor de localización para recibir la información necesaria
        String rulMessage = "";
        //vamos a suscribirnos empleando el nombre del agente, para no tener problemas a la hora de coger la mac
        rulMessage += "<osami type=\"rul\">" + "\n" + "<agents><agent><id>" + agentBTId + "</id></agent></agents>" + "\n";
        //rulMessage += "<osami type=\"rul\">" + "\n" + "<agents><agent><name>" + agentBTName + "</name></agent></agents>" + "\n";

        //Esta parte se puede omitir si queremos recibir la localizacion de cualquier usuario
        //requiere previamente haber asociado algún dispositivo a ese usuario
        rulMessage += "<users><user><name>" + userId + "</name></user></users>" + "\n";
        //Esta parte sirve para indicar a que dirección xmpp enviar los eventos de localización correspondientes a la regla
        rulMessage += "<rule><address>" + clientXMPPUser + "@" + clientXMPPDomain + "</address></rule>" + "\n";
        rulMessage += "</osami>";

        expectedAnswerType = RULE_CREATION;
        System.out.println("Enviamos el siguiente mensaje de Rul: ");
        System.out.println(rulMessage);
        xmppService.sendMessage(locserverAddr, rulMessage);
        int maxcont = 20;
        while ((expectedAnswerType != NONE) && (maxcont != 0)) {
            //con esto comprobamos si ya se ha recibido la respuesta al mensaje de attachment
            try {
                Thread.sleep(500);
                maxcont--;
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        if (maxcont == 0) {
            System.out.println("OJO SERVIDOR DE LOCALIZACION CAIDO");

        }
    }

    private static void sendAttMessage() {
        //Enviamos al servidor de localizacion un mensaje de asociacion de un dispositivo con un usuario
        String attMessage = "";
        attMessage += "<osami type=\"att\">" + "\n";
        attMessage += "<devices><device><id>" + userBTId + "</id></device></devices>" + "\n";
        attMessage += "<user><name>" + userId + "</name><address>" + userEmail + "</address></user>" + "\n";
        attMessage += "</osami>";

        //esperamos la respuesta de un attachment
        expectedAnswerType = DEVICE_ATT;
        System.out.println("Enviamos el siguiente mensaje de Att: ");
        System.out.println(attMessage);
        xmppService.sendMessage(locserverAddr, attMessage);

        //Para no esperar infinitamente;
        int maxcont = 20;
        while ((expectedAnswerType != NONE) && (maxcont != 0)) {
            //con esto comprobamos si ya se ha recibido la respuesta al mensaje de attachment
            try {
                Thread.sleep(500);
                maxcont--;
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        if (maxcont == 0) {
            System.out.println("OJO SERVIDOR DE LOCALIZACIÖN CAIDO");

        }
    }

    public static void sendRulDelMessage() {
        String rulDelMessage = "";
        rulDelMessage += "<osami type=\"rul\">" + "\n";
        //Indicamos el id de la regla
        rulDelMessage += "<rule remove=\"true\"><id>" + ruleId + "</id></rule>" + "\n";
        rulDelMessage += "</osami>";

        expectedAnswerType = RULE_DELETION;


        System.out.println("Enviamos el siguiente mensaje de RulDel: ");
        System.out.println(rulDelMessage);
        xmppService.sendMessage(locserverAddr, rulDelMessage);

        //maximo que espero por la respuesta...
        int contmax = 20;
        if (ruleId != null) {
            while ((expectedAnswerType != NONE) && (contmax != 0)) {//con esto comprobamos si ya se ha recibido la respuesta al mensaje de eliminación de regla
                try {
                    Thread.sleep(500);
                    contmax--;
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        if (contmax == 0) {
            System.out.println("Salí porque no recibí respuesta");
        }
        if (ruleId == null) {
            System.out.println("Salí porque ruleId = null");
        }
        //aqui el usuario decide salir->NO SE ALMACENA ESTADO
        System.exit(0);
    }

    private static void createXMPPConnection() {
        //xmppService = new XMPPService("osami.tid.es", 5222, "gonzalo", "osami.tid.es", "osami", false);
        xmppService = new XMPPService(clientXMPPServer, 5222, clientXMPPUser, clientXMPPDomain, clientXMPPPassword, false);

        xmppService.addXMPPServiceListener(new XMPPServiceListener() {

            public void xmppConnecting(String server, int port) {
                System.out.println("Conectando con " + server + ":" + port);
            }

            public void xmppCreatingAccount(String user, String domain) {
                System.out.println("Creando la cuenta " + user + "@" + domain);
            }

            public void xmppLogging(String user, String domain) {
                System.out.println("Usuario " + user + " identificándose en " + domain);
            }

            public void xmppLogged() {
                System.out.println("Identificación correcta");
            }

            public void xmppMessageReceived(Message message) {
                System.out.println("Se ha recibido el siguiente mensaje de " + message.getFrom() + ":");
                //Si el mensaje es de la direccion correcta lo procesamos
                if (message.getFrom().startsWith(locserverAddr)) {//aquí hay que poner la dirección del servidor de localización
                    locationMessageReceived(message);
                } else {//if (message.getFrom().startsWith("localserver@osami.tid.es")) {
                    edutainmentMessageReceived(message);
                }
            }

            public void xmppError(XMPPException xmppException) {

                xmppException.printStackTrace();
                System.out.println("Se ha producido un error.");
                //TODO Silvia
                //System.exit(0);
            }

            public void xmppDisconnected() {
                System.out.println("Conexión con el servidor perdida");


            }
        });

        //este método se queda escuchando los posibles mensajes XMPP recibidos
        xmppService.run();

        //TODO subscribirse al localization service para que nos envíe la información de los usuarios
        sendAttMessage();

        sendRulMessage();
    }

    private static void createSystemTray() {
        if (SystemTray.isSupported()) {

            tray = SystemTray.getSystemTray();
            Image image = null;




            image = (new javax.swing.ImageIcon(Main.class.getResource("/resources/birrete.gif"))).getImage();
            /*
            try {
            image = Toolkit.getDefaultToolkit().getImage(new URL("http://localhost:7070/EdutainmentClient/birrete.gif"));
            } catch (MalformedURLException ex) {               
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }
             */
            MouseListener mouseListener = new MouseListener() {

                public void mouseClicked(MouseEvent e) {
                    System.out.println("Tray Icon - Mouse clicked!");
                }

                public void mouseEntered(MouseEvent e) {
                    System.out.println("Tray Icon - Mouse entered!");
                }

                public void mouseExited(MouseEvent e) {
                    System.out.println("Tray Icon - Mouse exited!");
                }

                public void mousePressed(MouseEvent e) {
                    System.out.println("Tray Icon - Mouse pressed!");
                }

                public void mouseReleased(MouseEvent e) {
                    System.out.println("Tray Icon - Mouse released!");
                }
            };
            ActionListener exitListener = new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    System.out.println("Tray Exiting...");
                    //TO-DO Eliminar la regla del servidor de localización y a lo mejor desasociar el dispositivo BT del usuario
                    //Eliminamos la regla del servidor de localización
                    sendRulDelMessage();
                }
            };
            ActionListener openListener = new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    System.out.println("Tray Opening... ");
                    /*if (rutascorm != null) {
                        System.out.println("Tray Opening... " + rutascorm + nombrecurso);
                    } else {
                        System.out.println("Tray Opening... " + listaCursos);
                    }
                     */
                    //si ya esta iniciado no hacemos caso
                    if (!started) {
                        started = true;

                        Vector allPoints = new Vector();
                        allPoints = DBAccessImplementation.getInstance().getAllPoints();

                        System.out.println("Todos los datos de la tabla: "+allPoints.size());
                        System.out.println(allPoints);
                        if ((((Vector) allPoints.get(0)).size() != 0) || (rutascorm != null)) {
                            System.out.println("rutascorm!=null o database!=0");
                            if (rutascorm == null) {
                                System.out.println("Hay algún punto almacenado, empiezo desde ahí1");
                                Vector punto = (Vector) allPoints.get(5);
                                int ultimo=punto.size()-1;
                                
                                String courseURL = (String) punto.get(ultimo);
                                String r1 = courseURL.substring(0, courseURL.length() - 1);
                                rutascorm = r1.substring(0, r1.lastIndexOf("/") + 1);
                                //System.out.println("r1 " + r1);
                                nombrecurso = r1.substring(r1.lastIndexOf("/") + 1, r1.length()) + "/";
                                basededatos = true;
                            }

                            System.out.println("rutascorm: " + rutascorm + " nombrecurso: " + nombrecurso);
                            mw = new MainWindow(userId, false);
                            mw.init();

                        } else {
                            System.out.println("Entramos por portada");
                            mw_portada = new MainWindow_portada(userId, listaCursos);
                            mw_portada.init();

                        }

                    }
                }
            };
            ActionListener minimizeListener = new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    System.out.println("Tray Minimizing... " + started);

                    boolean alma = true;
                    //return Vector<String> que contiene:
                    // courseId, scoId y timestamp;
                    Vector<String> result = new Vector();

                    if (started) {
                        started = false;

                        if (mw == null) {
                            System.out.println("MainWindow es null, no almacenamos nada ");
                        }
                        //TO-DO Aquí en lugar de un dispose hay que hacer que el reproductor de cursos guarde la información de la posición del curso
                        else{
                            result = stopMainWindow(alma);

                        }
                        if (mw_portada != null) {
                            mw_portada.dispose();
                            mw_portada = null;
                        }
                        System.gc();

                        rutascorm = null;
                        nombrecurso = null;
                        System.out.println("//118-11-2010 a false");
                        basededatos = false;
                        
                    }//fuera de rango


                }
            };
            PopupMenu popup = new PopupMenu();
            MenuItem defaultItem = new MenuItem("Exit");
            MenuItem openItem = new MenuItem("Open");
            MenuItem minimizeItem = new MenuItem("Minimize");
            defaultItem.addActionListener(exitListener);
            openItem.addActionListener(openListener);
            minimizeItem.addActionListener(minimizeListener);
            popup.add(openItem);
            popup.add(defaultItem);
            popup.add(minimizeItem);

            final TrayIcon trayIcon = new TrayIcon(image, "Tray Demo", popup);

            ActionListener actionListener = new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    trayIcon.displayMessage("Action Event",
                            "An Action Event Has Been Peformed!",
                            TrayIcon.MessageType.INFO);
                }
            };

            trayIcon.setImageAutoSize(true);
            trayIcon.addActionListener(actionListener);
            trayIcon.addMouseListener(mouseListener);

            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                System.err.println("TrayIcon could not be added.");
            }

        } else {
            System.out.println("System tray is currently not supported.");
        }
    }

    private static void configureXMPPAccount() {

        //obtengo la MAC del equipo donde me estoy ejecutando para
        //poder suscribirme a los eventos de este equipo
        //agentBTId = "00:13:02:5F:A2:F6";
        agentBTId = getMacAddress();

        //Leemos el fichero de configuracion
        clientOptions = readOptions();

        //direccion XMPP que usará el cliente Edutainment para comunicarse con el servidor de localización
        clientXMPPUser = clientOptions.getProperty("clientXMPPUser", clientXMPPUser);
        clientXMPPDomain = clientOptions.getProperty("clientXMPPDomain", clientXMPPDomain);
        clientXMPPPassword = clientOptions.getProperty("clientXMPPPassword", clientXMPPPassword);

        clientXMPPServer = clientOptions.getProperty("clientXMPPServer", clientXMPPServer);

        userId = clientOptions.getProperty("userId", userId);
        userEmail = clientOptions.getProperty("userEmail", userEmail);
        //identifica al dispositivo bluetooth que queremos detectar
        userBTId = clientOptions.getProperty("userBTId", userBTId);
        //dirección XMPP del servidor de localización
        locserverAddr = clientOptions.getProperty("locserverAddr", locserverAddr);

        //Si está comentado en el fichero properties, no la modifica
        //dejamos esta linea por si acaso tenemos algún problema
        //poder cambiar la mac desde el fichero
        agentBTId = clientOptions.getProperty("agentBTId", agentBTId);
        agentBTName = clientOptions.getProperty("agentBTName", agentBTName);
    }

    private static void readArguments(String[] args) {
        // Los argumentos son o la rutaScorm de un curso
        //o una lista con todos los cursos disponibles

        if (args.length >= 1) {
            int offset = 0;
            //esto es debido a q a veces lo pone a veces no...depende linux/windows
            if ((args[0].compareTo("null") != 0) && (args[0].compareTo("\"null\"") != 0)) {
                String total = args[0];

                if (total.contains("\"")) {
                    offset = 1;
                }
                if (total.contains("rutaCurso")) {
                    maxim = true;
                    rutascorm = total.substring(total.indexOf("=") + 1, total.lastIndexOf("/") + 1);
                    nombrecurso = total.substring(total.lastIndexOf("/") + 1, total.length() - offset) + "/";
                    System.out.println("De los argumentos de entrada obtengo :\n RutaScorm: " + rutascorm + "\n NombreCurso: " + nombrecurso);
                }
                if (total.contains("vector")) {
                    maxim = true;
                    listaCursos = new Vector<String>();
                    System.out.println("Extraer bien los cursos");
                    String[] prueba = total.split(",");
                    for (int i = 0; i < prueba.length; i++) {
                        System.out.println(prueba[i] + "\n");
                    }

                    listaCursos.add(prueba[0].substring(prueba[0].indexOf("=") + 2));
                    for (int i = 1; i < prueba.length - 1; i++) {
                        listaCursos.add(prueba[i]);
                    }
                    listaCursos.add(prueba[prueba.length - 1].substring(0, prueba[prueba.length - 1].length() - 2));
                    /*
                     * total=total.substring(total.indexOf("=") + 2, total.length() - 1);
                    for (int i = 1; i < args.length - 1; i++) {
                    listaCursos.add(args[i].substring(0, args[i].length() - 1));
                    }
                     * listaCursos.add(args[args.length - 1].substring(0, args[args.length - 1].length() - 1 - offset));
                     * */



                    System.out.println("De los argumentos de entrada obtengo la lista de cursos: ");
                    for (int j = 0; j < listaCursos.size(); j++) {
                        System.out.println(listaCursos.get(j));
                    }
                }

            }
        }
    }

    private static String getMacAddress() {

        String[] results = null;
        try {
            String line;
            boolean encontrado = false;

            String[] cmd = {"cmd.exe", "/c", "ipconfig /all"};
            Pattern pattern = Pattern.compile("Direcci");
            Matcher matcher = pattern.matcher("");

            Process p = Runtime.getRuntime().exec(cmd);

            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));

            while ((line = input.readLine()) != null) {
                matcher.reset(line);
                if (matcher.find()) {
                    results = line.split(": ");
                    encontrado = true;
                    break;
                }
            }
            input.close();
            if (!encontrado) {

                Pattern pattern2 = Pattern.compile("Physical Address");
                Matcher matcher2 = pattern2.matcher("");

                BufferedReader input2 = new BufferedReader(new InputStreamReader(p.getInputStream()));

                while ((line = input2.readLine()) != null) {
                    matcher2.reset(line);
                    if (matcher2.find()) {
                        results = line.split(": ");
                        encontrado = true;
                        break;
                    }
                }
                input2.close();
            }



        } catch (Exception e) {

            e.printStackTrace();
        }
        String result = results[1].replace('-', ':');
        return result;

        //Lo que hace el agente BT
        /*
        if sys.platform == 'win32':
        mac=''
        for line in os.popen('ipconfig /all'):
        if line.lstrip().startswith('Physical Address'):
        mac = line.split(':')[1].strip().replace('-',':')
        break
        if mac == '':
        #Si el SO no esta en ingles lo anterior no funciona, probamos en espanhol
        for line in os.popen('ipconfig /all'):
        if line.lstrip().startswith('Direcci'):
        mac = line.split(':')[1].strip().replace('-',':')
        break
        else:
        for line in os.popen('/sbin/ifconfig'):
        if line.find('Ether') > -1:
        mac = line.split()[4]
        break
        return mac
         */


        //El original hecho por Gonzalo
        /*
        String macAddr = "";
        try {
        Enumeration<NetworkInterface> netIfaces = NetworkInterface.getNetworkInterfaces();
        while (netIfaces.hasMoreElements()) {
        NetworkInterface netIface = netIfaces.nextElement();
        System.out.println(netIface.getDisplayName());
        if (netIface.getDisplayName().toLowerCase().contains("ethernet")) {
        byte[] ethMac = netIface.getHardwareAddress();
        //System.out.println(ethMac.length);
        //System.out.println(StringUtils.encodeHex(ethMac));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        for (int i = 0; i < ethMac.length; i++) {
        //System.out.format("%02X%s", ethMac[i], (i < ethMac.length - 1) ? ":" : "");
        ps.format("%02X%s", ethMac[i], (i < ethMac.length - 1) ? ":" : "");
        }
        macAddr = baos.toString();
        break;
        }
        }
        } catch (SocketException ex) {
        ex.printStackTrace();
        }
        return macAddr;
         */

    }

    private static Properties readOptions() {


        // String FICHERO_CONFIGURACION = System.getProperty("user.dir") + File.separator + "config" + File.separator + "edutainment" + File.separator + "options.properties";

        //System.out.println("Fichero de configuración " + FICHERO_CONFIGURACION);
        InputStream is = null;

        // is = new FileInputStream(new File(FICHERO_CONFIGURACION));

        is = Main.class.getResourceAsStream("/config/options.properties");
        //prop.load(is);


        Properties options = new Properties();
        try {
            options.load(is);
            //options.load(Main.class.getResourceAsStream("/edutainmentclient/config/options.properties"));
            // options.load(new FileInputStream("edutainmentclient/config/options.properties"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return options;
    }

    public static void edutainmentStopEvent(String courseId, String scoId, String timestamp) {
        String rplMessage = "";
        rplMessage += "<edutainment type=\"clientStopEvent\">" + "\n";
        if (courseId != null) {
            rplMessage += "\t" + "<course>" + "\n";
            rplMessage += "\t\t" + "<id>" + courseId + "</id>" + "\n";
            if (scoId != null) {
                rplMessage += "\t\t" + "<sco id=\"" + scoId + "\" timestamp=\"" + timestamp + "\"/>" + "\n";
            }
            rplMessage += "\t\t" + "<courseURL>" + "abc" + "</courseURL>" + "\n";
            rplMessage += "\t" + "</course>" + "\n";
        }
        rplMessage += "</edutainment>";
        System.out.println("Stop event sending " + rplMessage);
        xmppService.sendMessage(edutainmentServerAddr, rplMessage);
    }

    private static void edutainmentStartRequestMessage(EdutainmentMessage em, Message message) {
        System.out.println("Start request received");

//ojo aqui deberíamos hacer aunque ya esté iniciado (FORZAR UN PUNTO)
        if (!started) {
            if (em.getCourseId().equals("")) {
                System.out.println("No envió ningún punto en la request");
                //forzar=true;
                //DBAccessImplementation.getInstance().deleteAllPoints();
                if (!em.getUserId().equals("")) {
                    mw_portada = new MainWindow_portada(em.getUserId(), listaCursos);
                } else //usamos el usuario por defecto....
                {
                    mw_portada = new MainWindow_portada(userId, listaCursos);
                }
                mw_portada.init();
                started = true;


            } else {
                System.out.println("Envió un punto en la request");
                System.out.println("courseURL: " + em.getcourseURL() + "courseid: " + em.getCourseId() + " scoId: " + em.getScoId() + " userId: " + em.getUserId() + " timestamp: " + em.getScoTimestamp() + " coursePath: " + em.getScoPath());
                String r1 = em.getcourseURL().substring(0, em.getcourseURL().length() - 1);
                rutascorm = r1.substring(0, r1.lastIndexOf("/") + 1);

                nombrecurso = r1.substring(r1.lastIndexOf("/") + 1, r1.length()) + "/";

                //DBAccessImplementation.getInstance().deleteAllPoints();
                System.out.println(rutascorm + " " + nombrecurso + " ");

                //DBAccessImplementation.getInstance().storeLastSco(rutascorm + nombrecurso, em.getCourseId(), em.getUserId(), em.getScoId(), em.getScoPath(), Float.toString(em.getScoTimestamp()));

                if (!em.getUserId().equals("")) {
                    mw = new MainWindow(em.getUserId(), rutascorm + nombrecurso, em.getCourseId(), em.getScoId(), em.getScoPath(), Float.toString(em.getScoTimestamp()), false);
                } else {
                    mw = new MainWindow(userId, rutascorm + nombrecurso, em.getCourseId(), em.getScoId(), em.getScoPath(), Float.toString(em.getScoTimestamp()), false);
                }
                mw.init();
                started = true;
            }

            String rplMessage = "";
            rplMessage += "<edutainment type=\"clientStartRes\">" + "\n";
            rplMessage += "\t" + "<status>ok</status>" + "\n";
            rplMessage += "</edutainment>";
            System.out.println("Enviamos el siguiente mensaje2: ");
            System.out.println(rplMessage);
            xmppService.sendMessage(message.getFrom(), rplMessage);

        } else {
            //aqui si ya esta iniciado, empezarlo en otro punto
            String rplMessage = "";
            rplMessage += "<edutainment type=\"clientStartRes\">" + "\n";
            rplMessage += "\t" + "<status>error</status>" + "\n";
            rplMessage += "</edutainment>";
            System.out.println("Enviamos el siguiente mensaje2: ");
            System.out.println(rplMessage);
            xmppService.sendMessage(message.getFrom(), rplMessage);
        }


    }

    private static void edutainmentStopRequestMessage(Message message) {
        System.out.println("started " + started);
        if (started) {
            //almaceno o no?
            //almacenar true
            //no almacenar false
            Vector<String> datos = locationEventOutRangeMessage(false);
            //System.out.println(datos);
            if (mw == null) {
                System.out.println("mw es null");
            }
            //String courseId = mw.getCourseLoader().getCourseId();
            //String scoId = DBAccessImplementation.getInstance().getLastScoId(courseId, userId);
            //String timeStamp = DBAccessImplementation.getInstance().getScoPoint(scoId, userId);
            // float timeStampf = Float.parseFloat(timeStamp);
            String rplMessage = "";
            rplMessage += "<edutainment type=\"clientStopRes\">" + "\n";
            rplMessage += "\t" + "<status>ok</status>" + "\n";
            if (datos.size() > 0) {
                rplMessage += "\t" + "<course>" + "\n";
                rplMessage += "\t\t" + "<id>" + datos.get(0) + "</id>" + "\n";
                if (datos.size() > 1) {
                    rplMessage += "\t\t" + "<sco id=\"" + datos.get(1) + "\" timestamp=\"" + datos.get(2) + "\" scoPath=\"" + datos.get(3) + "\"/>" + "\n";

                }
                rplMessage += "\t\t" + "<url>" + rutascorm + nombrecurso + "</url>" + "\n";
                rplMessage += "\t" + "</course>" + "\n";
            }
            rplMessage += "</edutainment>";
            System.out.println("Enviamos el siguiente mensaje3: ");
            System.out.println(rplMessage);
            xmppService.sendMessage(message.getFrom(), rplMessage);
            rutascorm=null;
            nombrecurso=null;
            /*
            if (mw_portada != null) {
            mw_portada.dispose();
            mw_portada = null;
            }
            if (mw != null) {
            stopMainWindow();
            mw.dispose();
            mw = null;
            }

             */
            //Ya lo pone el location OUT
            // started = false;
        } else {
            String rplMessage = "";
            rplMessage += "<edutainment type=\"clientStopRes\">" + "\n";
            rplMessage += "\t" + "<status>error</status>" + "\n";
            //rplMessage += "\t" + "<code></code>" + "\n";
            //rplMessage += "\t" + "<reason>player wasn't started</reason>" + "\n";
            rplMessage += "</edutainment>";
            System.out.println("Enviamos el siguiente mensaje4: ");
            System.out.println(rplMessage);
            xmppService.sendMessage(message.getFrom(), rplMessage);
        }
    }

    private static void edutainmentPingRequestMessage(Message message) {
        String rplMessage = "";
        rplMessage += "<edutainment type=\"pingRes\">" + "\n";
        rplMessage += "\t" + "<status>ok</status>" + "\n";
        rplMessage += "</edutainment>";
        xmppService.sendMessage(message.getFrom(), rplMessage);
    }

    private static void edutainmentContentRequestMessage(Message message) {
        String courseId = "";
        String scoId = "";
        String scoPoint = "0";
        String scoPath = "";
        if (started) {
            if (mw != null) {


                JInternalFrame jif = mw.panel.getSelectedFrame();
                courseId = mw.getCourseLoader().getCourseId();
                // result.add(courseId);
                if (jif instanceof VentanaSeleccionUnidad) {
                    VentanaSeleccionUnidad vsu = (VentanaSeleccionUnidad) jif;
                    VentanaSeleccionUnidad vsup;

                } else if (jif instanceof VentanaSCO) {
                    VentanaSCO vsco = (VentanaSCO) jif;
                    AppletTemplateComponentsXML atcx = vsco.getAtcx();
                    //Variables a almacenar en la base de datos
                    scoId = atcx.vsup.unidadPrincipal.getSubUnits()[atcx.vsup.focused].getIdentifier();

                    //String scoPath = "";

                    for (int d = 0; d < atcx.playersName.size(); d++) {
                        String mediaPanel = (String) atcx.playersName.get(d);
                        //SSS 26102009 esto no lo tengo pero parece que no lo usa
                        MediaPanel mp = (MediaPanel) atcx.players.get(mediaPanel);
                        //Si no es test hay que guardar el instante de tiempo

                        if (!atcx.ESTEST) {
                            scoPoint = String.valueOf(mp.getTime());
                            if (mp.getTime() >= mp.getDuration()) {
                                scoPoint = "0";
                            }
                        }
                    }
                    VentanaSeleccionUnidad vsu = atcx.vsup;
                    VentanaSeleccionUnidad vsup;
                    while (vsu != null) {
                        vsup = vsu.vsupadre;

                        String itemId = vsu.unidadPrincipal.getSubUnits()[vsu.focused].getIdentifier();

                        if (!itemId.equals(scoId)) {
                            if (scoPath.equals("")) {
                                scoPath = itemId;
                            } else {
                                scoPath = itemId + " " + scoPath;
                            }
                        }
                        if (vsup == null) {
                            scoPath = vsu.unidadPrincipal.getIdentifier() + " " + scoPath;
                        }
                        vsu = vsup;
                        //vsup = vsup.vsupadre;
                    }

                    System.out.println("puntos a almacenar: ");
                    System.out.println(courseId);
                    System.out.println(scoId);
                    System.out.println(scoPoint);
                    System.out.println(scoPath);
                }
            }
            String rplMessage = "";
            rplMessage += "<edutainment type=\"getContentRes\">" + "\n";
            rplMessage += "<status>ok</status>" + "\n";
            if (courseId.compareTo("") != 0) {
                rplMessage += "\t" + "<course>" + "\n";
                rplMessage += "\t" + "<id>" + courseId + "</id>" + "\n";
                if (scoId.compareTo("") != 0) {
                    rplMessage += "\t" + "<sco id=\"" + scoId + "\" timestamp=\"" + scoPoint + "\" coursePath=\"" + scoPath + "\"/>" + "\n";
                }
                rplMessage += "\t" + "<url>" + rutascorm + nombrecurso + "</url>" + "\n";
                rplMessage += "\t" + "</course>" + "\n";
            }
            rplMessage += "</edutainment>";
            xmppService.sendMessage(message.getFrom(), rplMessage);
        } else {
            String rplMessage = "";
            rplMessage += "<edutainment type=\"getContentRes\">" + "\n";
            rplMessage += "\t" + "<status>error</status>" + "\n";
            //rplMessage += "\t" + "<code></code>" + "\n";
            //rplMessage += "\t" + "<reason>player wasn't started</reason>" + "\n";
            rplMessage += "</edutainment>";
            System.out.println("Enviamos el siguiente mensaje4: ");
            System.out.println(rplMessage);
            xmppService.sendMessage(message.getFrom(), rplMessage);
        }
    }

    private static void edutainmentErrorRequestMessage(EdutainmentMessage em, Message message) {

        String rplMessage = "";
        switch (em.getErrorCode()) {
            case EdutainmentMessage.NOT_XML_FORMAT:
                rplMessage += "<edutainment type=\"errorRes\">\n\t<status>error</status>\n\t<code>401</code>\n\t<reason>Message is not in XML format</reason>\n</edutainment>";
                break;
            case EdutainmentMessage.NOT_EDUTAINMENT_MESSAGE:
                rplMessage += "<edutainment type=\"errorRes\">\n\t<status>error</status>\n\t<code>402</code>\n\t<reason>Not an edutainment message</reason>\n</edutainment>";
                break;
            case EdutainmentMessage.NO_SUCH_MESSAGE_TYPE:
                rplMessage += "<edutainment type=\"errorRes\">\n\t<status>error</status>\n\t<code>403</code>\n\t<reason>Not such message type</reason>\n</edutainment>";
                break;
            case EdutainmentMessage.MISSING_USER_ID:
                rplMessage += "<edutainment type=\"clientStartRes\">\n\t<status>error</status>\n\t<code>404</code>\n\t<reason>Missing user ID</reason>\n</edutainment>";
                break;
        }
        System.out.println("Enviamos el siguiente mensaje5: ");
        System.out.println(rplMessage);
        xmppService.sendMessage(message.getFrom(), rplMessage);
    }

    private static void edutainmentMessageReceived(Message message) {

        EdutainmentMessage em = new EdutainmentMessage();
        if (em.parseMessage(message)) {
            edutainmentServerAddr = message.getFrom();
            System.out.println("Recibido un mensaje de Edutainment");
            if (em.getMessageTypeCode() == EdutainmentMessage.START_REQUEST) {
                edutainmentStartRequestMessage(em, message);

            } else if (em.getMessageTypeCode() == EdutainmentMessage.STOP_REQUEST) {
                edutainmentStopRequestMessage(message);

            } else if (em.getMessageTypeCode() == EdutainmentMessage.PING_REQUEST) {
                edutainmentPingRequestMessage(message);

            } else if (em.getMessageTypeCode() == EdutainmentMessage.CONTENT_REQUEST) {
                edutainmentContentRequestMessage(message);

            }
        } else {
            edutainmentErrorRequestMessage(em, message);
            //Se produjo un error al parsear el mensaje, creamos el mensaje de respuesta
        }
    }

    private static void locationAnswerMessage(LocationMessage lm, Message message) {
        System.out.println("Mensaje de respuesta:");
        System.out.println("Result: " + lm.getResult());
        System.out.println("Code: " + lm.getCode());
        System.out.println("Text: " + lm.getText());

        switch (expectedAnswerType) {
            case NONE://Esto no debería ocurrir, si no estamos esperando un mensaje tipo ans no debería llegar ninguno
                System.out.println("*******Error inesperado");
                break;

            case DEVICE_ATT:
                System.out.println("Recibido un mensaje de respuesta a la solicitud de una attachment");
                //TO-DO Comprobar que el attachment se realizó correctamente y en caso contrario repetirlo de alguna forma
                expectedAnswerType = NONE;
                break;

            case DEVICE_DET:
                System.out.println("Recibido un mensaje de respuesta a la solicitud de una dettachment");
                //TO-DO Comprobar que el dettachment se realizcó correctamente y en caso contrario repetirlo de alguna forma
                expectedAnswerType = NONE;
                break;

            case RULE_CREATION:
                System.out.println("Recibido un mensaje de respuesta a la solicitud de una creación de regla");
                if ((lm.getResult().equals("true")) && (lm.getCode().equals("200"))) {//Comprobamos si la regla se creó correctamente
                    String splitedText[] = lm.getText().split(" ");
                    ruleId = splitedText[1].substring(1, splitedText[1].length() - 1);
                    System.out.println("ruleId: " + ruleId);

                }
                expectedAnswerType = NONE;
                break;

            case RULE_DELETION:
                System.out.println("Recibido un mensaje de respuesta a la solicitud de una eliminación de regla");
                if ((lm.getResult().equals("true")) && (lm.getCode().equals("200"))) {//Comprobamos si la regla se eliminó correctamente
                    String splitedText[] = lm.getText().split(" ");
                    System.out.println(splitedText[1]);
                    String receivedRuleId = splitedText[1].substring(1, splitedText[1].length() - 1);
                    if (receivedRuleId.equals(ruleId)) {
                        System.out.println("La regla fue eliminada correctamente");
                    } else {
                        System.out.println("Hubo algún error al eliminar la regla");
                    }
                }
                expectedAnswerType = NONE;
                break;

        }
    }

    private static void locationEventInRangeMessage() {
        //dentro del rango
        System.out.println("Localizado el usuario " + userId + " dentro del rango");
        //analizar la siguiente situación:
        //esta un usuario delante pq le dio a open
        //y el servidor de localización localiza a otro
        if (!started) {
            Vector allPoints = new Vector();
            allPoints = DBAccessImplementation.getInstance().getAllPoints();
            System.out.println("Todos los datos de la tabla:");
            System.out.println(allPoints);
            //19-11-2010
            //aquí ponia o listaCursos==null
            if ((((Vector) allPoints.get(0)).size() != 0) || (rutascorm != null)) {
                System.out.println("Hay algún punto almacenado, empiezo desde ahí3");
                Vector punto = (Vector) allPoints.get(5);
                 int ultimo=punto.size()-1;
                String courseURL = (String) punto.get(ultimo);
                String r1 = courseURL.substring(0, courseURL.length() - 1);
                rutascorm = r1.substring(0, r1.lastIndexOf("/") + 1);
                System.out.println("r1 " + r1);
                nombrecurso = r1.substring(r1.lastIndexOf("/") + 1, r1.length()) + "/";
                System.out.println("//118-11-2010 c");
                basededatos = true;
                System.out.println("rutascorm " + rutascorm + " nombrecurso " + nombrecurso);
                mw = new MainWindow((String) ((Vector) allPoints.get(1)).get(ultimo), false);
                // mw = new MainWindow((String)((Vector)allPoints.get(1)).get(0), courseURL, (String)((Vector)allPoints.get(0)).get(0),(String)((Vector)allPoints.get(2)).get(0), (String)((Vector)allPoints.get(3)).get(0), (String)((Vector)allPoints.get(4)).get(0), false);
                mw.init();

            } else {
                System.out.println("Entramos por portada");
                mw_portada = new MainWindow_portada(userId, listaCursos);
                mw_portada.init();

            }
            started = true;
        }
    }

    private static Vector<String> stopMainWindow(boolean almacenar) {
        System.out.println("--------------->stopMainWindow");
        boolean alma = almacenar;
        Vector<String> result = new Vector();
        if (mw.bgMusicPlayer != null) {
            mw.bgMusicPlayer.removeControllerListener(mw);
            mw.bgMusicPlayer.stop();
            mw.bgMusicPlayer.setMediaTime(new Time(0));
            mw.bgMusicPlayer.close();
        }

        JInternalFrame jif = mw.panel.getSelectedFrame();
        String courseId = mw.getCourseLoader().getCourseId();
        result.add(courseId);
        if (jif instanceof VentanaSeleccionUnidad) {
            if (alma) {
                DBAccessImplementation.getInstance().storeLastSco(rutascorm + nombrecurso, courseId, userId, "", "", "");
            }
            VentanaSeleccionUnidad vsu = (VentanaSeleccionUnidad) jif;
            VentanaSeleccionUnidad vsup;

            while (vsu != null) {
                vsup = vsu.vsupadre;
                vsu.setVisible(false);
                mw.panel.remove(vsu);
                vsu.dispose();
                vsu = vsup;
                //vsup = vsup.vsupadre;
            }

        } else if (jif instanceof VentanaSCO) {//Si es una ventana de SCO guardamos el estado
            System.out.println("Almacenando el SCO actual en la base de datos");
            VentanaSCO vsco = (VentanaSCO) jif;

            AppletTemplateComponentsXML atcx = vsco.getAtcx();
            //Variables a almacenar en la base de datos
            String scoId = atcx.vsup.unidadPrincipal.getSubUnits()[atcx.vsup.focused].getIdentifier();
            String scoPoint = "0";
            String scoPath = "";
            //String userid;


            //Lo primero es detener los reproductores y los hilos
            atcx.okcomponents.clear();
            atcx.wrongcomponents.clear();
            atcx.HILOS.clear();

            for (int d = 0; d < atcx.playersName.size(); d++) {
                String mediaPanel = (String) atcx.playersName.get(d);
                //SSS 26102009 esto no lo tengo pero parece que no lo usa
                MediaPanel mp = (MediaPanel) atcx.players.get(mediaPanel);
                //Si no es test hay que guardar el instante de tiempo

                if (!atcx.ESTEST) {
                    scoPoint = String.valueOf(mp.getTime());
                    if (mp.getTime() >= mp.getDuration()) {
                        scoPoint = "0";
                    }
                    System.out.println("Punto a almacenar: " + scoPoint);
                }
                atcx.jButtonStopActionPerformed(mediaPanel);
                mp.mediaPlayer.close();
            }
            //SSS 26102009 para controlar el next
            atcx.NEXT = false;
            vsco.dispose();

            VentanaSeleccionUnidad vsu = atcx.vsup;
            VentanaSeleccionUnidad vsup;

            while (vsu != null) {
                vsup = vsu.vsupadre;
                vsu.setVisible(false);
                mw.panel.remove(vsu);
                String itemId = vsu.unidadPrincipal.getSubUnits()[vsu.focused].getIdentifier();

                if (!itemId.equals(scoId)) {
                    if (scoPath.equals("")) {
                        scoPath = itemId;
                    } else {
                        scoPath = itemId + " " + scoPath;
                    }
                }
                if (vsup == null) {
                    scoPath = vsu.unidadPrincipal.getIdentifier() + " " + scoPath;
                }
                vsu.dispose();
                vsu = vsup;
                //vsup = vsup.vsupadre;
            }
            System.out.println("rutaScormmmm " + rutascorm + " nombreCurso " + nombrecurso);

            if (alma) {
                DBAccessImplementation.getInstance().storeLastSco(rutascorm + nombrecurso, courseId, userId, scoId, scoPath, scoPoint);
            }

            result.add(scoId);
            result.add(scoPoint);
            result.add(scoPath);

        }
        mw.panel.setVisible(false);
        mw.remove(mw.panel);
        mw.panel = null;
        mw.removeAll();
        mw.setVisible(false);
        mw.dispose();
        mw = null;
        return result;
    }

    private static Vector<String> locationEventOutRangeMessage(boolean almacenar) {
        boolean alma = almacenar;
        //return Vector<String> que contiene:
        // courseId, scoId y timestamp;
        Vector<String> result = new Vector();
        //fuera de rango
        System.out.println("locationEventOutRangeMessage started: " + started);
        if (started) {
            //fuera del rango
            System.out.println("El usuario " + userId + " ha salido del rango");

            if (mw == null) {
                System.out.println("MainWindow es null");
            }
            //TO-DO Aquí en lugar de un dispose hay que hacer que el reproductor de cursos guarde la información de la posición del curso
            if (mw != null) {
                result = stopMainWindow(alma);

            }
            if (mw_portada != null) {
                //no almaceno nada pq portada
                mw_portada.dispose();
                mw_portada = null;
            }
            System.gc();
            started = false;
            
        }//fuera de rango
        else {
            //reproductor no iniciado no hacemos nada
        }
        return result;
    }

    private static void locationEventMessage(LocationMessage lm) {
        System.out.println("Se ha recibido información de localización correspondiente a la regla con id " + lm.getRuleId());
        System.out.println("Lugar:\n\t- " + lm.getLocName() + "\n\t- " + lm.getLocCoor() + "\n\t- " + lm.getLocDate());
        System.out.println("Dispositivos:");

        for (int i = 0; i < lm.getvPairs().size(); i++) {
            Pair pair = lm.getvPairs().elementAt(i);
            System.out.println("\t- deviceId: " + pair.getDeviceId() + "\tinRange: " + pair.isDeviceInRange() + "\tuserId: " + pair.getUserId());
        }
        int pairsSize = lm.getvPairs().size();
        if (lm.getRuleId().equals(ruleId)) {
            System.out.println("coincide con la regla que buscamos");
            //Si el evento corresponde con la regla que definimos lo procesamos, sino lo descartamos
            //Vamos a considerar el principio que solo nos van a informar de una pareja de usario-dispositivo
            if (pairsSize == 1) {
                Pair pair = lm.getvPairs().elementAt(0);
                if (pair.getUserId().equals(userId)) {
                    if (pair.isDeviceInRange()) {
                        locationEventInRangeMessage();
                    } else {
                        locationEventOutRangeMessage(true);
                        rutascorm=null;
                         nombrecurso=null;
                    }
                } else {
                    //llega información de otro usuario
                    System.out.println("Esta información de localización no debería de haber llegado, la descartamos");
                    System.out.println("Deteniendo el reproductor de cursos para el usuario " + userId);
                }
            } else if (pairsSize > 1) {
                //Pair size >1
                //TO-DO Unimplemented
            }
        }
    }

    private static void locationMessageReceived(Message message) {
        LocationMessage lm = new LocationMessage();
        if (lm.parseMessage(message)) {
            if (lm.getMessageTypeCode() == LocationMessage.ANSWER_MESSAGE) {
                locationAnswerMessage(lm, message);
            } else if (lm.getMessageTypeCode() == LocationMessage.EVENT_MESSAGE) {
                locationEventMessage(lm);
            }//event message
        } else {
            //location message
        }
    }
}


