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

import java.util.List;
import java.util.Objects;

import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList;
import speiger.src.coreengine.assets.api.ID;
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferBinding;
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.BufferMode;
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureBinding;
import speiger.src.coreengine.platform.graphics.api.shader.states.Bindings.TextureMode;
import speiger.src.coreengine.platform.graphics.api.texture.states.TextureType;

public record ComputePipeline(ID id, ID shader, List<BufferBinding> uniforms, List<TextureBinding> textures) {
	
	public static Builder builder(ID id) {
		return new Builder(id);
	}
	
	public static class Builder {
		ID id;
		ID shader;
		ObjectList<BufferBinding> uniforms = new ObjectArrayList<>();
		ObjectList<TextureBinding> textures = new ObjectArrayList<>();
		
		private Builder(ID id) {
			this.id = Objects.requireNonNull(id);
		}
		
		public Builder withShader(ID shader) {
			this.shader = Objects.requireNonNull(shader);
			return this;
		}
		
		public Builder withUniform(String name, int binding, int slot, int bytes) {
			uniforms.add(new BufferBinding(Objects.requireNonNull(name), binding, slot, bytes, BufferMode.UNIFORM));
			return this;
		}
		
		public Builder withBuffer(String name, int binding, int slot, int bytes) {
			uniforms.add(new BufferBinding(Objects.requireNonNull(name), binding, slot, bytes, BufferMode.STORAGE));
			return this;
		}
		
		public Builder withTexture(String name, int binding, int slot, TextureType type) {
			textures.add(new TextureBinding(Objects.requireNonNull(name), binding, slot, type, TextureMode.SAMPLER));
			return this;
		}
		
		public Builder withStorage(String name, int binding, int slot, TextureType type) {
			textures.add(new TextureBinding(Objects.requireNonNull(name), binding, slot, type, TextureMode.IMAGE_BUFFER));
			return this;
		}
		
		public ComputePipeline build() {
			return new ComputePipeline(id, Objects.requireNonNull(shader, "A Shader has to exist"), uniforms, textures);
		}
	}
}
