// (C) Copyright Jack Culpepper 1997
// This code may not be distributed without permission.
package gestalt;

import java.net.*;
import java.io.*;
import java.util.*;
import gestalt.Server;
import gestalt.Constants;
import gestalt.ClientRecord;
import gestalt.SlaveRecord;
import gestalt.ServerRecord;
import gestalt.Command;

public class Status extends Thread {
  static int number = 0;
  protected Socket peer;
  protected BufferedReader in;
  protected BufferedWriter out;
  protected Server server;

  public Status( Socket peer, Server server ) throws IOException {
    super( "Status-" + number++ + ":" + peer.getInetAddress().toString() +
      ":" + peer.getPort() );
    this.peer = peer;
    this.server = server;

    // Create the streams
    out = new BufferedWriter(
      new OutputStreamWriter( peer.getOutputStream() )
    );
    in = new BufferedReader(
      new InputStreamReader( peer.getInputStream() )
    );

    this.start();
  }

  public void println( String line ) {
    try {
      out.write( line, 0, line.length() );
      out.newLine();
      out.flush();
    }
    catch ( IOException e ) {
    }
  }

  public void print( String line ) {
    try {
      out.write( line, 0, line.length() );
      out.flush();
    }
    catch ( IOException e ) {
    }
  }

  public void printStatus( String[] stat ) {
    for ( int i = 0 ; i < stat.length ; i++ ) println( stat[ i ] );
  }

  public boolean exec( Command cmd ) {
    if ( cmd.getKey().equals( "ls" ) ) {
      if ( cmd.getValue().equals( "threads" ) ) {
        ThreadLister.listAllThreads( out );
      }
      else if ( cmd.getValue().equals( "slaves" ) ) {
        if ( server.slaves.isEmpty() ) println( "None." );
        else {
          print( "Waiting for synchronization..." );
          synchronized ( server.slaves ) {
            println( "synchronized." );
            for ( int i = 0 ; i < server.slaves.size() ; i++ ) {
              SlaveRecord rec = ( SlaveRecord )server.slaves.elementAt( i );
              println( "\n" + rec.status() );
            }
          }
        }
      }
      else if ( cmd.getValue().equals( "clients" ) ) {
        if ( server.clients.isEmpty() ) println( "None." );
        else {
          print( "Waiting for synchronization..." );
          synchronized ( server.clients ) {
            println( "synchronized." );
            for ( int i = 0 ; i < server.clients.size() ; i++ ) {
              ClientRecord rec = ( ClientRecord )server.clients.elementAt( i );
              println( "\n" + rec.status() );
            }
          }
        }
      }
      else if ( cmd.getValue().equals( "servers" ) ) {
        if ( server.servers.isEmpty() ) println( "None." );
        else {
          print( "Waiting for synchronization..." );
          synchronized ( server.servers ) {
            println( "synchronized." );
            for ( int i = 0 ; i < server.servers.size() ; i++ ) {
              ServerRecord rec = ( ServerRecord )server.servers.elementAt( i );
              println( "\n" + rec.status() );
            }
          }
        }
      }
    }
    else if ( cmd.getKey().equals( "date" ) ) {
      if ( cmd.getValue().equals( "" ) ) println( ( new Date() ).toString() );
      else println( "Too many arguments." );
    }
    else if ( cmd.getKey().equals( "gc" ) ) {
      if ( cmd.getValue().equals( "" ) ) {
        print( "Garbage collecting..." );
        System.gc();
        println( "done." );
      }
      else {
        println( "Too many arguments." );
      }
    }
    else if ( cmd.getKey().equals( "couple" ) ) {
      if ( cmd.getValue().equals( "" ) ) println( "Not enough arguments." );
      else server.couple( cmd.getValue() );
    }
    else if ( cmd.getKey().equals( "help" ) ) {
      println( "Supported commands:" );
      println( "ls threads | slaves | clients" );
      println( "date" );
      println( "gc" );
      println( "couple <hostname>" );
      println( "help" );
      println( "addServer <hostname>" );
      println( "updateServers" );
      println( "quit | q | bye" );
    }
    else if ( cmd.getKey().equals( "addServer" ) ) {
      if ( cmd.getValue().equals( "" ) ) println( "Not enough arguments." );
      else server.serverNames.addElement( cmd.getValue() );
    }
    else if ( cmd.getKey().equals( "updateServers" ) ) {
      if ( cmd.getValue().equals( "" ) ) server.updateServers();
      else println( "Too many arguments." );
    }
    else if ( cmd.getKey().equals( "quit" ) ) {
      return true;
    }
    else if ( cmd.getKey().equals( "q" ) ) {
      return true;
    }
    else if ( cmd.getKey().equals( "bye" ) ) {
      return true;
    }
    else if ( cmd.getKey().equals( "" ) ) {
    }
    else {
      println( "\"" + cmd.getKey() + cmd.getValue() + "\": Unknown command." );
    }
    return false;
  }

  // prompt; read command; exec it
  public void run() {
    boolean done = false;

    try {
      println( "Gestalt " + Constants.version + " status ready." );
      while ( ! done ) {
        print( "g> " );
        String line = in.readLine();
        Command cmd = new Command( line );
        done = exec( cmd );
      }

      println( "Goodbye." );
    }
    catch ( IOException e ) {
      System.out.println( "IOException while reading from in stream: " + e );
    }
    close();
  }

  public void report(String s) {
    System.out.println(toString() + ": " + s);
  }

  public String toString() {
    return this.getName();
  }

  public void close() {
    try {
      in.close();
      out.close();
      peer.close();
    }
    catch ( IOException e ) {
      report( "IOException occurred while trying to close a stream: " + e );
    }
  }

}

