package jp.ac.nii.icpc2010.players;

import java.util.ArrayList;
import java.util.List;

import jp.ac.nii.icpc2010.players.BasePlayer;
import jp.ac.nii.icpc2010.playfield.FieldDirection;
import jp.ac.nii.icpc2010.playfield.IPlayField;

/**
 * Player that tries to eat coins using a primitive search strategy.
 * Because of the primitive strategy, sometimes this agent kills itself.
 * @author johan
 *
 */
public class CoinPlayer extends BasePlayer {

	public CoinPlayer(int id, IPlayField playField) {
		super(id, playField);		
	}

	@Override
	public FieldDirection getInput() {
		
		int r = 1;
		int[] target = null;
		
		while (target == null && r < 20) {
			target = squareScan(r);			
				++r;
		}
		
		if (target != null) {
			//target is now in unwrapped (potentially out of bounds ) coordinates
			
//			System.err.println("Target found at " + target[0] + ", " + target[1]);
			
			int curx = getX();
			int cury = getY();
			int xdiff = target[0] - curx;
			int ydiff = target[1] - cury;
			
//			System.out.println("xd " + xdiff + " yd " + ydiff);
			
			FieldDirection goalDir;
			if (Math.abs(xdiff) > Math.abs(ydiff)) {
				if (xdiff < 0) {
					goalDir = FieldDirection.Left;
				} else {
					goalDir = FieldDirection.Right;
				}
				
			} else {
				if (ydiff < 0) {
					goalDir = FieldDirection.Up;
				} else {
					goalDir = FieldDirection.Down;
				}
			}
			if (getSafeDirs(curx, cury).contains(goalDir)) {
				return goalDir;
			} 
			return pickSafe();
 		} else {
 			//System.err.println("No target found!");
 			return pickSafe();
		}
	}
	
	FieldDirection pickSafe() {
		List<FieldDirection> safeDirs = getSafeDirs(getX(), getY());

		if (safeDirs.isEmpty()) {	  
			//give up
			return FieldDirection.Up;
		}
		return safeDirs.get((int) (Math.random() * safeDirs.size()));		
	}
	
	
	private int adjustWidth(int coord) {
		while (coord < 0) {
			coord += getPlayField().getWidth();			
		}
		return coord % getPlayField().getWidth();
	}
	
	private int adjustHeight(int coord) {
		while (coord < 0) {
			coord += getPlayField().getHeight();			
		}
		return coord % getPlayField().getHeight();
	}
	
	
	/** 
	 * Scan for coins in a square of a certain "radius" starting from current position.
	 * Return null or the coordinates of a coin. 
	 * @param radius
	 * @return
	 */
	public int[] squareScan(int radius) {
		int curx = getX();
		int cury = getY();
		//		System.out.println("r " + radius);
		for (int i = curx - radius; i < curx + radius; ++ i) {
			for (int j = cury - radius; j < cury + radius; ++ j) {
				int ri = adjustWidth(i);
				int rj = adjustHeight(j);
				
				if (playField.getObjectAt(ri, rj) == OBJECT_COIN) {
					return new int[] {i, j};
				}
			}
		}
		return null;
	}
	
}
