// (c) 1999 Michael Dom und Wolfgang Westje
// Aenderungen von Torsten Zey
// Alle Rechte vorbehalten.

package ClientAufg2;
import java.util.Properties;
import java.io.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import VierGewinnt.*;

/**
 * Benutzeroberfläche zur Bedienung der einzelnen Module.
 * @author Michael Dom, Wolfgang Westje
 */
public class Client {

    private static final int COMPUTER_JAVA  = 2;
    private static final int COMPUTER_JAVA2 = 3;

    private static PartieManager manager;
    private static Meister meister;
    private static int ticket = 0;
    private static ORB orb;
    private static int bedenkzeit = 7;
    private static final String PARTIENAME = "Partie1";
    private static NamingContext root;


    private static void spielfeldAusgeben(short[][] feld) {
	for (int i=hoehe.value; i>=1; i--) {
	    System.out.print("|");
	    for (int j=0; j<breite.value; j++)
		System.out.print(" "+((feld[j][i]==0)? " " : 
				      String.valueOf(feld[j][i])));
	    System.out.println(" |");
	}
	for (int i=1; i<=breite.value; i++) System.out.print("--");
	System.out.print("---\n ");
	for (int i=1; i<=breite.value;i++) System.out.print(" "+i % 10);
	System.out.println();
    }

    // holt Grundkontext "root" und das Manager-Objekt
    private static PartieManager holeManager() {
	
	PartieManager manager = null;
	
	// HIER BEGINNT IHRE AUFGABE
	try{	
	    //bekommen den initialen Namingcontext
	    root  = NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));
	    
	    
	    //bauen die Pfadkomponenten zum Managerobjekt
            NameComponent nc1 = new NameComponent("4 gewinnt", "directory");
            NameComponent nc2 = new NameComponent("Partiemanager", "directory");
            NameComponent nc3 = new NameComponent("manager", "object");
	    //setzen den Pfad zusammen
            NameComponent[] name = {nc1, nc2, nc3};
            
            System.out.print("Versuche, Manager zu erhalten...");
            
            //Mit viel Hilfe wird der Manager herausgeist
	    org.omg.CORBA.Object obj = root.resolve(name); 
            manager = PartieManagerHelper.narrow(obj);
            System.out.println("hier isser!");
	    
	}
	catch(Exception e){System.out.println("\nholeManager-Error: "+e.toString());}
	// HIER ENDET IHRE AUFGABE
	return manager;
    }

    private static Meister holeMeister(int typ) {
	
	Meister meister=null;
	
	// HIER BEGINNT IHRE AUFGABE
	try{	
	    //bekommen den initialen Namingcontext, falls nötig, sollte nicht nötig sein
	    if(root==null)
		root  = NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));
	    //bauen die Pfadkomponenten zum Managerobjekt
            NameComponent nc1 = new NameComponent("4 gewinnt", "directory");
            NameComponent nc2 = new NameComponent("Computergegner", "directory");
	    NameComponent nc3;
	    if(typ==COMPUTER_JAVA)
		nc3 = new NameComponent("javameister", "object");
	    else
		nc3 = new NameComponent("javameister2", "object");
	    //setzen den Pfad zusammen
            NameComponent[] name = {nc1, nc2, nc3};
            
            System.out.print("Versuche, Computergegner zu erhalten...");
            
            //Mit viel Hilfe wird der Computergegner herausgeist
	    org.omg.CORBA.Object obj = root.resolve(name); 
            meister = MeisterHelper.narrow(obj);
            System.out.println("hier isser!");
	    

	}
	catch(Exception e){System.out.println("holeMeister-Error: "+e.toString());}
	// HIER ENDET IHRE AUFGABE
	return meister;
    }


    private static void spielen(String partieName, int spielerTyp) 
	throws NO_IMPLEMENT {
	int COMPUTER = 2;

	if (spielerTyp>=COMPUTER) {
		meister = holeMeister(spielerTyp);
		meister.spielstaerke(bedenkzeit*3000/7);
		if (meister==null) return;
	}

	Partie4gewinnt partie = manager.spielen(partieName);
	IntHolder ticketHolder = new IntHolder();
	short spielerNummer = partie.init(ticketHolder);

	ticket = ticketHolder.value;
	if (spielerTyp<COMPUTER) 
	    System.out.println("\nSie sind Spieler "+spielerNummer);
	else System.out.println("\nIch bin Spieler "+spielerNummer);
	System.out.println("warte auf Spieler "+(spielerNummer %2 +1)+"...\n");
	
	do {
	    short status = 0;
	    try{
		Thread.sleep(500);
	    } catch (InterruptedException e) {}
	    status = partie.status(ticket);
	    
	    
	    if (status==1) {
		System.out.println("Spielfeld zur Zeit:\n");
		short[][] feld = partie.holeSpielfeld();
		spielfeldAusgeben(feld);
		System.out.println();
		long startZeit=System.currentTimeMillis();
		
		if (spielerTyp<COMPUTER) {
		    BufferedReader in=
			new BufferedReader(new InputStreamReader(System.in));
		    
		    do {
			System.out.print("Ihr Zug (1-"+breite.value+"): ");
			try {
			    status=partie.ziehen(ticket,(short)Integer.parseInt
						 (in.readLine()));  
			}catch (IOException e) {}
			catch (NumberFormatException e) { status = -1; }
			catch (NO_IMPLEMENT e) { throw e; }
		    } while (status<=1);
		}
		else status = partie.
			 ziehen(ticket,meister.besterZug(spielerNummer, feld));
		
		System.out.print("\nZugdauer: ");
		System.out.print((System.currentTimeMillis()-startZeit)/1000);
		System.out.println(" sec.");
		System.out.println("\nSpielfeld nach dem Zug:\n");
		spielfeldAusgeben(partie.holeSpielfeld());
		System.out.println();
	    }

	    switch (status) {
		
	    case -1: 
		System.err.println("Internal Error! (cannot happen...)");
		System.exit(-1);
		
	    case 2:
		break;
		
	    case 3: 
		if (spielerTyp<COMPUTER) 
		    System.out.println("\nSie haben gewonnen:\n");
		else System.out.println("\nIch habe gewonnen:\n");
		spielfeldAusgeben(partie.holeSpielfeld());
		return;
		
	    case 4: 
		if (spielerTyp<COMPUTER) 
		    System.out.println("\nSie haben verloren:\n");
		else System.out.println("\nIch habe verloren:\n");
		spielfeldAusgeben(partie.holeSpielfeld());
		return;

	    case 5: 
		System.out.println("\nDas Spiel endet unentschieden:\n");
		spielfeldAusgeben(partie.holeSpielfeld());
		return;
	    }
	} while (true);  
    }
    
    public static void main(String[] args) {
	orb = ORB.init(args,null);
	
	manager = holeManager();
	if (manager == null) System.exit(-1);
/*	
	int spielerTyp = 1;
	if (args.length>1) {
	    if (args[1].equals("java")) spielerTyp=2;
	    if (args[1].equals("c++")) spielerTyp=3;
	    if (args.length>2) try {
		bedenkzeit = Integer.parseInt(args[2]);
	    } catch (NumberFormatException e) {}
	}
	if (args.length>0) {
	    if ((args[0].equals("--help")) || (args[0].equals("-h"))) {
		System.out.println("vbj Client <partie> [java|c++] <zeit>");
		System.exit(0);
	    }
	    try {
		spielen(args[0],spielerTyp);
	    } catch (NO_IMPLEMENT e) {
		System.err.println("** Server nicht erreichbar!");
	    }
	    System.exit(0);
	}
*/	
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
	do {
	    System.out.println("\n4 gewinnt");	
	    System.out.println  ("---------\n");
	    System.out.println("1) Partie spielen");
	    System.out.println("2) Computergegner starten (JAVAMeister)");
	    System.out.println("3) Computergegner starten (JAVAMeister2)");
	    System.out.println("4) Computerbedenkzeit einstellen");
	    System.out.println("5) Partien auflisten");
	    //	    System.out.println("6) Chat");
	    
	    System.out.println("7) Ende");
	    int auswahl=0;
	    try { 
		auswahl = Integer.parseInt(in.readLine());
	    } catch (Exception e) { }

	    switch(auswahl) 
		{
		case 1:
		case 2:
		case 3:
		    String eingabe = "";
		    System.out.print("\nEingabe des Partienamens: ");
		    try {
			eingabe = in.readLine();
		    } catch (IOException e) { }
		    if (eingabe.equals("")) eingabe=PARTIENAME;
		    try {
			spielen(eingabe,auswahl);
		    } catch (NO_IMPLEMENT e) {
			System.err.println("** Server nicht erreichbar!");
		    }
		    break;
		case 4:
		    System.out.print("\nEingabe der Bedenkzeit in Sekunden: ");
		    try {
			bedenkzeit = Integer.parseInt(in.readLine());
		    } catch (Exception e) { 
			bedenkzeit=7; 
		    }
		    break;
		case 5: 
		    System.out.println("\nPartien zur Zeit:\n"
				       +manager.auflisten());
		    break;
/*		case 6:
		    System.out.println("\nChat beenden mit /ende.\n");
		    Zuhoerer zuhoerer = new Zuhoerer();
		    Sprecher sprecher = new Sprecher();
		    while (true) {
			try {
			    
			    while (!in.ready()) Thread.sleep(100);
			    String zeile=in.readLine();

			    if (zeile.equals("/ende")) break; 
			    sprecher.sprich(zeile);
			} catch (Exception e) {e.printStackTrace();}
		    } 
		    sprecher.trennen();
		    zuhoerer.trennen();
		    break;
*/
		case 7:
		    System.exit(-1);
		}
	    // try{Thread.currentThread().join();}catch(Exception e){}
	} while (true); 
    }
    
}
