package common.model;

import java.util.Map;

import common.collect.Maps;
import common.util.ExtMath;
import common.util.Facing;
import common.util.Matrix4f;
import common.util.Vector3f;

public enum ModelRotation
{
    X0_Y0(0, 0),
    X0_Y90(0, 90),
    X0_Y180(0, 180),
    X0_Y270(0, 270),
    X90_Y0(90, 0),
    X90_Y90(90, 90),
    X90_Y180(90, 180),
    X90_Y270(90, 270),
    X180_Y0(180, 0),
    X180_Y90(180, 90),
    X180_Y180(180, 180),
    X180_Y270(180, 270),
    X270_Y0(270, 0),
    X270_Y90(270, 90),
    X270_Y180(270, 180),
    X270_Y270(270, 270);

    private static final Map<Integer, ModelRotation> mapRotations = Maps.<Integer, ModelRotation>newHashMap();
    private final int combinedXY;
    private final Matrix4f matrix4d;
    private final int quartersX;
    private final int quartersY;

    private static int combineXY(int p_177521_0_, int p_177521_1_)
    {
        return p_177521_0_ * 360 + p_177521_1_;
    }

    private ModelRotation(int p_i46087_3_, int p_i46087_4_)
    {
        this.combinedXY = combineXY(p_i46087_3_, p_i46087_4_);
        this.matrix4d = new Matrix4f();
        Matrix4f matrix4f = new Matrix4f();
        matrix4f.setIdentity();
        Matrix4f.rotate((float)(-p_i46087_3_) * 0.017453292F, new Vector3f(1.0F, 0.0F, 0.0F), matrix4f, matrix4f);
        this.quartersX = ExtMath.absi(p_i46087_3_ / 90);
        Matrix4f matrix4f1 = new Matrix4f();
        matrix4f1.setIdentity();
        Matrix4f.rotate((float)(-p_i46087_4_) * 0.017453292F, new Vector3f(0.0F, 1.0F, 0.0F), matrix4f1, matrix4f1);
        this.quartersY = ExtMath.absi(p_i46087_4_ / 90);
        Matrix4f.mul(matrix4f1, matrix4f, this.matrix4d);
    }

    public Matrix4f getMatrix4d()
    {
        return this.matrix4d;
    }

    public Facing rotateFace(Facing p_177523_1_)
    {
        Facing enumfacing = p_177523_1_;

        for (int i = 0; i < this.quartersX; ++i)
        {
            enumfacing = enumfacing.rotateAround(Facing.Axis.X);
        }

        if (enumfacing.getAxis() != Facing.Axis.Y)
        {
            for (int j = 0; j < this.quartersY; ++j)
            {
                enumfacing = enumfacing.rotateAround(Facing.Axis.Y);
            }
        }

        return enumfacing;
    }

    public int rotateVertex(Facing facing, int vertexIndex)
    {
        int i = vertexIndex;

        if (facing.getAxis() == Facing.Axis.X)
        {
            i = (vertexIndex + this.quartersX) % 4;
        }

        Facing enumfacing = facing;

        for (int j = 0; j < this.quartersX; ++j)
        {
            enumfacing = enumfacing.rotateAround(Facing.Axis.X);
        }

        if (enumfacing.getAxis() == Facing.Axis.Y)
        {
            i = (i + this.quartersY) % 4;
        }

        return i;
    }

    public static ModelRotation getModelRotation(int p_177524_0_, int p_177524_1_)
    {
        return (ModelRotation)mapRotations.get(Integer.valueOf(combineXY((p_177524_0_ % 360 + 360) % 360, (p_177524_1_ % 360 + 360) % 360)));
    }

    public static ModelRotation getNorthRot(Facing face)
    {
        switch(face) {
	        case NORTH:
	        default:
	        	return X0_Y0;
	        case SOUTH:
	        	return X0_Y180;
	        case WEST:
	        	return X0_Y270;
	        case EAST:
	        	return X0_Y90;
	        case DOWN:
	        	return X270_Y0;
	        case UP:
	        	return X90_Y0;
        }
    }

    public static ModelRotation getEastRot(Facing face, boolean flip)
    {
        switch(face) {
	        case NORTH:
	        default:
	        	return flip ? X180_Y270 : X0_Y270;
	        case SOUTH:
	        	return flip ? X180_Y90 : X0_Y90;
	        case WEST:
	        	return flip ? X180_Y180 : X0_Y180;
	        case EAST:
	        	return flip ? X180_Y0 : X0_Y0;
	        case DOWN:
	        	return X270_Y0;
	        case UP:
	        	return X90_Y0;
        }
    }

    static {
        for (ModelRotation modelrotation : values())
        {
            mapRotations.put(Integer.valueOf(modelrotation.combinedXY), modelrotation);
        }
    }
}
