package CookieCutter.g2;

import java.util.*;
import CookieCutter.*;

/**
 * Modifeied Pillsbury Doughboy
 * Original Authors:
 * @author Mark Ayzenshtat
 * @author Vlad Shchogolev
 * @author David Vespe
 * new Authors
 * Yaniv
 * Alex
 * ALexis
 */
public class Group2Player1 implements IFCPlayer {

	private String kName = "Modified PD";
	private CookieCutter mCC;
	private Cookie[] mCookieShapes;
	private int mNumCookieCopies;
	private Move[] mMoves;

	public void register(CookieCutter iCC) throws Exception {
		mCC = iCC;
		Vertex[][] shapes = mCC.cookieshapes();
		mCookieShapes = new Cookie[shapes.length];
		for (int i = 0; i < shapes.length; i++) {
			mCookieShapes[i] = new Cookie(shapes[i], mCC);
		}

		mNumCookieCopies = mCC.cookieCopies();
	}

	public Move[] moves() throws Exception {
		if (mMoves == null) {
			mMoves = new Move[mCookieShapes.length];
			for (int i = 0; i < mMoves.length; i++) {
				mMoves[i] = new Move(mNumCookieCopies);
				computeMove(mMoves[i], mCookieShapes[i]);
			}
		}

		return mMoves;
	}

	/**
	 * This method packs and orients N copies of the given cookie shape and
	 * stores this information in the given move object.
	 */
	private void computeMove(Move iMove, Cookie iShape) {
		double minScore = Double.MAX_VALUE;
		Cookie[] bestPattern = cutCookies(iShape);
		
		optimumCutter placer = new optimumCutter();

		// run the given cookie shape through each cookie placer
		// keep the configuration that yields the minimum score
//		for (int i = 0; i < placers.length; i++) {
			Cookie[] cookies = cutCookies(iShape);

			//			System.out.println("\n------------\n[computeMove] placing cookies\n-----------\n");
			cookies = placer.placeCookies(cookies);//s[i]

			// make sure cookies don't intersect each other or dough borders
			//			System.out.println("[computeMove] checking for illegal placements");
			//			System.out.println("[computeMove] Cookie dump:");
			//			for (int z=0;z<cookies.length;z++){
			//			    System.out.println("\tCookie "+z+": "+cookies[z]);
			//			}
			if (!isLegal(cookies)) {
			    System.out.println("WARNING: CookiePlacer " + placer.getClass().getName()//s[i]
					       + " created a bad cookie arrangement, ignoring");
			} else {
			    //			    System.out.println("[computeMove] placements are valid. getting rightmost point of the cookies");
			    double score = Cookie.computeRightBoundary(cookies);
			    if (score < minScore) {
				minScore = score;
				bestPattern = cookies;
			    }
			}
//		}

		// write our final cookies to the move object
		storeInMove(bestPattern, iMove);
	}

	/**
	 * Return true if this is a legal cookie arrangement
	 */
	private boolean isLegal(Cookie[] iCookies) {
	    try {
// 		for (int i = 0; i < iCookies.length; i++) {
// 			if (!iCookies[i].isInBound()) {
// 				return false;
// 			}

// 			for (int j = i+1; j < iCookies.length; j++) {
// 				if (iCookies[i].intersects(iCookies[j])) {
// 					return false;
// 				}
//			}
//		}
	    }
	    catch (NullPointerException npe) {
		System.out.println("Null Pointer caught in isLegal: " + npe);
	    }

		return true;
	}

	private Cookie[] cutCookies(Cookie iTemplate) {
		// we create an array of N clones of this Cookie
		Cookie[] cookies = new Cookie[mNumCookieCopies];
		for (int i = 0; i < cookies.length; i++) {
			cookies[i] = iTemplate.copy();
		}

		return cookies;
	}

	/**
	 * Stores cookies' positions and orientations in the move object.  Also,
	 * computes the rightmost boundary of the cookie set stores it in the move
	 * object.
	 */
	private void storeInMove(Cookie[] iCookies, Move iMove) {
		// compute the rightmost boundary
		iMove.setRightBoundary(Cookie.computeRightBoundary(iCookies));
		try {
			for (int i = 0; i < iCookies.length; i++) {
				iMove.setCookiePosition(i, iCookies[i].getCentroid().asVertex(),
					iCookies[i].getRotation());
			}
		} catch (Exception ex) {
			System.err.println(ex);
		}
	}

	public String name() throws Exception {
		return kName;
	}

	public boolean interactive() throws Exception {
		return false;
	}
}
