package common.model;

import common.util.Facing;

public abstract class Model {
	public abstract Model uvLock();
	public abstract Model rotate(ModelRotation rot);
	public abstract Model add(float x1, float y1, float z1, float x2, float y2, float z2);
	public abstract Model noShade();
	public abstract Model rotate(float x, float y, float z, Facing.Axis axisIn, float angleIn, boolean rescaleIn);
	public abstract Model face(String texture, Facing... faces);
	public abstract Model cull(Facing cull);
	public abstract Model tint();
	public abstract Model rot(int rot);
	public abstract Model uv(float x1, float y1, float x2, float y2);
	public abstract String getPrimary();
	
    public Model slab(boolean upper) {
    	return this.slab(upper, this.getPrimary(), this.getPrimary());
    }
    
    public Model slab(boolean upper, String du) {
    	return this.slab(upper, du, du);
    }
    
    public Model slab(boolean upper, String down, String up) {
    	return this.add(0, upper ? 8 : 0, 0, 16, upper ? 16 : 8, 16).nswe().uv(0, upper ? 0 : 8, 16, upper ? 8 : 16)
    			.d(down).cull(upper ? null : Facing.DOWN).u(up).cull(upper ? Facing.UP : null);
    }
    
    public Model vslab(Facing dir) {
    	return this.vslab(dir, this.getPrimary(), this.getPrimary());
    }
    
    public Model vslab(Facing dir, String du) {
    	return this.vslab(dir, du, du);
    }
    
    public Model vslab(Facing dir, String down, String up) {
    	return this.add(0, 0, 0, 16, 16, 8).du().uv(0, 8, 16, 16).we().uv(0, 8, 16, 16).rot(90).n(down).s(up).noCull().rotate(ModelRotation.getNorthRot(dir));
    }
    
    public Model cross() {
    	return this
    			.add(0.8f, 0f, 8f, 15.2f, 16f, 8f).noShade().rotate(8, 8, 8, Facing.Axis.Y, 45, true)
    			.ns().uv(0, 0, 16, 16).noCull()
    			.add(8f, 0f, 0.8f, 8f, 16f, 15.2f).noShade().rotate(8, 8, 8, Facing.Axis.Y, 45, true)
    			.we().uv(0, 0, 16, 16).noCull();
    }
    
    public Model crossTint() {
    	return this
    			.add(0.8f, 0f, 8f, 15.2f, 16f, 8f).noShade().rotate(8, 8, 8, Facing.Axis.Y, 45, true)
    			.ns().uv(0, 0, 16, 16).noCull().tint()
    			.add(8f, 0f, 0.8f, 8f, 16f, 15.2f).noShade().rotate(8, 8, 8, Facing.Axis.Y, 45, true)
    			.we().uv(0, 0, 16, 16).noCull().tint();
    }
    
    public Model stairs(boolean upper, boolean inner, boolean outer, boolean left, Facing dir, String down, String up) {
    	this.add(0, 0, 0, 16, 8, 16).d(down).uv(0, 0, 16, 16).u(up).noCull().uv(0, 0, 16, 16).nswe().uv(0, 8, 16, 16);
    	if(outer)
        	this.add(8, 8, 8, 16, 16, 16).d(down).uv(8, 0, 16, 8).u(up).uv(8, 8, 16, 16).n().noCull().uv(0, 0, 8, 8).s().uv(8, 0, 16, 8)
    				.w().noCull().uv(8, 0, 16, 8).e().uv(0, 0, 8, 8);
    	else
    		this.add(8, 8, 0, 16, 16, 16).d(down).uv(inner ? 8 : 0, 0, 16, 16).u(up).uv(inner ? 8 : 0, 0, 16, 16).n().uv(0, 0, 8, 8)
    				.s().uv(8, 0, 16, 8).w().noCull().uv(0, 0, 16, 8).e().uv(0, 0, 16, 8);
    	if(inner)
    		this.add(0, 8, 8, 8, 16, 16).d(down).uv(0, 0, 8, 8).u(up).uv(0, 8, 8, 16).n().noCull().uv(8, 0, 16, 8).s().uv(0, 0, 8, 8)
					.w().uv(8, 0, 16, 8).e().uv(0, 0, 8, 8);
    	return this.rotate(ModelRotation.getEastRot(left ? Facing.getHorizontal(dir.getHorizontalIndex() + 3) : dir, upper)).uvLock();
    }
    
    public Model add() {
    	return this.add(0, 0, 0, 16, 16, 16);
    }
    
    public Model d(String textureIn) {
    	return this.face(textureIn, Facing.DOWN);
    }
    
    public Model u(String textureIn) {
    	return this.face(textureIn, Facing.UP);
    }
    
    public Model n(String textureIn) {
    	return this.face(textureIn, Facing.NORTH);
    }
    
    public Model s(String textureIn) {
    	return this.face(textureIn, Facing.SOUTH);
    }
    
    public Model w(String textureIn) {
    	return this.face(textureIn, Facing.WEST);
    }
    
    public Model e(String textureIn) {
    	return this.face(textureIn, Facing.EAST);
    }
    
    public Model nswe(String textureIn) {
    	return this.face(textureIn, Facing.NORTH, Facing.SOUTH, Facing.WEST, Facing.EAST);
    }
    
    public Model dnswe(String textureIn) {
    	return this.face(textureIn, Facing.DOWN, Facing.NORTH, Facing.SOUTH, Facing.WEST, Facing.EAST);
    }
    
    public Model du(String textureIn) {
    	return this.face(textureIn, Facing.DOWN, Facing.UP);
    }
    
    public Model ns(String textureIn) {
    	return this.face(textureIn, Facing.NORTH, Facing.SOUTH);
    }
    
    public Model we(String textureIn) {
    	return this.face(textureIn, Facing.WEST, Facing.EAST);
    }
    
    public Model all(String textureIn) {
    	return this.face(textureIn, Facing.DOWN, Facing.UP, Facing.NORTH, Facing.SOUTH, Facing.WEST, Facing.EAST);
    }
    
    public Model d() {
    	return this.d(this.getPrimary());
    }
    
    public Model u() {
    	return this.u(this.getPrimary());
    }
    
    public Model n() {
    	return this.n(this.getPrimary());
    }
    
    public Model s() {
    	return this.s(this.getPrimary());
    }
    
    public Model w() {
    	return this.w(this.getPrimary());
    }
    
    public Model e() {
    	return this.e(this.getPrimary());
    }
    
    public Model nswe() {
    	return this.nswe(this.getPrimary());
    }
    
    public Model dnswe() {
    	return this.dnswe(this.getPrimary());
    }
    
    public Model du() {
    	return this.du(this.getPrimary());
    }
    
    public Model ns() {
    	return this.ns(this.getPrimary());
    }
    
    public Model we() {
    	return this.we(this.getPrimary());
    }
    
    public Model all() {
    	return this.all(this.getPrimary());
    }
    
    public Model noCull() {
    	return this.cull(null);
    }
}