/*
 * NewJFrame.java
 *
 * Created on 14. November 2006, 20:50
 */

package peer2peer;

import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;


/**
 *
 * @author  Thomas
 */
public class rnclient extends javax.swing.JFrame {
    public int SERVER_UDP_PORT = 2411;
    public String SERVER_ADDRESS = "224.0.0.42";
    public int SERVER_TCP_PORT;
    public int CLIENT_PORT;
    public int CONNECTED;
    public File FILELISTPATH = new File("/home/Thomas/Peer2Peer/build/classes/peer2peer/freigaben.txt");
    public java.util.List SEEDLIST = new ArrayList();
    public java.util.List LEACHLIST = new ArrayList();
    public InetAddress SERVER_TCP_ADDRESS;
    Clientlauscher clauscher;
    Serverlauscher slauscher;
    public Status stat;
    public String SAVEDIR;
        
    
    public void initConfig() {
        
    }
    
    /**
     * Liest die Datei FILELISTPATH ein, und generiert daraus die Freigabeliste
     */
    public void initFileList() {
        String zeile = new String();
        DefaultListModel model = (DefaultListModel) jList1.getModel();
        String[] input = new String[2];
        try {
            BufferedReader reader = new BufferedReader(new FileReader(FILELISTPATH));
            String Textfeld;
            while ((zeile = reader.readLine()) != null) {
            /*
             *inhalt[0] Dateigröße
             *inhalt[1] Dateiname
             */
                zeile=zeile.trim();
                input = zeile.split(" ",2);
                SEEDLIST.add(input);
                
                stat.setStatus(zeile,stat.EMPF);
                try {
                    model.insertElementAt(input[1],0);
                } catch (ArrayIndexOutOfBoundsException e) {
                    e.printStackTrace();
                    stat.setStatus("Fehler beim eintragen der Freigaben von: " + zeile,2);
                }
            }
            
        } catch(IOException e) {
            e.printStackTrace();
            return;
        }
    }
    
    /**
     * Holt per UDP Multicast an SERVER_ADDRESS den TCP Port vom Server, und dessen IP Addresse
     */
    public void getServer() {
	InetAddress address = null;
	try {
	    address = InetAddress.getByName(SERVER_ADDRESS);
            
	} catch(UnknownHostException e) {
	    e.printStackTrace();
	    // System.exit(2);
            return;
	}

	DatagramSocket socket = null;
	try {
	    socket = new DatagramSocket();
            socket.setSoTimeout(10000);
	} catch (SocketException e) {
	    e.printStackTrace();
	    // System.exit(3);
            return;
	}
        
        try {
            String Textfeld = new String();
            
            /*
	    socket.connect(address, SERVER_UDP_PORT);
            Textfeld = jTextArea1.getText();
            jTextArea1.setText(Textfeld + "Versuche zu Server zu verbinden. ("+ address.toString() + ":" + SERVER_UDP_PORT + javax.swing.text.DefaultEditorKit.EndOfLineStringProperty);
            */
            
	    String discover = new String("server_discovery\n");
            byte[] buf = new byte[22];
            byte[] buf2 = new byte[22];
            buf = discover.getBytes();
	    DatagramPacket packet = new DatagramPacket(buf,buf.length,address,SERVER_UDP_PORT);
	    DatagramPacket receive = new DatagramPacket(buf2,buf2.length,address,SERVER_UDP_PORT);
         
	    socket.send(packet);    // sendet "server_discover\n"
            
            //Statusmeldung im Statusfeld
            stat.setStatus(discover,stat.SEND);
            
            socket.receive(receive);                     // empfängt die Antwort vom Server
            SERVER_TCP_ADDRESS = receive.getAddress();   //Sucht die IP Adresse aus dem Antwortpacket herraus
            
	    byte[] data = receive.getData();
	    String data2 = new String(data);
       
            
            //Statusmeldung im Statusfeld
            stat.setStatus(data2,stat.EMPF);
            int index = data2.indexOf("\n");
            if (index == -1) index = data2.length();
            data2 = data2.substring(16,index);         //Port rauskopieren
            
	    SERVER_TCP_PORT = Integer.parseInt(data2);
            
            //Statusmeldung im Statusfeld
            stat.setStatus("Server gefunden! ("+ SERVER_TCP_ADDRESS.toString() + ":" + SERVER_TCP_PORT + ")",2);
	} catch(IOException e) {
	    e.printStackTrace();
	    // System.exit(4);
            return;
	}
    }
    
    /**
     * Startet den Serverlauscher, registriert sich beim Server, sendet die Dateiliste und startet den lausch Thread
     */
    public void connectToServer() {    
        slauscher = new Serverlauscher(this);
        slauscher.register();
        slauscher.sendSeedlist();
        slauscher.start();
    }
    
    public void getFile() {
        
    }
    
    /**
     * Startet den Thread für den Clientlauscher, der auf Anfragen anderer Clients lauscht, setzt ebenfalls den CLIENT_TCP_PORT
     */
    public void initLocalServer() {
        clauscher = new Clientlauscher(this);
        clauscher.start();        
    }
    
    
    /** Creates new form NewJFrame */
    public rnclient() {
        initComponents();
    }
    
    /** 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.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        jFrame1 = new javax.swing.JFrame();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        jFrame2 = new javax.swing.JFrame();
        jProgressBar1 = new javax.swing.JProgressBar();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jToolBar1 = new javax.swing.JToolBar();
        jButton1 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList2 = new javax.swing.JList();
        jLabel2 = new javax.swing.JLabel();
        addButton = new javax.swing.JButton();
        removeButton = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jList3 = new javax.swing.JList();
        getButton = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenu3 = new javax.swing.JMenu();
        about = new javax.swing.JMenuItem();

        jFrame1.setTitle("Info");
        jFrame1.setAlwaysOnTop(true);
        jFrame1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        jFrame1.setEnabled(false);
        jFrame1.setResizable(false);
        jLabel4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/peer2peer/physikshow.png")));

        jLabel5.setText("rnClient");

        jLabel6.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabel6.setText("Peer 2 Peer Client f\u00fcr die Vorlesung");
        jLabel6.setAlignmentY(0.0F);

        jLabel7.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabel7.setText("Rechnernetze I Wintersemester 06/07");
        jLabel7.setAlignmentY(0.0F);

        jLabel8.setFont(new java.awt.Font("Dialog", 0, 12));
        jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jLabel8.setText("an der Uni Bonn.");
        jLabel8.setAlignmentY(0.0F);

        org.jdesktop.layout.GroupLayout jFrame1Layout = new org.jdesktop.layout.GroupLayout(jFrame1.getContentPane());
        jFrame1.getContentPane().setLayout(jFrame1Layout);
        jFrame1Layout.setHorizontalGroup(
            jFrame1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jFrame1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jLabel4)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jFrame1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jLabel5)
                    .add(jLabel6)
                    .add(jLabel7)
                    .add(jLabel8))
                .add(45, 45, 45))
        );
        jFrame1Layout.setVerticalGroup(
            jFrame1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jFrame1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jFrame1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jLabel4)
                    .add(jFrame1Layout.createSequentialGroup()
                        .add(jLabel5)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel6)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel7)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel8)))
                .addContainerGap(63, Short.MAX_VALUE))
        );
        jFrame2.setTitle("Downloading");
        jFrame2.setAlwaysOnTop(true);

        jLabel9.setFont(new java.awt.Font("Dialog", 1, 18));
        jLabel9.setText("Downloading:");

        jLabel10.setFont(new java.awt.Font("Dialog", 1, 18));
        jLabel10.setText("0%");

        org.jdesktop.layout.GroupLayout jFrame2Layout = new org.jdesktop.layout.GroupLayout(jFrame2.getContentPane());
        jFrame2.getContentPane().setLayout(jFrame2Layout);
        jFrame2Layout.setHorizontalGroup(
            jFrame2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jFrame2Layout.createSequentialGroup()
                .addContainerGap()
                .add(jFrame2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jProgressBar1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
                    .add(jFrame2Layout.createSequentialGroup()
                        .add(jLabel9)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel10)))
                .addContainerGap())
        );
        jFrame2Layout.setVerticalGroup(
            jFrame2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jFrame2Layout.createSequentialGroup()
                .addContainerGap()
                .add(jFrame2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel9)
                    .add(jLabel10))
                .add(16, 16, 16)
                .add(jProgressBar1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 32, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("rnClient");
        jList1.setModel(new DefaultListModel());
        jScrollPane1.setViewportView(jList1);

        jButton1.setText("Verbinden");
        jToolBar1.add(jButton1);

        jButton4.setText("Einstgellungen");
        jToolBar1.add(jButton4);

        jLabel1.setText("Freigegebene Dateien");

        jList2.setModel(new DefaultListModel());
        jList2.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane2.setViewportView(jList2);

        jLabel2.setText("Verf\u00fcgbare Dateien");

        addButton.setText("Datei freigeben");
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        removeButton.setText("Datei entfernen");
        removeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeButtonActionPerformed(evt);
            }
        });

        jLabel3.setText("Status");

        jList3.setModel(new DefaultListModel());
        jList3.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jList3.setFocusable(false);
        jScrollPane3.setViewportView(jList3);

        getButton.setText("Herunterladen");
        getButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                getButtonActionPerformed(evt);
            }
        });

        jMenu1.setMnemonic('D');
        jMenu1.setText("Datei");
        jMenuBar1.add(jMenu1);

        jMenu3.setText("Hilfe");
        about.setMnemonic('r');
        about.setText("\u00dcber rnClient");
        about.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutActionPerformed(evt);
            }
        });

        jMenu3.add(about);

        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jLabel3)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, jScrollPane3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 761, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(jLabel1)
                                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 213, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(removeButton)
                                    .add(addButton))
                                .add(23, 23, 23)
                                .add(getButton)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(layout.createSequentialGroup()
                                        .add(jLabel2)
                                        .add(124, 124, 124))
                                    .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE))))
                        .add(16, 16, 16))))
            .add(jToolBar1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 773, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(jToolBar1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 45, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel1)
                    .add(jLabel2))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 303, Short.MAX_VALUE)
                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                        .add(layout.createSequentialGroup()
                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                .add(addButton)
                                .add(getButton))
                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                            .add(removeButton))
                        .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 303, Short.MAX_VALUE)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 29, Short.MAX_VALUE)
                .add(jLabel3)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 169, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void aboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutActionPerformed
// TODO add your handling code here:
        jFrame1.setVisible(true);
        jFrame1.pack();
    }//GEN-LAST:event_aboutActionPerformed

    private void getButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_getButtonActionPerformed
// TODO add your handling code here:
        int index = jList2.getSelectedIndex();
        Socket sock;
        OutputStream out;
        InputStream in;
        jLabel10.setText("0%");
        jFrame2.setVisible(true);
        jFrame2.pack();
        String[] selected = (String[]) SEEDLIST.get(index);
        try {
            sock = new Socket(InetAddress.getByName(selected[1]),Integer.parseInt(selected[2]));
        } catch(IOException e) {
            e.printStackTrace();
            // System.exit(3);
            return;
        } catch (NullPointerException e) {
            e.printStackTrace();
            return;
        }

        try {
            out = sock.getOutputStream();
            //this.writer = new BufferedOutputStream(this.out);
        } catch(IOException e) {
            e.printStackTrace();
            // System.exit(5);
            return;
        }

        String discover = new String("get_file "+selected[3]+"\n");
        byte[] buf = new byte[discover.length()];
        buf = discover.getBytes();
        try {
	    out.write(buf);
            stat.setStatus(discover,stat.SEND);
            out.flush();
        } catch(IOException e) {
            e.printStackTrace();
            return;
        }
        
        try {
            in = sock.getInputStream();
            //this.writer = new BufferedOutputStream(this.out);
        } catch(IOException e) {
            e.printStackTrace();
            // System.exit(5);
            return;
        }
        
        try {
            File lokal = new File(""+SAVEDIR+selected[4]);
            lokal.createNewFile();
            FileOutputStream lokalstream = new FileOutputStream(lokal);
            int c = 0;
            while ((c = in.read()) != -1 ) {
                lokalstream.write(c);
            }
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        
    }//GEN-LAST:event_getButtonActionPerformed

    private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
        int index = jList1.getSelectedIndex();
        DefaultListModel listModel = (DefaultListModel) jList1.getModel();
        try {
            listModel.remove(index);
            LEACHLIST.remove(index);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
            return;
        }
        int size = listModel.getSize();

        if (size == 0) { //Nobody's left, disable firing.
            removeButton.setEnabled(false);

        } else { //Select an index.
            if (index == listModel.getSize()) {
            //removed item in last position
                index--;
            }

            jList1.setSelectedIndex(index);
            jList1.ensureIndexIsVisible(index);
        }
        slauscher.sendSeedlist();
    }//GEN-LAST:event_removeButtonActionPerformed

    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
        DefaultListModel listModel = (DefaultListModel) jList1.getModel();
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Datei freigeben");
        fc.setFileSelectionMode ( JFileChooser.FILES_ONLY);
        int result = fc.showOpenDialog (this);
        if (result == JFileChooser.CANCEL_OPTION) {
            return;
        } else if (result == JFileChooser.APPROVE_OPTION) {

            File datei = fc.getSelectedFile ();
            String dateiname = datei.getAbsolutePath();
            long dateisize = datei.length();
            String[] seed = new String[2];

            if (dateiname != null) {
                listModel.addElement(dateiname);
                seed[0]= "" + dateisize;
                seed[1]=dateiname;
                SEEDLIST.add(seed);
            }
            else return;
        } else {
            return;
        }
        
        slauscher.sendSeedlist();
        
        return;
    }//GEN-LAST:event_addButtonActionPerformed
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                rnclient myclient = new rnclient();
                myclient.setVisible(true);
                myclient.stat = new Status(myclient);
                myclient.getServer();
                myclient.initLocalServer();
                myclient.initFileList();
                myclient.connectToServer();
            }
        });
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem about;
    private javax.swing.JButton addButton;
    private javax.swing.JButton getButton;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton4;
    private javax.swing.JFrame jFrame1;
    private javax.swing.JFrame jFrame2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    public javax.swing.JList jList1;
    public javax.swing.JList jList2;
    public javax.swing.JList jList3;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JButton removeButton;
    // End of variables declaration//GEN-END:variables
    
}


class Serverlauscher extends Thread {
    public Socket sock = null;
    public OutputStream out = null;
    public OutputStream writer;
    rnclient rn;

    Serverlauscher(rnclient rn ) {
        this.rn = rn;
        
        try {
            this.sock = new Socket(rn.SERVER_TCP_ADDRESS, rn.SERVER_TCP_PORT);
        } catch(IOException e) {
            e.printStackTrace();
            // System.exit(3);
            return;
        } catch (NullPointerException e) {
            e.printStackTrace();
            return;
        }

        try {
            this.out = sock.getOutputStream();
            //this.writer = new BufferedOutputStream(this.out);
        } catch(IOException e) {
            e.printStackTrace();
            // System.exit(5);
            return;
        }
    }
    
    /**
     * Sendet regester + CLIENT_PORT an den Server
     */
    public void register() {
        String discover = new String("register "+rn.CLIENT_PORT+"\n");
        byte[] buf = new byte[discover.length()];
        buf = discover.getBytes();
        try {
	    this.out.write(buf);
            rn.stat.setStatus(discover,rn.stat.SEND);
            this.out.flush();
        } catch(IOException e) {
            e.printStackTrace();
            return;
        }
        
    }
    
    /**
     * Sendet die Freigabeliste an den Server, wird beim start aufgerufen, und bei jeder änderung der Freigabelist.
     */
    public void sendSeedlist() {
 
        int seedcount = rn.SEEDLIST.size();
        String seed = new String();
        for (int i = 0;i < seedcount;i++) {
            String[] inhalt = (String[]) rn.SEEDLIST.get(i);
            /*
             *inhalt[0] Dateigröße
             *inhalt[1] Dateiname
            */
            seed = seed + inhalt[0] + " "+ inhalt[1] +"\n";
        }

        String discover = new String("send_filelist "+seedcount+"\n"+seed);
        byte[] buf = new byte[discover.length()];
        buf = discover.getBytes();

        try {
	     out.write(buf);
             rn.stat.setStatus(discover,rn.stat.SEND);
             out.flush();
        } catch(IOException e) {
            e.printStackTrace();
            return;
        }
    }
    

    /**
     * Der Serverlauscher Thread, horcht auf der Server TCP verbindung auf eintreffende update_filelist
     */
    public void run() {
        try {

            BufferedReader reader = new BufferedReader(new InputStreamReader(this.sock.getInputStream()));
            String[] input = new String[4];
            String address;
            DefaultListModel model = (DefaultListModel) rn.jList2.getModel();
            rn.stat.setStatus("Serverlauscher gestartet!",2);
            while (true) {
                String str = reader.readLine();
                int pos;
                if (str.startsWith("update_filelist")) {
                    rn.stat.setStatus("Empfange Dateiliste: "+str,rn.stat.EMPF);
                    if (str.indexOf("\n") != -1) pos = str.indexOf("\n"); else pos=str.length();
                    int count = Integer.parseInt(str.substring(15,pos).trim());
                    rn.stat.setStatus("Count: "+count,rn.stat.EMPF);
                    rn.LEACHLIST.clear();
                    model.clear();
                    for (int i = 0;i < count; i++) {
                        str = reader.readLine().trim();
                        rn.stat.setStatus(str,rn.stat.EMPF);
                        input = str.split(" ",4);
                        /*
                         *input[0] Dateigröße
                         *input[1] IP
                         *input[2] Port
                         *input[3] Dateiname
                         */
                        address = sock.getLocalAddress().toString();
                        address = address.split("/")[1].trim();
                                
                        if ((input[1].trim().compareToIgnoreCase(address.trim())!=0)||(Integer.parseInt(input[2].trim())!=rn.CLIENT_PORT)) {
                            rn.stat.setStatus(address+" "+input[1],rn.stat.EMPF);
                            rn.LEACHLIST.add(input);
                            model.addElement(input[3]);
                        }
                    }
                }
                else rn.stat.setStatus(str,rn.stat.EMPF);
                
            }
            
        } catch(IOException e) {
            e.printStackTrace();
            return;
        } finally {
            try {
                sock.close();
            } catch(IOException e) {
                e.printStackTrace();
                // System.exit(3);
                return;
            }
        }
    }
}

class Clientlauscher extends Thread {

    rnclient rn = null;
    ServerSocket sock = null;
    
    /**
     * Erzeugt eine Instanz von Clientlauscher und setzt den Client TCP Port
     * @param rn Instanz von rnclient, die diese Instanz aufruft, sollte "this" sein.
     * @return 
     */
    Clientlauscher(rnclient rn) {
	this.rn = rn;
        
        try {
            sock = new ServerSocket(0);
        } catch(IOException e) {
            e.printStackTrace();
            // System.exit(3);
            return;
        } catch (NullPointerException e) {
            e.printStackTrace();
            return;
        }
        
        rn.CLIENT_PORT = sock.getLocalPort();
        rn.stat.setStatus("Client Port gesetzt: "+rn.CLIENT_PORT,2);
    }

    /**
     * Wartet auf ankommende Clients und erzeugt dann einen neuen Thread, der die Datei sendet.
     */
    public void run() {
        while (true) {
            Socket incoming = null;
            try {
                incoming = sock.accept();
            } catch(IOException e) {
                System.out.println(e);
                continue;
            }

            new LauscherHandler(rn,incoming).start();
        }  
    }
}

class LauscherHandler extends Thread {
    Socket incoming;
    rnclient rn;

    /**
     * Erzeugt eine neue Instanz, die auf ein get_file von anderen Clients horscht
     * @param rn Instanz von rnclient, die diese Instanz aufruft, sollte "this" sein.
     * @param incoming Der Socket, der TCP verbindung zum Client
     * @return 
     */
    LauscherHandler(rnclient rn,Socket incoming) {
	this.incoming = incoming;
        this.rn = rn;
    }

    /**
     * wartet auf dem Client TCP Port auf ein get_file, und sendet diese dann
     */
    public void run() {
	try {
	    BufferedReader reader = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
	    OutputStream out = incoming.getOutputStream();
	    
	    boolean done = false;
	    while ( ! done) {
		String str = reader.readLine();
                rn.stat.setStatus(str,rn.stat.EMPF);
		if (str == null) 
		    done = true;
		else if (str.startsWith("get_file")) {
                    String file = str.substring(9,str.indexOf("\n"));
                    FileInputStream filereader = new FileInputStream(file);
                    byte b[]=new byte[1024];
                    int numRead=0;
                    while ( ( numRead=filereader.read(b)) > 0) {
                        out.write(b, 0, numRead);
                    }
                    out.flush();
                    done = true;
		}
		
	    }
	    incoming.close();
	} catch(IOException e) {
	    e.printStackTrace();
	}
    }

}



class Status {
    rnclient rn;
    final static int EMPF = 1;
    final static int SEND = 0;

    /**
     * Erzeugt eine neue Instanz von Status
     * @param rn Instanz von rnclient, die diese Instanz aufruft, sollte "this" sein.
     * @return 
     */
    Status (rnclient rn) {
        this.rn = rn;
    }
    
    /**
     * Fügt eine neue Statuszeile im Statusfenster hinzu (beachtet keine \n)
     * @param nachricht Die Nachricht
     * @param stat Art der Nachricht, 0 Sende Status, 1 Empfangs Status, 2 sontiger Status
     */
    public void setStatus(String nachricht, int stat) {
        Color farbe;
        if (stat == EMPF) farbe = java.awt.Color.blue;
        else if (stat == SEND) farbe = java.awt.Color.red;
        else farbe = java.awt.Color.black;
        
        Object element[] = { new Font("Dialog", Font.PLAIN, 12), farbe, nachricht.trim()+"\n" };
        DefaultListModel listModel = (DefaultListModel) rn.jList3.getModel();
        ListCellRenderer renderer = new ComplexCellRenderer();
        rn.jList3.setCellRenderer(renderer);
        listModel.addElement(element);
        System.out.println(nachricht.trim());
    }
}

class ComplexCellRenderer implements ListCellRenderer {
  protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();

  public Component getListCellRendererComponent(JList list, Object value,
    int index, boolean isSelected, boolean cellHasFocus) {
    Font theFont = null;
    Color theForeground = null;
    Icon theIcon = null;
    String theText = null;

    JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

    if (value instanceof Object[]) {
      Object values[] = (Object[]) value;
      theFont = (Font) values[0];
      theForeground = (Color) values[1];
      theText = (String) values[2];
    } else {
      theFont = list.getFont();
      theForeground = list.getForeground();
      theText = "";
    }
    if (!isSelected) {
      renderer.setForeground(theForeground);
    }
    if (theIcon != null) {
      renderer.setIcon(theIcon);
    }
    renderer.setText(theText);
    renderer.setFont(theFont);
    return renderer;
  }
}
