package simulationObjects;

import java.util.ArrayList;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import controller.Grid;
import controller.GridInfo;

/**
 *
 * @author Will Chang
 *
 */
public class Patch extends Group {
    protected Cell myCell;
    protected int xCoord;
    protected int yCoord;
    protected Grid grid;
    protected ArrayList<Patch> myNeighbors;
    protected Image image;
    protected ImageView myView;
    protected State myState;
    protected PatchBody myBody;
    protected GridInfo infoSheet;
    
    private Class<?> myCellClass;

    private int myPreviousCellState;

    private int REMOVE_ME = 0;

    /**
     * Constructors
     */
    public Patch() {
	super();
	infoSheet = new GridInfo();
    }

    public Patch(int x, int y, Grid m) {
	super();
	initialize(x, y, m);
    }
    
    /**
     * creates a patch body for the patch
     * 
     * @param bodyType
     * what kind of shape it is
     */
    public void createBody(int bodyType){
        if (myBody != null){
            getChildren().remove(myBody);
        }
        //TODO: use reflection
        switch (bodyType){
            case 0:
                myBody = new PatchBodyRectangle(xCoord,yCoord,grid.getMinHeight(),grid.getMinWidth(),grid.getGridHeight(),grid.getGridWidth());
                break;
            case 1:
                myBody = new PatchBodyTriangle(xCoord,yCoord,grid.getMinHeight(),grid.getMinWidth(),grid.getGridHeight(),grid.getGridWidth());
                break;
            case 2:
                myBody = new PatchBodyHexagon(xCoord,yCoord,grid.getMinHeight(),grid.getMinWidth(),grid.getGridHeight(),grid.getGridWidth());
                break;
        }
        if (myCell != null){
            updateCellConstraints(myCell);
        }
        getChildren().add(myBody);
    }

    protected enum State {
	EMPTY, GENERATING, OCCUPIED, EMPTYING
    }

    /**
     * For Special patch simulations.
     *
     * @param x
     *            loc
     * @param y
     *            loc
     * @param m
     *            manager
     */
    public void initialize(int x, int y, Grid m) {
	xCoord = x;
	yCoord = y;
	grid = m;
	infoSheet = new GridInfo();
	myState = State.EMPTY;
    }

    /**
     * Returns surrounding Patches
     */
    public void getNeighbors() {
	myNeighbors = grid.getNeighborsAround(xCoord, yCoord);
    }

    /**
     * Gets the cell
     *
     * @return myCell
     */
    public Cell getCell() {
	return myCell;
    }

    public int getGridX() {
	return xCoord;
    }

    public int getGridY() {
	return yCoord;
    }

    /**
     * Sets up the update
     */
    public void prepareToUpdate() {
	if (myCell != null) {
	    myCell.prepareToUpdate(this, myNeighbors);
	}
    }

    /**
     * Updates patch and the cell
     */
    public void update() {
	// Update this
	if (myCell != null) {
	    myCell.update(this, myNeighbors);
	    // TODO put 0 into the GridInfo/GameInfo
	    if (myCell != null && myCell.getState() == 0) {
		removeCell();
	    }
	}

    }

    // modified the order for processing 4 directions
    protected enum relativePosition {
	NORTH, SOUTH, EAST, WEST, SOUTHEAST, NORTHEAST, SOUTHWEST, NORTHWEST
    }

    public boolean isEmpty() {
	return myCell == null;
    }

    /**
     * Adds cell along with GUI info.
     *
     * @param cell
     *            to occupy patch
     */
    public void addCell(Cell cell) {
	if (myCell != null) {
	    removeCell();
	}
	myState = State.OCCUPIED;
	myCell = cell;
	updateCellConstraints(myCell);
        getChildren().add(myCell);
    }
    
    public void updateCellConstraints(Cell cell){
        cell.setHeight(myBody.getPatchWidth()/2);
        cell.setWidth(myBody.getPatchWidth()/2);
        cell.setLayoutX(myBody.getCenter().x-myBody.getPatchWidth()/4);
        cell.setLayoutY(myBody.getCenter().y-myBody.getPatchHeight()/4);
        cell.setArcHeight(cell.getHeight());
        cell.setArcWidth(cell.getWidth());
    }

    public void removeCell() {
	if (myCell != null) {
	    getChildren().remove(myCell);
	    myCell = null;
	    myState = State.EMPTY;
	}
    }

    public Patch randomEmptyPatch() {
	// get an empty patch from grid manager
	return grid.findEmptyPatch();
    }

    public int getPreviousState() {
	return myPreviousCellState;
    }

    public void setPreviousState(int myState) {
	myPreviousCellState = myState;
    }
    
    //TODO for new simulations
    public int getState()
    {
        return 0;
    }
    public void setCellClass(Class<?> c){
        myCellClass = c;
    }

    public void toggleCellState () {
        if (myCell != null){
            int nextState = myCell.getNextState();
            if (nextState == -1){
                removeCell();
            }
            else{
                myCell.setState(nextState);
            }
        }
        else{
            try {
                addCell((Cell) myCellClass.newInstance());
                myCell.setState(1);
                myCell.setX(xCoord);
                myCell.setY(yCoord);
            }
            catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    public void setColorToBody(Color myColor) {
	myBody.setFill(myColor);
    }

}

@@ -4945,18 +4945,224 @@
     
+createNewCell();%0A        %7D%0A    %7D%0A%0A    /**%0A     * create a new cell and assign it to this patch%0A     * new cell comes from the cell class stored in this patch%0A     */%0A    private void createNewCell () %7B%0A        
 try %7B%0A
-    
     
@@ -5216,36 +5216,32 @@
 ));%0A            
-    
 myCell.setState(
@@ -5244,20 +5244,16 @@
 ate(1);%0A
-    
         
@@ -5281,36 +5281,32 @@
 d);%0A            
-    
 myCell.setY(yCoo
@@ -5314,34 +5314,26 @@
 d);%0A        
-    %7D%0A    
+%7D%0A
         catc
@@ -5400,20 +5400,16 @@
         
-   
- 
 e.printS
@@ -5417,38 +5417,24 @@
 ackTrace();%0A
-            %7D%0A
         %7D%0A  

Move cell creation to a new class