/* Cyclops
 * FER - SPVP
 * Fakultet elektrotehnike i racunarstva (http://www.fer.hr/)
 * Unska 3, 10000 Zagreb, Hrvatska
 * (c) 2001 FER, Zagreb.
 */

package hr.fer.zesoi.cyclops;

import java.util.*;


/**
 * Cyclops simulator
 * The LineEnd class implements a generic line ending.
 * @author Darko Vasić
 * @author Tomislav Petković
 * @author Zvonko Kostanjčar
 * @version 19-05-2001
 */
class LineEnd
{

    /**
     * Maximal number of packets that can pass through the line
     * in one simulation cycle.
     */
    protected int max_capacity;

    /** Number of packets currently stored in a buffer. */
    protected int number_of_packets;

    /** Packet storage. */
    protected Stack storage_buffer = new Stack();

    /** Line reference. */
    protected Line line;

    /**
     * Default constructor. One packet buffer is created.
     */
    public LineEnd (Line line)
    {
	this.line = line;
	max_capacity = 1;
	number_of_packets = 0;
    }
    /* LineEnd */

    /**
     * Normal constructor. Buffer of specified capacity is created.
     */
    public LineEnd (Line line, int capacity)
    {
	this.line = line;
	max_capacity = capacity;
	number_of_packets = 0;
    }
    /* LineEnd */

    /**
     * Sets buffer capacity to specified capacity. If buffer contains
     * more elements then specified capacity, some elements are lost.
     * @param capacity Buffer capacity.
     */
    public void setCapacity (int capacity)
    {
	if (capacity > 0)
	    {
		while (capacity < number_of_packets)
		    {
			this.get();
		    }
		max_capacity = capacity;
	    }
	else
	    {
		while ( !storage_buffer.isEmpty() )
		    {
			this.get();
		    }
		max_capacity = capacity;
	    }
    }
    /* setCapacity */

    /**
     * Test for empty buffer. Returns true if empty.
     * @return Buffer status.
     */
    public boolean isEmpty ()
    {
	return storage_buffer.isEmpty();
    }
    /* isEmpty */

    /**
     * Puts one packet in the buffer. Returns true
     * if succesful, and false if buffer is full.
     *
     * @param packet New element.
     * @return Returns false for full buffer.
     */
    public boolean receive (Object packet)
    {
	if (number_of_packets <= max_capacity)
	    {
		storage_buffer.push(packet);
		number_of_packets = number_of_packets + 1;
		return true;
	    }
	else
	    {
		return false;
	    }
    }
    /* receive */

    /**
     * Gets next element (packet) and removes it from the
     * buffer. Generates exception if buffer is empty.
     * @return Returns buffer element (packet).
     */
    public Object get ()
    {
	Object packet;

	if (number_of_packets > 0)
	    {
		number_of_packets = number_of_packets - 1;
		packet = storage_buffer.pop();
		return packet;
	    }
	else
	    {
		throw new NoSuchElementException("No more packages.");
	    }
    }
    /* get */

    /**
     * Peeks at the first element.
     * @return Returns first element.
     */
    public Object peek ()
    {
	return storage_buffer.peek();
    }
    /* peek */

    /**
     * Gets element by index.
     * @return Returns element at index i;
     */
    public Object elementAt (int i)
    {
	return storage_buffer.elementAt(i);
    }
    /* elementAt */

    /**
     * Gets total number of elements.
     * @return Returns number of elements.
     */
    public int size() {
	return storage_buffer.size();
    }
    /* size */

    /**
     * Deletes line.
     */
    public void delete()
    {
	line.delete();
    }
    /* delete */

}
/* LineEnd */
