package hw1;

import java.util.ArrayList;
import java.util.Arrays;

public class Node {
	private int[] value;
	private Node parent;
	private int level;
	private String direction;
	private int zIndex;

	public Node(int[] state, Node parent, int level, String direction, int zIndex) {
		this.setValue(state);
		this.setParent(parent);
		this.setLevel(level);
		this.setDirection(direction);
		this.setZIndex(zIndex);
	}
	
	public Node(int[] state) {
		this.setValue(state);
		this.setParent(null);
		this.setLevel(0);
		for (int i = 0; i<state.length; i++) {
			if (state[i] == 0) {
				this.setZIndex(i);
				break;
			}
		}
	}	
	
	public ArrayList<Node> getChildren() {
		
		int[] parentState = null;
		if (parent != null)
			parentState = parent.value;
		
		int row = zIndex / 3;
		int col = zIndex % 3;
		
		ArrayList<Integer> zeroIndices = new ArrayList<Integer>();
		ArrayList<String> directions = new ArrayList<String>();
		
		if (row != 0) { // NORTH
			zeroIndices.add(3*(row - 1) + col);
			directions.add("N");
		}
		if (row != 2) { // SOUTH
			zeroIndices.add(3*(row + 1) + col);
			directions.add("S");
		}
		if (col != 0) { // WEST
			zeroIndices.add(3*row + (col - 1));
			directions.add("W");
		}
		if (col != 2) { // EAST
			zeroIndices.add(3*row + (col + 1));
			directions.add("E");
		}
		
		ArrayList<Node> children = new ArrayList<Node>();
		for (int i=0; i<zeroIndices.size(); i++) {
			int[] newState = Arrays.copyOf(value, value.length);
			int index = zeroIndices.get(i);
			newState[zIndex] = value[index];
			newState[index] = 0;
			if (!Arrays.equals(newState, parentState))
				children.add(new Node(newState, this, this.level+1, directions.get(i), index));
		}
		return children;
	}
	
	public String getValueString() {
		int[] c = value;
		return c[0]+""+c[1]+""+c[2]+""+c[3]+""+c[4]+""+c[5]+""+c[6]+""+c[7]+""+c[8];
	}

	public void setValue(int[] value) {
		this.value = value;
	}

	public int[] getValue() {
		return value;
	}
	
	public void setParent(Node parent) {
		this.parent = parent;
	}

	public Node getParent() {
		return parent;
	}
	
	public void setLevel(int level) {
		this.level = level;
	}

	public int getLevel() {
		return level;
	}

	public void setDirection(String direction) {
		this.direction = direction;
	}

	public String getDirection() {
		return direction;
	}

	public void setZIndex(int zIndex) {
		this.zIndex = zIndex;
	}

	public int getZIndex() {
		return zIndex;
	}	
}

