package calc;

/*
 * like the index2d object
 * this one compute in 3d
 * \____________________/
 *       /
 * \ ('<            <') /
 * (<=)              (=>)
 *
 * what if ...
 * \____________________/
 *                 \
 * \ ('>            >') /
 * (<=)              (=>)
 *
 * just shut up
 * \____________________/
 *      /
 * \ ('<            <') /
 * (<=)              (=>)
 * */

/**
 * @author martin
 *index 3d calculator
 */
public class Index3d {
	private final int _w,
    				  _h,
    				  _d;

	/**
	 * private constructor
	 * @param w as width
	 * @param h as height
	 * @param d as depth
	 */
	private Index3d(int w, int h, int d){
		_w = w;
		_h = h;
		_d = d;
	}

	/**
	 * static factory
	 * from rect coordinate
	 * @param w as width
	 * @param h as height
	 * @param d as depth
	 * @return new index 3d calculator
	 */
	public static Index3d fromRect(int w, int h, int d){
		if (w < 1 || h < 1 || d < 1)
			throw new IllegalArgumentException();
		return new Index3d(w,h,d);
	}

	/**
	 * static factory
	 * for cube size
	 * @param w as width
	 * @return new index 3d calculator
	 */
	public static Index3d fromCube(int w){
		if (w < 1)
			throw new IllegalArgumentException();
		return new Index3d(w,w,w);
	}

	/**
	 * size getter
	 * @return size
	 */
	public int size(){
		return _w*_h*_d;
	}

	/**
	 * index calculator
	 * @param x as coordinate
	 * @param y as coordinate
	 * @param z as coordinate
	 * @return index calculated
	 */
	public int index(int x, int y, int z){
		if (x < 0 || x > _w || y < 0 || y > _h || z < 0 || z > _d)
			throw new ArrayIndexOutOfBoundsException();
		return x + y * _w + z * _w * _h;
	}

	/**
	 * x calculator
	 * @param index
	 * @return x coordinate
	 */
	public int x(int index){
		if (index > size())
			throw new ArrayIndexOutOfBoundsException();
		return index % _w;
	}

	/**
	 * y calculator
	 * @param index
	 * @return y coordinate
	 */
	public int y(int index){
		if (index > size())
			throw new ArrayIndexOutOfBoundsException();
		return (index / _w)%_h;
	}

	/**
	 * z calculator
	 * @param index
	 * @return z coordinate
	 */
	public int z(int index){
		if (index > size())
			throw new ArrayIndexOutOfBoundsException();
		return index / (_w*_h);
	}

	/**
	 * getter
	 * @return width
	 */
	public int w(){
		return _w;
	}

	/**
	 * getter
	 * @return height
	 */
	public int h(){
		return _h;
	}

	/**
	 * getter
	 * @return depth
	 */
	public int d(){
		return _d;
	}

	public static void main(String [] args){
		Index3d t = new Index3d(3,3,4);

		for (int z=0;z<4;z++)
			for (int y=0;y<3;y++)
				for (int x=0;x<3;x++)
					System.out.print(t.index(x, y, z) + " ");
		System.out.println();
		for (int i=0;i<36;i++){
			System.out.print("("+t.x(i)+","+t.y(i)+","+t.z(i)+") ");
		}
	}
}
