package com.danitheskunk.skunkworks.gfx;

import com.danitheskunk.skunkworks.Recti;
import com.danitheskunk.skunkworks.Vec2i;
import org.lwjgl.stb.STBImage;

import java.nio.ByteBuffer;

public class Image {
	private final byte[] data;
	private final Vec2i size;

	//constructors
	public Image(ByteBuffer buffer) { //png or similar
		//todo: resource system
		int[] x = {0}, y = {0}, n = {0};
		var img = STBImage.stbi_load_from_memory(buffer, x, y, n, 4);
		size = new Vec2i(x[0], y[0]);
		data = new byte[x[0] * y[0] * 4];
		assert img != null;
		img.get(data);
	}

	public Image(Vec2i size) {
		this.size = size;
		data = new byte[size.getX() * size.getY() * 4];
	}

	public Image(ByteBuffer buffer, Vec2i size) {
		data = new byte[buffer.remaining()];
		buffer.get(data);
		this.size = size;
	}

	public void drawImage(Image srcImage, Vec2i destPos) {
		drawImage(srcImage, destPos, new Recti(Vec2i.ZERO,
			srcImage.getSize()));
	}

	public void drawImage(Image srcImage, Vec2i destPos, Recti srcRect) {
		//todo: check bounds
		//todo: write in faster way than pixel stuff
		for(int y = 0; y < srcRect.getHeight(); ++y) {
			for(int x = 0; x < srcRect.getWidth(); ++x) {
				var iterPos = new Vec2i(x, y);
				var to = Vec2i.add(destPos, iterPos);
				var from = Vec2i.add(srcRect.getPos(), iterPos);
				setPixel(to, srcImage.getPixel(from));
			}
		}
	}

	//getters
	public byte[] getData() {
		return data;
	}

	public int getHeight() {
		return size.getY();
	}

	public Color getPixel(Vec2i pos) {
		int i = pos.getX() * 4 + pos.getY() * 4 * size.getX();
		return new Color(((int) data[i]) & 0xFF,
			((int) data[i + 1]) & 0xFF,
			((int) data[i + 2]) & 0xFF,
			((int) data[i + 3]) & 0xFF
		);
	}

	public Vec2i getSize() {
		return size;
	}

	public Image getSubImage(Recti rect) {
		Image img = new Image(rect.getSize());
		img.drawImage(this, Vec2i.ZERO, rect);
		return img;
	}

	public int getWidth() {
		return size.getX();
	}

	public void setPixel(Vec2i pos, Color col) {
		int i = pos.getX() * 4 + pos.getY() * 4 * size.getX();
		data[i] = (byte) (col.getR() & 0xFF);
		data[i + 1] = (byte) (col.getG() & 0xFF);
		data[i + 2] = (byte) (col.getB() & 0xFF);
		data[i + 3] = (byte) (col.getA() & 0xFF);
	}
}
