/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * PacMP_Launcher.java
 *
 * Created on 10.07.2009, 13:09:43
 */

package pacmp;

import java.io.*;
import java.net.URL;
import javax.swing.*;

/**
 *
 * @author Benjamin
 */
public class PacMP_Launcher extends javax.swing.JDialog {

    /** Creates new form PacMP_Launcher */
    public PacMP_Launcher(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    private void messageBox(String message)
    {
        JOptionPane.showConfirmDialog(
                null,
                message,
                "alert",
                JOptionPane.OK_OPTION);
    }

    /**
     * Speichert die aktuellen Werte in die nums.sav.
     */
    private void writeNumsSav() 
    {
        try
        {
            BufferedWriter out = new BufferedWriter(new FileWriter("saves\\nums.sav"));
            out.write("session_id = " + Integer.toString(m_session) + "\n");
            out.write("player_id = " + Integer.toString(m_player) + "\n");
            out.write("wm_x = 0\n");
            out.write("wm_y = 0\n");
            out.write("other_x = 0\n");
            out.write("other_y = 0\n");
            out.close();
        }

        catch(IOException ex)
        {
            messageBox("Fehler beim Schreiben von nums.sav.");
        }
    }

    /**
     * Thread zum Synchronisieren mit dem Server.
     * Alle 0.3 Sekunden wird die aktuelle Position an den Server geschickt
     * und die Antwort, also die Position des anderen Spielers, in die
     * nums.sav gespeichert.
     */
    private class Synchronizer implements Runnable
    {
        private int m_session;
        private int m_player;
        private String m_server;
        private int m_x, m_y;
        private int m_otherx, m_othery;
        private boolean m_changes;

        public Synchronizer(int session, int player, String server)
        {
            m_session = session;
            m_player = player;
            m_server = server;
            m_x = m_y = 0;
            m_otherx = m_othery = 0;
            m_changes = false;
        }

        public void run()
        {
            while (true)
            {
                try
                {
                    Thread.sleep(1000);
                }
                catch(InterruptedException ex)
                {
                    // ka was ich hier machen soll...
                }

                readNumsSav();
                syncWithServer();
                if (m_changes) writeNumsSav();
            }
        }

        /**
         * Liest die eigenen Koordinaten aus der nums.sav.
         * @throws IOException
         */
        private void readNumsSav() 
        {
            try
            {
                // Datei kopieren um PaC-DK möglichst nicht in die Quere zu kommen
                try { Runtime.getRuntime().exec("extract.bat").waitFor(); }
                catch(InterruptedException ex) { System.out.println("copy interrupted"); }
                
                // Datei lesen
                BufferedReader in = new BufferedReader(new FileReader("saves\\nums2.sav"));
                String line;
                while((line = in.readLine()) != null)
                {
                    if (line.startsWith("wm_x = "))
                        m_x = Integer.parseInt( line.substring(7) );
                    if (line.startsWith("wm_y = "))
                        m_y = Integer.parseInt( line.substring(7) );
                }
                in.close();
            }
            
            catch(IOException ex)
            {
                System.out.println("Fehler beim Lesen von nums.sav");
            }
        }

        /**
         * Speichert die aktuellen Werte in die nums.sav.
         */
        private void writeNumsSav() 
        {
            try
            {
                System.out.println( "Positionsupdate: " + Integer.toString(m_otherx) +
                                    "/" + Integer.toString(m_othery) );
                // in separate Datei schreiben, um PaC-DK nicht in die Quere zu kommen
                BufferedWriter out = new BufferedWriter(new FileWriter("saves\\nums2.sav"));
                out.write("session_id = " + Integer.toString(m_session) + "\n");
                out.write("player_id = " + Integer.toString(m_player) + "\n");
                out.write("wm_x = " + Integer.toString(m_x) + "\n");
                out.write("wm_y = " + Integer.toString(m_y) + "\n");
                out.write("other_x = " + Integer.toString(m_otherx) + "\n");
                out.write("other_y = " + Integer.toString(m_othery) + "\n");
                out.close();

                // rüberkopieren
                try { Runtime.getRuntime().exec("replace.bat").waitFor(); }
                catch(InterruptedException ex) { System.out.println("replace interrupted"); }
            }

            catch(IOException ex)
            {
                System.out.println("Fehler beim Schreiben von nums.sav");
            }
        }

        /**
         * Synchronisiert mit dem Server.
         * Aktuelle Werte werden an den Server geschickt und Position des
         * anderen Spielers als Antwort empfangen.
         */
        private void syncWithServer()
        {
            // Nicht synchronisieren wenn Position vom Spiel noch nicht
            // gesetzt wurde.
            if (m_x == 0) return;

            try
            {
                // URL basteln
                String request = m_server + "/pac-mp.php?" +
                                 "sid=" + Integer.toString(m_session) +
                                 "&pid=" + Integer.toString(m_player) +
                                 "&x=" + Integer.toString(m_x) +
                                 "&y=" + Integer.toString(m_y);

                // Werte an Server senden
                URL url = new URL(request);
                Object obj = url.getContent();
                if (obj instanceof java.io.InputStream)
                {
                    // Prüfen ob Antwort gültig ist
                    InputStream stream = (InputStream)obj;
                    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                    String response = reader.readLine();

                    try
                    {
                        if (response == null) throw new NumberFormatException();
                        int pos = response.indexOf(" ");

                        int newx = Integer.parseInt(response.substring(0, pos));
                        int newy = Integer.parseInt(response.substring(pos+1));

                        m_changes = (newx != m_otherx || newy != m_othery);
                        if (m_changes) 
                        {
                            m_otherx = newx;
                            m_othery = newy;
                        }
                    }
                    catch(NumberFormatException ex)
                    {
                        System.out.println("Ungueltige Antwort vom Server: " + response);
                    }
                }
                else
                {
                    System.out.println("Server lieferte Kauderwelsch zurueck.");
                }
            }

            catch(java.net.MalformedURLException ex)
            {
                System.err.println("Ungueltige URL");
            }

            catch(java.io.IOException ex)
            {
                System.err.println("Server nicht erreichbar");
            }
        }
    };

    /**
     * Startet das Spiel und den Synchronizer.
     */
    private void startGame()
    {
        try
        {
            // Spiel starten
            java.lang.Process game = Runtime.getRuntime().exec("pacmp.exe");
            if (game == null) 
            {
                messageBox("pacmp.exe konnte nicht gestartet werden.");
                return;
            }

            // Synchronizer Thread starten
            Synchronizer sync = new Synchronizer(m_session, m_player, txtServer.getText());
            new Thread(sync).start();
        }

        catch(java.io.IOException ex)
        {
            messageBox("pacmp.exe wurde nicht gefunden.");
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        txtServer = new javax.swing.JTextField();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        lblSession = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        btnJoin = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        txtSession = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jLabel1.setText("Server Adresse:");

        txtServer.setText("http://gehirnmutant.de/pacmp");
        txtServer.setToolTipText("Die URL des Servers. Du musst hier das Verzeichnis angeben, in dem sich die pac-mp.php und pac-mp-newgame.php befinden.");

        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jButton1.setText("Spiel erstellen");
        jButton1.setToolTipText("Ein neues Spiel starten. Du bekommst eine Session-ID zugewiesen, die du deinem Mitspieler mitteilen musst, damit er sich mit dir verbinden kann.");
        jButton1.setName("btnHost"); // NOI18N
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jLabel2.setText("Session ID:");

        lblSession.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        lblSession.setText("-");
        lblSession.setName("lblSessionID"); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblSession, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(lblSession)
                    .addComponent(jButton1))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        btnJoin.setText("Spiel beitreten");
        btnJoin.setToolTipText("Einem bestehenden Spiel beitreten. Du musst den gleichen Server verwenden und die Session-ID kennen, um beitreten zu können.");
        btnJoin.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnJoinActionPerformed(evt);
            }
        });

        jLabel4.setText("Session ID:");

        txtSession.setToolTipText("Session-ID zum Beitreten. Derjenige, der das Spiel aufgemacht hat, muss dir die Session-ID mitteilen.");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addComponent(btnJoin)
                .addGap(18, 18, 18)
                .addComponent(jLabel4)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtSession, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnJoin)
                    .addComponent(jLabel4)
                    .addComponent(txtSession, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(9, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(txtServer, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 263, Short.MAX_VALUE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 47, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed

        try
        {
            // Neue Session vom Server anfordern
            URL url = new URL(txtServer.getText() + "/pac-mp-newgame.php");
            Object obj = url.getContent();
            if (obj instanceof java.io.InputStream)
            {
                // Prüfen ob Antwort gültig ist
                InputStream stream = (InputStream)obj;
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                String response = reader.readLine();

                try
                {
                    m_session = Integer.parseInt(response);
                    m_player = 1;
                    lblSession.setText(response);
                }
                catch(NumberFormatException ex)
                {
                    messageBox("Ungueltige Antwort vom Server: " + response);
                }

                // Spiel starten
                writeNumsSav();
                startGame();
            }
            else
            {
                messageBox("Server lieferte Kauderwelsch zurueck.");
            }
        }

        catch(java.net.MalformedURLException ex)
        {
            System.err.println("Ungueltige URL");
            messageBox("Die angegebene Server-Adresse ist keine gueltige URL.");
        }

        catch(java.io.IOException ex)
        {
            System.err.println("Server nicht erreichbar");
            messageBox("Server nicht erreichbar");
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void btnJoinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnJoinActionPerformed
        try
        {
            m_player = 2;
            m_session = Integer.parseInt(txtSession.getText());
            writeNumsSav();
            startGame();
        }
        catch(NumberFormatException ex)
        {
            messageBox("Ungueltige Session-ID");
        }
    }//GEN-LAST:event_btnJoinActionPerformed

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                PacMP_Launcher dialog = new PacMP_Launcher(new javax.swing.JFrame(), true);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnJoin;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JLabel lblSession;
    private javax.swing.JTextField txtServer;
    private javax.swing.JTextField txtSession;
    // End of variables declaration//GEN-END:variables

    private int m_session;
    private int m_player;
}
