package Rectangles;

import Rectangles.Rectangles;
import Rectangles.IFCConstants;
import Rectangles.Robot;
import Rectangles.MoveResult;
import ui.*;

public class EnemyRobot extends Robot implements IFCConstants, Comparable {
	public static final double TOTALSCORE_GRANULARITY = 1000;
	public static final double POINTS_WEIGHT = .6;
	private double _playerScore;
	private int _distance;
	private Rectangles _rectangles;
	private Trail _trail;
	/*
	private Segment _closestSegment;
	private int _closestSegmentIndex;
	private Point _closestPoint;
	*/

	// _enemyRobot is the actual enemy we're examining
	// x, y is the position of the friendly robot (where we're examining from)
	public EnemyRobot( Robot _enemyRobot, int x, int y, Rectangles rectangles ) 
		throws Exception {
		super( _enemyRobot.xpos(), _enemyRobot.ypos() );

		// copy some basic info about the enemy robot
		_rectangles = rectangles;
		setColor( _enemyRobot.color() );
		setPlayerIndex( _enemyRobot.playerIndex() );
		setID( _enemyRobot.ID() );

		// calculate some stats about the enemy robot
		_trail = Hunter.traceback( rectangles, playerIndex(), ID() );
		_rectangles = rectangles;
		updatePointsScore( rectangles );
		updateDistanceTo( x, y );
	}

	public EnemyRobot( Robot _enemyRobot, Trail trail, int x, int y, Rectangles rectangles ) 
		throws Exception {
		super( _enemyRobot.xpos(), _enemyRobot.ypos() );

		// copy some basic info about the enemy robot
		setColor( _enemyRobot.color() );
		setPlayerIndex( _enemyRobot.playerIndex() );
		setID( _enemyRobot.ID() );

		// calculate some stats about the enemy robot
		_trail = trail;
		_rectangles = rectangles;
		updateDistanceTo( x, y );
		updatePointsScore( rectangles );
	}

	public Trail getTrail() {
		return( _trail );
	}

	// "distance that robot doesn't have to travel to reach enemy robot"
	public double distanceScore() throws Exception {
		return( ( 1 - POINTS_WEIGHT ) * ( 1.0 - ( _distance / ( 2.0 * ( double )( _rectangles.size() ) ) ) ) );
	}

	public double pointsScore() {
		return( POINTS_WEIGHT * _playerScore );
	}

	public double totalScore() throws Exception {
		return( TOTALSCORE_GRANULARITY * ( distanceScore() + pointsScore() ) );
	}

	// perhaps, use distance to trail behind enemy robots?
	// or, just use distance to current position of enemy robot?
	public void updateDistanceTo( int x, int y ) throws Exception {
		Point closestPoint = _trail.closestPoint( x, y, _rectangles );
		_distance = closestPoint.distanceTo( x, y );
		/*
		System.out.println( "closest point = [" + closestPoint.xpos() + ", " + 
			closestPoint.ypos() + "], robot at [" + xpos() + ", " + ypos() + 
			"] ref point = [" + x + ", " + y + "], dist = " + _distance 
		);
		*/
	}

	public void updatePointsScore( Rectangles rectangles ) throws Exception {
		MoveResult[] results = _rectangles.history();
		double[] currentScores;
		
		if( results.length > 0 ) {
			currentScores = results[results.length - 1].scores();

			// sum distances
			double totalScore = 0.0;

			for( int i = 0; i < currentScores.length; i++ ) {
				totalScore += currentScores[i];
			}

			// normalize players score
			if( totalScore > 0.0 ) {
				_playerScore = currentScores[playerIndex()] / totalScore;
			}
			else {
				_playerScore = 0.0;
			}
		}
		else {
			_playerScore = 0.0;
		}
	}

	// "How Traceback Destructive Robot Scores Enemy Robots"
	// - higher priority targets have high player scores and low distances
	// - lower priority targets have low player scores and high distances
	public int compareTo( Object another ) {
		EnemyRobot anotherEnemy = ( EnemyRobot )another;

		try {
			//return( ( int )( totalScore() - anotherEnemy.totalScore() ) );
			return( ( int )( anotherEnemy.totalScore() - totalScore() ) );
		}
		catch( Exception e ) {
			return( 0 );
		}
	}
}
