package com.danitheskunk.skunkworks.audio.nodes;

import com.danitheskunk.skunkworks.audio.AudioBuffer;
import com.danitheskunk.skunkworks.audio.AudioEngine;

public abstract class Node {
	private final AudioEngine engine;
	private final int[] inConnectionSlots;
	private final Node[] inConnections;
	private final int inCount;
	private final boolean[] isOutConnected;
	private final int outCount;

	public Node(AudioEngine engine, int inCount, int outCount) {
		this.inCount = inCount;
		this.outCount = outCount;
		isOutConnected = new boolean[outCount];
		inConnections = new Node[inCount];
		inConnectionSlots = new int[inCount];
		this.engine = engine;
		if(outCount > 1) {
			throw new RuntimeException("more than one out connection not yet" +
				" " +
				"allowed, needs handling in getBuffer to only process once");
		}
	}

	public static void connect(Node src, int srcSlot, Node dst, int dstSlot) {
		if(srcSlot < 0 || srcSlot >= src.outCount) {
			throw new RuntimeException("invalid srcSlot");
		}
		if(dstSlot < 0 || dstSlot >= dst.inCount) {
			throw new RuntimeException("invalid dstSlot");
		}
		if(src.isOutConnected[srcSlot]) {
			throw new RuntimeException("src node slot already connected");
		}
		if(dst.inConnections[dstSlot] != null) {
			throw new RuntimeException("dst node slot already connected");
		}
		src.isOutConnected[srcSlot] = true;
		dst.inConnections[dstSlot] = src;
		dst.inConnectionSlots[dstSlot] = srcSlot;
	}

	public abstract AudioBuffer getBuffer(int slot);

	protected AudioBuffer getBufferFromInput(int inSlot) {
		if(inConnections[inSlot] == null) return null;
		return inConnections[inSlot].getBuffer(inConnectionSlots[inSlot]);
	}

	public AudioEngine getEngine() {
		return engine;
	}

	public int getInCount() {
		return inCount;
	}

	public int getOutCount() {
		return outCount;
	}
}
