import java.io.*;
import java.net.*;

public class NetFlip extends Flip {

  private NetInterface ni;

  public static void main(String args[]){
    if(args.length != 1){
      System.err.println("Usage: java NetFlip serverhost");
    } else {
      new NetFlip(args[0]);
    }
  }

  public NetFlip(String server){
    super();
    setTitle("NetFlip");
    ni = new NetInterface(server, this);
  }

  public void pushButton(int row, int col){
    // This overrides the pushButton method from the Flip class
    // and arranges that when the user pushes a button, the push
    // is sent over the network to the server, and hence all clients.
    ni.sendPush(row, col);
  }

  public void pushLocalButton(int row, int col){
    // This is used when the server tells us about a pushing of
    // a button, to just do the response (flipping) on this one client.
    // This is the same as what happens in normal non-Net Flip when
    // the user pushes a button, so we just use the Flip class's method.
    super.pushButton(row, col);
  }
}

class NetInterface extends Thread {

  static final int port = 8199; // agreed upon with FlipServer, unassigned
  NetFlip nFlip;
  Socket sock;
  InputStream in;
  OutputStream out;

  public NetInterface(String server, NetFlip nf){
    nFlip = nf;
    try{
      sock = new Socket(server, port);
      in = sock.getInputStream();
      out = sock.getOutputStream();
      start(); // start thread listening for pushes from the server
    } catch(Exception e){
      System.err.println(e);
      System.err.println("Trouble connecting to server; running standalone.");
    }
  }

  public void run(){  // runs in the thread listening to the server
    try{
      while(true){
        int row = in.read();
        int col = in.read();
        if(col == -1){  // end of data indication
          break;        // break out of loop to closeDown
        }
        nFlip.pushLocalButton(row, col);
      }
      closeDown(); // this means the server died -- shut down connection
    } catch(Exception e){
      System.err.println(e);
      System.exit(1);
    }
  }

  public void sendPush(int row, int col){
    if(out == null){  // no server connection
      nFlip.pushLocalButton(row, col); // so locally fake the round-trip
    } else {
      try{
        out.write(row);
        out.write(col);
      } catch(Exception e){
        System.err.println(e);
        System.exit(1);
      }
    }
  }
  
  private void closeDown() throws IOException {
    out.close();
    in.close();
    sock.close();
    System.err.println("Server shut down; reverting to standalone operation.");
    out = null;  // so we know to do the pushing locally
  }
}