package de.unidortmund.dependencies;

public class Slot implements Content {

	private int index;

	private int level;

	private Content content;

	private int numberOfElements;

	private Slot(Slot slot, int level) {
		this.level = level;
		this.numberOfElements = 1;
		content = slot;
		Memory.registerSlot(this);
	}

	public Slot(Content content, int level) {
		this.level = level;
		this.numberOfElements = 1;
		Memory.registerSlot(this);
		if (level == 1) {
			// @todo mir über null Gedanken machen!
			this.content = content;
		} else {
			this.content = new Slot(content, level - 1);
		}
	}

	public Slot(Value[] contents, int level) {
		this.level = level;
		Memory.registerSlot(this);
		if (level == 3) {
			numberOfElements = 1;
			this.content = new Slot(contents, 2);
		} else {
			assert level == 2;
			numberOfElements = contents.length;
			Slot[] slots = new Slot[numberOfElements];
			for (int i = 0; i < numberOfElements; i++) {
				slots[i] = new Slot(contents[i], 3);
			}
			this.content = slots[0];
		}
	}

	public Slot(Variable[] variables, int level) {
		this.level = level;
		Memory.registerSlot(this);
		if (level == 3) {
			numberOfElements = 1;
			this.content = new Slot(variables, 2);
		} else {
			assert level == 2;
			numberOfElements = variables.length;
			Slot[] slots = new Slot[numberOfElements];
			for (int i = 0; i < numberOfElements; i++) {
				Slot valueSlot = (Slot) variables[i].getSlot().content;
				slots[i] = new Slot(valueSlot, 3);
			}
			this.content = slots[0];
		}
	}

	public int getNumberOfElements() {
		return numberOfElements;
	}

	public void setNumberOfElements(int numberOfElements) {
		this.numberOfElements = numberOfElements;
	}

	public int getLevel() {
		return level;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	private String getAddress() {
		return "a(" + level + "," + index + ")";
	}

	public String toString() {
		String result = getAddress();
		if (numberOfElements == 1) {
			result = result + " " + content.toString();
		} else {
			Slot firstSlot = (Slot) content;
			for (int i = 0; i < numberOfElements; i++) {
				result = result
						+ "\n"
						+ Memory.getSlot(firstSlot.level, firstSlot.index + i)
								.toString();
			}
		}
		return result;
	}

	public Slot getFirstSlotAtLevel(int level) {
		if (this.level == level) {
			return this;
		} else {
			return ((Slot) content).getFirstSlotAtLevel(level);
		}
	}

	public Slot getLastSlotAtLevel(int level) {
		// ist bisher programmiert und macht bisher Sinn nur bei der zweiten Schicht
		if (this.level == level) {
			if (level != 2) {
				return this;
			} else {
				if (((Slot) content).level == 3) {
					return this;
				}
			}
		}
		return ((Slot) content).getLastSlotAtLevel(level);
	}


	
	public boolean isComposite() {
		if (level == 3) {
			return ((Slot) content).isComposite();
		} else {
			// sollte Schicht2 sein
			Slot myValue = (Slot) content;
			if (myValue.level == 1) {
				return false;
			} else if (myValue.level == 3) {
				return true;
			} else {
				return myValue.isComposite();
			}
		}
	}

	public int getIndex() {
		return index;
	}

	public Value getValue() {
		assert numberOfElements == 1;
		if (content instanceof Value) {
			return (Value) content;
		} else {
			return ((Slot) content).getValue();
		}
	}

	public Content getContent() {
		return content;
	}

	public void setContent(Content content) {
		this.content = content;
	}

}
