import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.Random;


/**
  *
  * BinärSpiel: Man kann eine gewisse Zeit Binärzahlen in Dezimalzahlen umrechnen
  * Die Ergebnisse werden an den Server geschickt
  * V1.1: Rundenzeit vom Server steuerbar, Fehlerkorrektur
  * V1.2: Gesamtzeit vom Server steuerbar 
  *
  * @version 1.2 vom 18.02.2019
  * @author  Thomas Schaller
  * cc0-Lizenz ZPG IMP Klasse 9
  */

public class BinaerSpiel extends JFrame implements MySocketListener {
  // Anfang Attribute
  private JTextField jTFLoesung = new JTextField();
  private JTextField jTFAufgabe = new JTextField();
  private JButton bLeicht = new JButton();
  private JButton bMittel = new JButton();
  private JButton bSchwer = new JButton();
  private JButton bPruefen = new JButton();
  private JPanel jPanel1 = new JPanel(null, true);
    private JLabel lRunde = new JLabel();
    private JLabel lZeit = new JLabel();
  private JPanel jPanel2 = new JPanel(null, true);
    private JLabel ltPunkte = new JLabel();
    private JLabel lPunkte = new JLabel();
  private JButton jBVerbinden = new JButton();
  private JButton bRundestarten = new JButton();
  private JLabel lServer = new JLabel();
  private JTextField jTFAdress = new JTextField();
  private JLabel l = new JLabel();
  private JLabel l1 = new JLabel();
  private JLabel l3 = new JLabel();
  private JLabel l2 = new JLabel();
  private JLabel l5 = new JLabel();
  private JLabel l6 = new JLabel();
  private Timer timer1 = new Timer(1000, null);
  private JLabel lSpielername = new JLabel();
  private JTextField jTFName = new JTextField();
  private JLabel l4 = new JLabel();
  private JLabel jLMeldung = new JLabel();
  private JLabel lcc2018ThomasSchallerVersion10 = new JLabel();
  private JPanel jPanel3 = new JPanel(null, true);
    private JLabel lGesamt = new JLabel();
    private JLabel lGesamtzeit = new JLabel();
  // Ende Attribute
  private int spielzeit = 60;
  private int restzeit = 0;
  private int gesamtzeit = 0;
  private int zahl = 0;
  private int punkte = 0;
  private MySocket client = null;
  private int lastLevel = 0;
  private boolean spiellaeuft = false;


  public BinaerSpiel (String title) {
    super (title);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    int frameWidth = 597; 
    int frameHeight = 276;
    setSize(frameWidth, frameHeight);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2;
    setLocation(x, y);
    Container cp = getContentPane();
    cp.setLayout(null);
    // Anfang Komponenten
    jTFLoesung.setBounds(272, 168, 150, 28);
    jTFLoesung.setEditable(true);
    jTFLoesung.setEnabled(true);
    jTFLoesung.setVisible(false);
    jTFLoesung.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        jTFLoesung_KeyPressed(evt);
      }
    });
    cp.add(jTFLoesung);
    jTFAufgabe.setBounds(40, 168, 150, 28);
    jTFAufgabe.setEditable(false);
    jTFAufgabe.setEnabled(true);
    jTFAufgabe.setVisible(false);
    cp.add(jTFAufgabe);
    bLeicht.setBounds(128, 168, 99, 25);
    bLeicht.setText("einfach");
    bLeicht.setMargin(new Insets(2, 2, 2, 2));
    bLeicht.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        bLeicht_ActionPerformed(evt);
      }
    });
    bLeicht.setVisible(false);
    bLeicht.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        bLeicht_KeyPressed(evt);
      }
    });
    cp.add(bLeicht);
    bMittel.setBounds(248, 168, 91, 25);
    bMittel.setText("mittel");
    bMittel.setMargin(new Insets(2, 2, 2, 2));
    bMittel.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        bMittel_ActionPerformed(evt);
      }
    });
    bMittel.setVisible(false);
    bMittel.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        bMittel_KeyPressed(evt);
      }
    });
    cp.add(bMittel);
    bSchwer.setBounds(368, 168, 83, 25);
    bSchwer.setText("schwer");
    bSchwer.setMargin(new Insets(2, 2, 2, 2));
    bSchwer.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        bSchwer_ActionPerformed(evt);
      }
    });
    bSchwer.setVisible(false);
    bSchwer.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        bSchwer_KeyPressed(evt);
      }
    });
    cp.add(bSchwer);
    bPruefen.setBounds(472, 168, 75, 25);
    bPruefen.setText("Prüfen");
    bPruefen.setMargin(new Insets(2, 2, 2, 2));
    bPruefen.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        bPruefen_ActionPerformed(evt);
      }
    });
    bPruefen.setEnabled(true);
    bPruefen.setVisible(false);
    bPruefen.setSelected(true);
    cp.add(bPruefen);
    jPanel1.setBounds(192, 72, 177, 49);
    jPanel1.setOpaque(false);
    jPanel1.setBorder(BorderFactory.createBevelBorder(1, new Color(0xC0C0C0), Color.BLACK));
    cp.add(jPanel1);
    lRunde.setBounds(8, 8, 86, 30);
    lRunde.setText("Runde:");
    lRunde.setFont(new Font("Dialog", Font.BOLD, 22));
    lRunde.setForeground(new Color(0x800000));
    jPanel1.add(lRunde);
    lZeit.setBounds(88, 8, 83, 30);
    lZeit.setText("? sek");
    lZeit.setFont(new Font("Dialog", Font.BOLD, 22));
    lZeit.setForeground(new Color(0x800000));
    lZeit.setHorizontalAlignment(SwingConstants.RIGHT);
    jPanel1.add(lZeit);
    jPanel2.setBounds(8, 72, 177, 49);
    jPanel2.setOpaque(false);
    jPanel2.setBorder(BorderFactory.createBevelBorder(1, new Color(0xC0C0C0), Color.BLACK));
    cp.add(jPanel2);
    jBVerbinden.setBounds(408, 40, 169, 25);
    jBVerbinden.setText("Verbinden");
    jBVerbinden.setMargin(new Insets(2, 2, 2, 2));
    jBVerbinden.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        jBVerbinden_ActionPerformed(evt);
      }
    });
    cp.add(jBVerbinden);
    ltPunkte.setBounds(8, 8, 110, 30);
    ltPunkte.setText("Punkte:");
    ltPunkte.setFont(new Font("Dialog", Font.BOLD, 22));
    ltPunkte.setForeground(new Color(0x800000));
    jPanel2.add(ltPunkte);
    lPunkte.setBounds(96, 8, 70, 30);
    lPunkte.setText("0");
    lPunkte.setForeground(new Color(0x800000));
    lPunkte.setFont(new Font("Dialog", Font.BOLD, 22));
    lPunkte.setHorizontalAlignment(SwingConstants.RIGHT);
    jPanel2.add(lPunkte);
    bRundestarten.setBounds(120, 160, 353, 41);
    bRundestarten.setText("Runde starten");
    bRundestarten.setMargin(new Insets(2, 2, 2, 2));
    bRundestarten.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        bRundestarten_ActionPerformed(evt);
      }
    });
    bRundestarten.setEnabled(false);
    bRundestarten.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        bRundestarten_KeyPressed(evt);
      }
    });
    cp.add(bRundestarten);
    lServer.setBounds(8, 40, 110, 20);
    lServer.setText("Server:");
    cp.add(lServer);
    jTFAdress.setBounds(128, 40, 270, 25);
    jTFAdress.addKeyListener(new KeyAdapter() { 
      public void keyPressed(KeyEvent evt) { 
        jTFAdress_KeyPressed(evt);
      }
    });
    cp.add(jTFAdress);
    l.setBounds(24, 160, 14, 33);
    l.setText("(");
    l.setFont(new Font("Dialog", Font.BOLD, 24));
    l.setVisible(false);
    cp.add(l);
    l1.setBounds(256, 160, 14, 33);
    l1.setText("(");
    l1.setFont(new Font("Dialog", Font.BOLD, 24));
    l1.setVisible(false);
    cp.add(l1);
    l3.setBounds(192, 160, 10, 33);
    l3.setText(")");
    l3.setFont(new Font("Dialog", Font.BOLD, 24));
    l3.setVisible(false);
    cp.add(l3);
    l2.setBounds(200, 184, 14, 20);
    l2.setText("2");
    l2.setFont(new Font("Dialog", Font.BOLD, 11));
    l2.setVisible(false);
    cp.add(l2);
    l5.setBounds(424, 160, 14, 33);
    l5.setText(")");
    l5.setFont(new Font("Dialog", Font.BOLD, 24));
    l5.setVisible(false);
    cp.add(l5);
    l6.setBounds(432, 184, 16, 20);
    l6.setText("10");
    l6.setFont(new Font("Dialog", Font.BOLD, 11));
    l6.setVisible(false);
    cp.add(l6);
    timer1.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        timer1_ActionPerformed(evt);
      }
    });
    timer1.setRepeats(true);
    timer1.setInitialDelay(0);
    lSpielername.setBounds(8, 8, 110, 20);
    lSpielername.setText("Spielername:");
    cp.add(lSpielername);
    jTFName.setBounds(128, 8, 270, 25);
    cp.add(jTFName);
    l4.setBounds(224, 168, 22, 25);
    l4.setText("->");
    l4.setFont(new Font("@System", Font.BOLD, 24));
    l4.setVisible(false);
    cp.add(l4);
    jLMeldung.setBounds(8, 128, 566, 20);
    jLMeldung.setText("");
    cp.add(jLMeldung);
    lcc2018ThomasSchallerVersion10.setBounds(8, 216, 566, 20);
    lcc2018ThomasSchallerVersion10.setText("(cc) 2018, Thomas Schaller, Version 1.2");
    lcc2018ThomasSchallerVersion10.setHorizontalAlignment(SwingConstants.CENTER);
    cp.add(lcc2018ThomasSchallerVersion10);
    addWindowListener(new WindowAdapter() { 
      public void windowClosed(WindowEvent evt) { 
        BinaerSpiel_WindowClosed(evt);
      }
    });
    jPanel3.setBounds(376, 72, 201, 49);
    jPanel3.setOpaque(false);
    jPanel3.setBorder(BorderFactory.createBevelBorder(1, new Color(0xC0C0C0), Color.BLACK));
    cp.add(jPanel3);
    lGesamt.setBounds(8, 8, 93, 30);
    lGesamt.setText("Gesamt:");
    lGesamt.setFont(new Font("Dialog", Font.BOLD, 22));
    lGesamt.setForeground(new Color(0x800000));
    jPanel3.add(lGesamt);
    lGesamtzeit.setBounds(112, 8, 83, 30);
    lGesamtzeit.setText("? sek");
    lGesamtzeit.setFont(new Font("Dialog", Font.BOLD, 22));
    lGesamtzeit.setForeground(new Color(0x800000));
    lGesamtzeit.setHorizontalAlignment(SwingConstants.RIGHT);
    jPanel3.add(lGesamtzeit);
    // Ende Komponenten
    setResizable(false);
    setVisible(true);
  }

  // Anfang Methoden
  
  private void neueAufgabe(int min, int max) {
    Random r = new Random();
    do{
      zahl = r.nextInt(max-min)+min;
    } while (jTFAufgabe.equals(Integer.toBinaryString(zahl)));
    jTFAufgabe.setText(Integer.toBinaryString(zahl));
    jTFLoesung.setText("");

    bPruefen.setVisible(true);
    jTFLoesung.setVisible(true);
    jTFAufgabe.setVisible(true);
    l1.setVisible(true);
    l2.setVisible(true);
    l3.setVisible(true);
    l4.setVisible(true);
    l5.setVisible(true);
    l6.setVisible(true);
    l.setVisible(true);
    bLeicht.setVisible(false);
    bMittel.setVisible(false);
    bSchwer.setVisible(false);
    jTFLoesung.requestFocus();
  }

  public void bLeicht_ActionPerformed(ActionEvent evt) {
    lastLevel = 0;
    neueAufgabe(1,16);
  } // end of bLeicht_ActionPerformed

  public void bMittel_ActionPerformed(ActionEvent evt) {
    lastLevel = 1;
    neueAufgabe(16,128);
    
  } // end of bMittel_ActionPerformed

  public void bSchwer_ActionPerformed(ActionEvent evt) {
    lastLevel = 2;
    neueAufgabe(128,1024);
    
  } // end of bSchwer_ActionPerformed

  public void bPruefen_ActionPerformed(ActionEvent evt) {
    try{
      int loesung = Integer.parseInt(jTFLoesung.getText());
      if(loesung == zahl) {
        jLMeldung.setText("Richtig! Du erhälst "+zahl+" Punkte.");
        punkte += zahl;
        lPunkte.setText(""+punkte);
      }
      else {
        jLMeldung.setText("Leider falsch! Richtig wäre "+Integer.toBinaryString(zahl)+" -> "+zahl+" gewesen.");
      } // end of if-else

    
    } catch(Exception e) {
        jLMeldung.setText("Deine Eingabe ist keine korrekte Zahl.");
      
    }
    bPruefen.setVisible(false);
    jTFAufgabe.setVisible(false);
    jTFLoesung.setVisible(false);
    bLeicht.setVisible(true);
    bMittel.setVisible(true);
    bSchwer.setVisible(true);
    l1.setVisible(false);
    l2.setVisible(false);
    l3.setVisible(false);
    l4.setVisible(false);
    l5.setVisible(false);
    l6.setVisible(false);
    l.setVisible(false);
    setLevelFocus();
    
  } // end of bPruefen_ActionPerformed

  public void jBVerbinden_ActionPerformed(ActionEvent evt) {

    String a = jTFAdress.getText();
    int p = 44444;
    if (client != null && client.isAktiv()) {
      jTFName.setEnabled(true);
      jTFAdress.setEnabled(true);
      
      jBVerbinden.setText("Verbinden");
      client.sendeNachricht("exit");
      client.trenneVerbindung();
    } else {
      client = new MySocket(a, p, this);
      if (client.isAktiv()) {
        jTFName.setEnabled(false);
        jTFAdress.setEnabled(false);
        jBVerbinden.setText("Trennen");
        client.sendeNachricht(("user:"+jTFName.getText()+":alle"));
      }
    } // end of if-else
  } // end of jBVerbinden_ActionPerformed    
    


  public void bRundestarten_ActionPerformed(ActionEvent evt) {
    bRundestarten.setVisible(false);
    bLeicht.setVisible(true);
    bMittel.setVisible(true);
    bSchwer.setVisible(true);
    setLevelFocus();
    restzeit = Math.min(spielzeit,gesamtzeit-1);
    punkte = 0;
    lZeit.setText(""+restzeit+" sek");
    lPunkte.setText(""+punkte);
    timer1.start();
    spiellaeuft = true;
     jLMeldung.setText("");
    
  } // end of bRundestarten_ActionPerformed

  public void timer1_ActionPerformed(ActionEvent evt) {
    restzeit--;
    lZeit.setText(""+restzeit+" sek");
    lGesamtzeit.setText(""+gesamtzeit+" sek");
    if(restzeit == 0 || gesamtzeit == 0) {
      timer1.stop();
      if(client != null) {
        if(gesamtzeit > 0) {
          client.sendeNachricht("punkte:"+punkte);
           jLMeldung.setText("Deine Zeit ist abgelaufen. Du hast "+punkte+ " Punkte erreicht. Punkte wurden gespeichert.");
        } else {
           jLMeldung.setText("Die Gesamtzeit ist abgelaufen. Die Punkte konnten nicht mehr gespeichert werden.");
        } // end of if-else

      } else {
         jLMeldung.setText("Deine Zeit ist abgelaufen. Du hast "+punkte+ " Punkte erreicht. Serververbindung abgebrochen.");
      } // end of if-else
      spiellaeuft = false;

      bRundestarten.setVisible(true);
      if(gesamtzeit > 0) {
        bRundestarten.requestFocus();
      } else {
        bRundestarten.setEnabled(false);
      } // end of if-else

    bPruefen.setVisible(false);
    jTFAufgabe.setVisible(false);
    jTFLoesung.setVisible(false);
    bLeicht.setVisible(false);
    bMittel.setVisible(false);
    bSchwer.setVisible(false);
    l1.setVisible(false);
    l2.setVisible(false);
    l3.setVisible(false);
    l4.setVisible(false);
    l5.setVisible(false);
    l6.setVisible(false);
    l.setVisible(false);
    }

   
    
  } // end of timer1_ActionPerformed
  
  
  /** Neuer Client macht nichts
  */
  public void neuerClient(MySocket client) { 
  }
    
  public void nachrichtEmpfangen(MySocket client) {
     String n = client.holeNachricht();
     if(n.startsWith("round")){
       try{
         spielzeit = Integer.parseInt(n.substring(6));
       } catch (Exception e) {
         spielzeit = 60;
       }
       restzeit = spielzeit;
       lZeit.setText(""+restzeit+" sek"); 
     }
     if(n.startsWith("game")){
       try{
         gesamtzeit = Integer.parseInt(n.substring(5));
       } catch (Exception e) {
         gesamtzeit = 0;
       }
       lGesamtzeit.setText(""+gesamtzeit+" sek"); 
       if(gesamtzeit > 0 && !spiellaeuft) {
         bRundestarten.setEnabled(true);
         bRundestarten.requestFocus();
       }
 
     }


  }
    
  public void verbindungBeendet(MySocket client) {
    jTFName.setEnabled(true);
    jTFAdress.setEnabled(true);
    jBVerbinden.setText("Verbinden");
    client = null;
  }
  public void BinaerSpiel_WindowClosed(WindowEvent evt) {
    client.sendeNachricht("exit");
    client.trenneVerbindung();
    
  } // end of BinaerSpiel_WindowClosed

  public void jTFLoesung_KeyPressed(KeyEvent evt) {
    if(evt.getKeyCode() == KeyEvent.VK_ENTER)
      bPruefen_ActionPerformed(null);
  } // end of jTFLoesung_KeyPressed
  
  public void setLevelFocus() {
    if(lastLevel == 0) bLeicht.requestFocus();
    if(lastLevel == 1) bMittel.requestFocus();
    if(lastLevel == 2) bSchwer.requestFocus(); 
  }


  public void bLeicht_KeyPressed(KeyEvent evt) {
    if(evt.getKeyCode() == KeyEvent.VK_ENTER)
      bLeicht_ActionPerformed(null);

    if(evt.getKeyCode() == KeyEvent.VK_LEFT){
      lastLevel = (lastLevel+2)%3;
      setLevelFocus();
    }

    if(evt.getKeyCode() == KeyEvent.VK_RIGHT){
      lastLevel = (lastLevel+1)%3;
      setLevelFocus();
    }
  } // end of bLeicht_KeyPressed

  public void bMittel_KeyPressed(KeyEvent evt) {
    if(evt.getKeyCode() == KeyEvent.VK_ENTER)
      bMittel_ActionPerformed(null);
    if(evt.getKeyCode() == KeyEvent.VK_LEFT){
      lastLevel = (lastLevel+2)%3;
      setLevelFocus();
    }

    if(evt.getKeyCode() == KeyEvent.VK_RIGHT){
      lastLevel = (lastLevel+1)%3;
      setLevelFocus();
    }
  } // end of bMittel_KeyPressed

  public void bSchwer_KeyPressed(KeyEvent evt) {
    if(evt.getKeyCode() == KeyEvent.VK_ENTER)
      bSchwer_ActionPerformed(null);
    if(evt.getKeyCode() == KeyEvent.VK_LEFT){
      lastLevel = (lastLevel+2)%3;
      setLevelFocus();
    }

    if(evt.getKeyCode() == KeyEvent.VK_RIGHT){
      lastLevel = (lastLevel+1)%3;
      setLevelFocus();
    }      
  } // end of bSchwer_KeyPressed

  public void jTFAdress_KeyPressed(KeyEvent evt) {
    if(evt.getKeyCode() == KeyEvent.VK_ENTER)
      jBVerbinden_ActionPerformed(null);
   
  } // end of jTFAdress_KeyPressed

  public void bRundestarten_KeyPressed(KeyEvent evt) {
   if(evt.getKeyCode() == KeyEvent.VK_ENTER)
      bRundestarten_ActionPerformed(null);
   
  } // end of bRundestarten_KeyPressed

  // Ende Methoden

  public static void main(String[] args) {
    new BinaerSpiel("BinaerSpiel");
  }
}

