package thebetweenlands.util;

public class TextureAtlasHelper {
	private final float horizontalSegments, verticalSegments, horizontalPadding, verticalPadding;

	/**
	 * Creates a new texture atlas helper.
	 * Some padding may be required in order to prevent texture bleeding
	 * caused by anisotropic filtering. The padding must be the same on all
	 * sides of a segment.
	 * @param texWidth Texture width
	 * @param texHeight Texture height
	 * @param segmentWidth Segment width (including padding)
	 * @param segmentHeight Segment height (including padding)
	 * @param horizontalPadding Horizontal padding
	 * @param verticalPadding Vertical padding
	 */
	public TextureAtlasHelper(int texWidth, int texHeight, int segmentWidth, int segmentHeight, int horizontalPadding, int verticalPadding) {
		this.horizontalSegments = (float)texWidth / (float)segmentWidth;
		this.verticalSegments = (float)texHeight / (float)segmentHeight;
		this.horizontalPadding = (float)horizontalPadding / (float)texWidth;
		this.verticalPadding = (float)verticalPadding / (float)texHeight;
	}

	/**
	 * Creates a new texture atlas helper with equal texture, segment and padding width/height.
	 * Some padding may be required in order to prevent texture bleeding
	 * caused by anisotropic filtering. The padding must be the same on all
	 * sides of a segment.
	 * @param texSize Texture size
	 * @param segmentSize Segment size
	 * @param padding Padding size
	 */
	public TextureAtlasHelper(int texSize, int segmentSize, int padding) {
		this(texSize, texSize, segmentSize, segmentSize, padding, padding);
	}

	/**
	 * Returns the relative (0.0 - 1.0) min. and max. UVs for the given segment of the texture.
	 * Index 0 is min. UV coordinates and index 1 is max. UV coordinates.
	 * @param segment Texture segment
	 * @return Relative min. and max. UVs
	 */
	public float[][] getUVs(int segment) {
		float[][] ret = new float[2][2];
		float diffU = 1.0F;
		float diffV = 1.0F;
		float segmentX = segment % (int)this.horizontalSegments;
		float segmentY = segment / (int)this.verticalSegments;
		float relU = (float)segmentX / (float)this.horizontalSegments;
		float relV = (float)segmentY / (float)this.verticalSegments;
		float segmentMinU = diffU * (relU + this.horizontalPadding);
		float segmentMinV = diffV * (relV + this.verticalPadding);
		float segmentMaxU = diffU * (relU + 1.0F / (float)this.horizontalSegments - this.horizontalPadding);
		float segmentMaxV = diffV * (relV + 1.0F / (float)this.verticalSegments - this.verticalPadding);
		ret[0][0] = (float)(segmentMinU);
		ret[0][1] = (float)(segmentMinV);
		ret[1][0] = (float)(segmentMaxU);
		ret[1][1] = (float)(segmentMaxV);
		return ret;
	}

	/**
	 * Returns the relative (0.0 - 1.0) min. and max. interpolated UVs for the given segment of the texture.
	 * Index 0 is min. UV coordinates and index 1 is max. UV coordinates.
	 * @param segment Texture segment
	 * @param umin
	 * @param vmin
	 * @param umax
	 * @param vmax
	 * @return Relative interpolated min. and max. UVs
	 */
	public float[][] getInterpolatedUVs(int segment, float umin, float vmin, float umax, float vmax) {
		float[][] ret = new float[2][2];
		float[][] UVs = this.getUVs(segment);
		float uDiff = UVs[1][0] - UVs[0][0];
		float vDiff = UVs[1][1] - UVs[0][1];
		ret[0][0] = UVs[0][0] + uDiff * umin;
		ret[0][1] = UVs[0][1] + vDiff * vmin;
		ret[1][0] = UVs[0][0] + uDiff * umax;
		ret[1][1] = UVs[0][1] + vDiff * vmax;
		return ret;
	}
}
