package speiger.src.coreengine.platform.graphics.api.buffer;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.List;

import org.jspecify.annotations.NonNull;
import org.lwjgl.system.MemoryUtil;

import speiger.src.collections.ints.misc.pairs.IntObjectPair;
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.platform.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.platform.graphics.api.utils.BufferOwner;
import speiger.src.coreengine.platform.graphics.api.utils.GraphicsResource;

public abstract class VertexBuffer implements GraphicsResource {
	protected final BufferType type;
	protected final BufferState usage;
	protected int size;
	
	public VertexBuffer(BufferType type, BufferState usage) {
		this.type = type;
		this.usage = usage;
	}
	
	public BufferType type() {
		return type;
	}
	
	public BufferState usage() {
		return usage;
	}
	
	public int size() {
		return size;
	}
	
	public abstract VertexBuffer bind();
	public abstract VertexBuffer unbind();
	
	public abstract VertexBuffer allocate(int totalBytes);
	public abstract VertexBuffer set(long pointer, int totalBytes, BufferOwner owner);
	public VertexBuffer set(ByteBuffer buffer, BufferOwner owner) { return set(MemoryUtil.memAddress(buffer), buffer.remaining(), owner); }
	public VertexBuffer set(byte[] data) { return set(MemoryUtil.memAlloc(data.length).put(data).flip(), BufferOwner.GIVEN); }
	
	public abstract VertexBuffer fill(long pointer, int totalBytes, int offset, BufferOwner owner);
	public VertexBuffer fill(int offset, ByteBuffer buffer, BufferOwner owner) { return fill(MemoryUtil.memAddress(buffer), buffer.remaining(), offset, owner); }
	public VertexBuffer fill(int offset, byte[] data) {
		return fill(offset, MemoryUtil.memAlloc(data.length).put(data).flip(), BufferOwner.GIVEN);
	}
	
	public abstract VertexBuffer read(long pointer, int totalBytes, int offset, @NonNull Runnable completion);
	public VertexBuffer read(Buffer buffer, int totalBytes, int offset, @NonNull Runnable completion) { return read(MemoryUtil.memAddress(buffer), totalBytes, offset, completion); }
	
	public VertexBuffer fill(List<IntObjectPair<byte[]>> data) { return fill(0, data); }
	public abstract VertexBuffer fill(int offset, List<IntObjectPair<byte[]>> data);
	
	public abstract VertexBuffer shrink(int newSize);
	public abstract VertexBuffer grow(int newSize);
	public abstract VertexBuffer shift(int source, int dest, int length);
}
