//  package Tests;

import java.awt.event.*; // for mouseEvent and InputEvent
import java.beans.*;
import RemoteInterface.*; // for Move

public class TicTacToeTest 
    extends GameTest {
    
    
    public TicTacToeTest(String logFile) {
	super(logFile); // report file
	 
	className = "TicTacToe";        // CUT
	fileName =  "TicTacToe.java";   // CUT file name
    }

    // Preconditions: called by AbstractTest::testProcess via inheritance
    // Symantics: showTestMenu is to be used together with testDispatch
    // Postconditions: Displays super.showTestMenu and then displays
    //                 tests available in this class
    protected void showTestMenu(){
	super.showTestMenu();
	System.out.println("1. Create TicTacToe Game");
	System.out.println("2. Check Class Invariants");
	System.out.println("3. setMove(2) test ");
    }
    
    // Preconditions: called by AbstractTest::testProcess via inheritance
    //                called after a user has input "which" test to run
    //                the tests are numbered in showTestMenu.
    // Symantics: testDispatch is to be used with showTestMenu
    // Postconditions: Executes the user selected test
    protected void testDispatch(int which)
	throws Exception {
	
	switch (which) {
	case 1 :			// 1. Create GameBoard
	    functionalSuite();
	    break;
	case 2 :			// 2. Check Class Invariants
	    logTestResult( "Script2 - class Invariants", 
			   classInvariant() );
	    break;
	case 3:			// 14. setMove(2) test 
	    logTestResult( " 14. setMove(2) test  ",
			   setMoveTest(2) );
	    break;
	default :
	    super.testDispatch(which);
	    break;  
	}
	
    }
 
    //--------------------------------------------------------------
    // The following are test scripts to be used with GameBoard.java
    // tests Scripts return boolean and do not take parameters.
  
    public void functionalSuite(){
        testScript1();
	
	//      testScript2();
	//  	testScript3();
	//  	testScript4();
	
    }

    public void structuralSuite(){}
    public void interactionSuite(){}
    public void baselineSuite(){}
    public void regressionSuite(){}
    
    public boolean classInvariant(){
	
	boolean result;
	
	try {
	    int gameStatus 
		= ((Integer)(getPrivateField(OUT, "GameBoard","gameStatus"))).intValue();
	    boolean invariant1 =  ( gameStatus >= -1 && 
				    gameStatus <= 2 );
	    
	    boolean invariant2 = ((GameBoard)OUT).playerID >= -1 ;
	    
	    result = (invariant1 && invariant2);
	    
	} catch (Exception e) {
	    e.printStackTrace();
	    result = false;
	}
	
	return result;
    }

    
    protected boolean testScript1(){
	OUT = new Game();
	boolean result = testCase1();
	logTestResult("Script1",result);
	return result;
    }
    
    protected boolean testCase1(){
	boolean result;

	try {
	    ((Game)OUT).setSize(160, 160);
	    ((Game)OUT).setVisible(true);
	    showFieldValues(OUT, "Game");
	    result = ((Game)OUT).isVisible();
	}
	catch(Exception e) {
	    e.printStackTrace();
	    result = false;
	}

	return result;
    }

    // -------------------------------------------------------------
    // The following are individual tests.  Most of these take 
    // a paramater and can be used in a test Script.
    // the individual tests attempt to follow a nameing scheme
    // which is the name of primary method they exercise followed
    // by the postfix - test.
    
    public boolean setGameStatusTest(int status){
 
	//legal status values are
	// -1=playing, 0=lost, 1=won, 2=draw
	boolean result;

	try {
	    ((Game)OUT).setGameStatus(status);
	    int gameStatus 
		= ((Integer)(getPrivateField(OUT, "GameBoard","gameStatus"))).intValue();
	    result = (gameStatus == status) &&  classInvariant() ;
	} catch (Exception e) {
	    e.printStackTrace();
	    result = false;
	}

	return result;
	
    }

    // Postcondition: calls java.awt.component.setSize
    public boolean setSizeTest(int width, int height) {
	boolean result;

	try {
	    boolean result1 =  ((GameBoard)OUT).isResizable();
	    logTestResult( " Game set to resizable ",
			   result1 );
	    
	    ((GameBoard)OUT).setSize(width, height );
	    // prompt user for confirmation - jlr
	    
	    result = result1 && classInvariant();
	}
	catch (Exception e ) {
	    e.printStackTrace();
	    result = false;
	}

	return result;
    }
    
    public boolean testMouseDispatch(int x, int y) {
	boolean result;
	try {
	    MouseEvent mouseEvent = new MouseEvent( (GameBoard)OUT, // source
						    MouseEvent.MOUSE_CLICKED, // type
						    0, // when
						    InputEvent.BUTTON1_MASK, // modifier
						    x, // location
						    y, // location
						    1, // click count during time period
						    false // popupMenuTrigger
						    );

	    // NOTE: Events delivered using dispathEvent 
	    // bypass the system's event queue
	    ((GameBoard)OUT).dispatchEvent(mouseEvent);  

	    // could put a confirmation dialog box here - jlr
	    
	    result = true;
	}
	catch ( Exception e ) {
	    e.printStackTrace();
	    result = false;
	}

	return result;

    }

  protected boolean testMouseUp(int x, int y) {
	boolean results;
	
	try {
	    PropertyChangeTestListener propertyChangeTest 
		= new PropertyChangeTestListener();
	    
	     ((GameBoard)OUT).addPropertyChangeListener( propertyChangeTest );
	    
	    boolean result1 = testMouseDispatch(x,y);
	    logTestResult( "testMouseScript: testMouseDispatch( " + 
			   x + ", " + y + ")", 
			   result1 );
	    boolean result2 =  propertyChangeTest.isPropertyChangeReceived();
	    logTestResult( "testMouseScript: isPropertyChangeReceived()", 
			   result2 );
	    if ( result2 ) {
  		PropertyChangeEvent pce = propertyChangeTest.getLastPropertyChangeEvent();
  		Move newMove = (Move)pce.getNewValue();
  		System.out.println(newMove.newPosition);
  	    }
	    results = result1 && result2;
	
	}
	catch ( Exception e ) {
	    e.printStackTrace();
	    results = false;
	}
		
	return results;

    }

    protected boolean testMouseUp ( GameBoardPosition position ) {

	return testMouseUp(position.x, position.y);
	
   }

    protected boolean testMouseScript() {
	boolean result = true;
	
	try {
	    for ( int i = 0; i < ((GameBoard)OUT).position.length ; i++ ) {
		result &= testMouseUp (((GameBoard)OUT).position[i]);
		logTestResult( "testMouseScript: position["+i+"]", 
			       result );	
	    }
	}
	catch (Exception e ) {
	    e.printStackTrace();
	    result = false;
	}
	return result;
    }

    protected boolean setPlayerIDTest( int newPlayerID ) {

	boolean result;

	try {
	    ((GameBoard)OUT).setPlayerID( newPlayerID );
	    int playerID 
		//  = ((Integer)(getPrivateField(OUT, "GameBoard", "playerID"))).intValue();
		= ((GameBoard)OUT).playerID;

	    result = (newPlayerID == playerID) ;
	}
	catch (Exception e) {
	    e.printStackTrace();
	    result = false;
	}

	return result;

    }

    protected boolean setMoveTest( int pos ) {
	boolean results;
	
	try {
	    PropertyChangeTestListener propertyChangeTest 
		= new PropertyChangeTestListener();
	    
	    ((Game)OUT).addPropertyChangeListener( propertyChangeTest );
	    
	    Class parameterTypes[] =   { Integer.TYPE };
		
	    Object parameters[] = { new Integer(pos) };

	    invokePrivateMethod( OUT,   // object to invoke method on
				 "Game", // object type
				 "setMove", // method name
				 parameterTypes,
				 parameters
				 );

	    logTestResult( "testSetMove: invokePrivateMethod( setMove )", 
			   true );
	    boolean result1 =  propertyChangeTest.isPropertyChangeReceived();
	    logTestResult( "testSetMove: isPropertyChangeReceived()", 
			   result1 );
	    if ( result1 ) {
  		PropertyChangeEvent pce = propertyChangeTest.getLastPropertyChangeEvent();
  		Move newMove = (Move)pce.getNewValue();
  		System.out.println(newMove.newPosition);
  	    }
	    results = result1;
	
	}
	catch ( Exception e ) {
	    e.printStackTrace();
	    results = false;
	}
		
	return results;
    }
	
    

}
