package com.apixandru.rummikub.swing;

import com.apixandru.rummikub.brotocol.SocketWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.io.IOException;
import java.net.Socket;
import java.util.prefs.Preferences;

import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.QUESTION_MESSAGE;

/**
 * @author Alexandru-Constantin Bledea
 * @since January 09, 2016
 */
final class ServerData {

    private static final Logger log = LoggerFactory.getLogger(ServerData.class);

    private static final String KEY_ADDRESS = "address";
    private static final String KEY_USERNAME = "username";

    private static final String OPT_CONNECT = "Connect";
    private static final String OPT_CANCEL = "Cancel";

    private static final String[] OPTIONS = {OPT_CONNECT, OPT_CANCEL};

    private static final int CHOICE_CONNECT = 0;

    private ServerData() {
    }

    static ConnectionData getConnectionData() {
        final Preferences prefs = Preferences.userNodeForPackage(ServerData.class);

        String address = System.getProperty("rk.address");
        String username = System.getProperty("rk.user");

        final JTextField tfUsername = newField(prefs, KEY_USERNAME, username);
        final JTextField tfAddress = newField(prefs, KEY_ADDRESS, address);

        boolean showDialog = null == address || null == username;

        while (true) {
            if (showDialog) {
                final int option = JOptionPane.showOptionDialog(
                        null,
                        createLoginPanel(tfUsername, tfAddress),
                        "Connection Data",
                        OK_CANCEL_OPTION,
                        QUESTION_MESSAGE,
                        null,
                        OPTIONS,
                        OPT_CONNECT);

                if (CHOICE_CONNECT != option) {
                    return null;
                }

                address = tfAddress.getText();
                username = tfUsername.getText();

                prefs.put(KEY_ADDRESS, address);
                prefs.put(KEY_USERNAME, username);
            }
            try {
                return new ConnectionData(new Socket(address, 50122), username);
            } catch (IllegalArgumentException ex) {
                showDialog = true;
                log.debug("Could not connect to " + address);
                JOptionPane.showMessageDialog(null,
                        ex.getMessage(),
                        "Cannot connect",
                        JOptionPane.ERROR_MESSAGE);
            } catch (IOException ex) {
                showDialog = true;
                log.debug("Could not connect to " + address);
                JOptionPane.showMessageDialog(null,
                        "Cannot connect to " + address + "!",
                        "Cannot connect",
                        JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private static JPanel createLoginPanel(final JTextField username, final JTextField address) {
        final JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.add(createLabels(), BorderLayout.WEST);
        panel.add(newPanel(address, username), BorderLayout.CENTER);
        return panel;
    }

    private static JPanel newPanel(final Component... components) {
        final JPanel controls = new JPanel(new GridLayout(0, 1, 2, 2));
        for (Component component : components) {
            controls.add(component);
        }
        return controls;
    }

    private static JTextField newField(final Preferences prefs, final String key, final String override) {
        return new JTextField(null == override ? prefs.get(key, "") : override);
    }

    private static JPanel createLabels() {
        return newPanel(new JLabel("Server", SwingConstants.RIGHT), new JLabel("Name", SwingConstants.RIGHT));
    }

    static final class ConnectionData {

        final SocketWrapper socket;
        final String username;

        ConnectionData(final Socket socket, final String username) throws IOException {
            this.socket = new SocketWrapper(socket);
            this.socket.write(username);
            if (!this.socket.readBoolean()) {
                throw new IllegalArgumentException(this.socket.readString());
            }
            this.username = username;
        }

    }

}

@@ -1673,24 +1673,25 @@
 owDialog) %7B%0A
+%0A
             
@@ -1698,425 +1698,48 @@
     
-final int option = JOptionPane.showOptionDialog(%0A                        null,%0A                        createLoginPanel(tfUsername, tfAddress),%0A                        %22Connection Data%22,%0A                        OK_CANCEL_OPTION,%0A                        QUESTION_MESSAGE,%0A                        null,%0A                        OPTIONS,%0A                        OPT_CONNECT);%0A%0A                if (CHOICE_CONNECT != option
+if (!choseConnect(tfUsername, tfAddress)
 ) %7B%0A
@@ -2138,32 +2138,46 @@
 gumentException 
+%7C IOException 
 ex) %7B%0A          
@@ -2201,32 +2201,188 @@
 = true;%0A        
+        showError(ex.getMessage(), address);%0A            %7D%0A        %7D%0A    %7D%0A%0A    private static void showError(final String message, final String address) %7B%0A
         log.debu
@@ -2415,32 +2415,24 @@
 + address);%0A
-        
         JOpt
@@ -2483,41 +2483,17 @@
     
-        ex.getMessage(),%0A        
+message,%0A
     
@@ -2534,32 +2534,24 @@
             
-       
- 
 JOptionPane.
@@ -2574,129 +2574,94 @@
     
-        %7D catch (IOException ex) %7B%0A                showDialog = true;%0A                log.debug(%22Could not connect to %22 +
+%7D%0A%0A    private static boolean choseConnect(final JTextField username, final JTextField
  add
@@ -2657,33 +2657,34 @@
 xtField address)
-;
+ %7B
 %0A               
@@ -2668,39 +2668,56 @@
 ress) %7B%0A        
-       
+return CHOICE_CONNECT ==
  JOptionPane.sho
@@ -2717,35 +2717,29 @@
 ane.show
-Message
+Option
 Dialog(
-null,
 %0A       
@@ -2743,32 +2743,38 @@
             
+null,%0A
         
 %22Cannot conn
@@ -2765,137 +2765,154 @@
     
-%22Cannot connect to %22 + address + %22!%22,%0A                        %22Cannot connect%22,%0A                        JOptionPane.ERROR
+        createLoginPanel(username, address),%0A                %22Connection Data%22,%0A                OK_CANCEL_OPTION,%0A                QUESTION
 _MESSAGE
 );%0A 
@@ -2903,26 +2903,25 @@
 TION_MESSAGE
-);
+,
 %0A           
@@ -2917,35 +2917,88 @@
             
-%7D%0A        %7D
+    null,%0A                OPTIONS,%0A                OPT_CONNECT);
 %0A    %7D%0A%0A    

break function down