/* Copyright (c) 2010, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.std.memory;

import java.util.Arrays;

import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.instance.InstanceData;

class ShiftRegisterData extends ClockState implements InstanceData {
	private BitWidth width;
	private Value[] vs;
	private int vsPos;
	
	public ShiftRegisterData(BitWidth width, int len) {
		this.width = width;
		this.vs = new Value[len];
		Arrays.fill(this.vs, Value.createKnown(width, 0));
		this.vsPos = 0;
	}
	
	@Override
	public ShiftRegisterData clone() {
		ShiftRegisterData ret = (ShiftRegisterData) super.clone();
		ret.vs = this.vs.clone();
		return ret;
	}
	
	public int getLength() {
		return vs.length;
	}
	
	public void setDimensions(BitWidth newWidth, int newLength) {
		Value[] v = vs;
		BitWidth oldWidth = width;
		int oldW = oldWidth.getWidth();
		int newW = newWidth.getWidth();
		if (v.length != newLength) {
			Value[] newV = new Value[newLength];
			int j = vsPos;
			int copy = Math.min(newLength, v.length);
			for (int i = 0; i < copy; i++) {
				newV[i] = v[j];
				j++;
				if (j == v.length) j = 0;
			}
			Arrays.fill(newV, copy, newLength, Value.createKnown(newWidth, 0));
			v = newV;
			vsPos = 0;
			vs = newV;
		}
		if (oldW != newW) {
			for (int i = 0; i < v.length; i++) {
				Value vi = v[i];
				if (vi.getWidth() != newW) {
					v[i] = vi.extendWidth(newW, Value.FALSE);
				}
			}
			width = newWidth;
		}
	}
	
	public void clear() {
		Arrays.fill(vs, Value.createKnown(width, 0));
		vsPos = 0;
	}
	
	public void push(Value v) {
		int pos = vsPos;
		vs[pos] = v;
		vsPos = pos >= vs.length - 1 ? 0 : pos + 1;
	}
	
	public Value get(int index) {
		int i = vsPos + index;
		Value[] v = vs;
		if (i >= v.length) i -= v.length;
		return v[i];
	}
	
	public void set(int index, Value val) {
		int i = vsPos + index;
		Value[] v = vs;
		if (i >= v.length) i -= v.length;
		v[i] = val;
	}
}