/*
 * Created on Mar 15, 2004
 */
package org.lucci.madhoc.util;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.lucci.madhoc.messaging.MemoryConsumingObject;

public class Buffer
{
    public final static int BYTES = 1;
    public final static int OBJECTS = 2;


    private int maximumSize = 10000;
    private List<MemoryConsumingObject> list = new LinkedList<MemoryConsumingObject>();
    private int overload = 0;
    private int unit = BYTES;

    public int getUnit()
    {
        return unit;
    }
    public void setUnit(int limitationMode)
    {
        this.unit = limitationMode;
    }
    /**
     * @return Returns the overheaded generated by one iteration
     */
    public int getOverload()
    {
        return overload;
    }

    /**
     * @param overheaded The overheaded to set.
     * This method is called by the simulation to reinit this value to zero.
     */
    public void setOverload(int overhead)
    {
        this.overload = overhead;
    }

    public void add(MemoryConsumingObject o)
        throws IOException
    {
        add(list.size(), o);
    }

    public void add(int i, MemoryConsumingObject o)
        throws IOException
    {
        int osize = getSize(o);

        if (osize > getMaximumSize() - getCurrentSize())
        {
            overload += osize;
            throw new IOException("buffer is full");
        }
        else
        {       
            list.add(i, o);
        }
    }
    
    public int getSize(MemoryConsumingObject o)
    {
        return getUnit() == BYTES ? o.getSizeInBytes() : 1;
    }

    public MemoryConsumingObject get(int i)
    {
        return (MemoryConsumingObject) list.get(i);
    }

    public MemoryConsumingObject remove(int i)
    {
        return (MemoryConsumingObject) list.remove(i);
    }
    
    public void remove(MemoryConsumingObject o)
    {
        if (this.list.remove(o) == false)
        {
            throw new IllegalArgumentException("message not contained in the buffer");      
        }
    }
    
    public int getMaximumSize()
    {
        return maximumSize;
    }

    public void setMaximumSize(int i)
    {
        maximumSize = i;
    }

    public int getCurrentSize()
    {
        if (getUnit() == BYTES)
        {
            int size = 0;
            Iterator i = list.iterator();
            
            while (i.hasNext())
            {
                size += ((MemoryConsumingObject) i.next()).getSizeInBytes();
            }
            
            return size;
        }
        else
        {
            return list.size();
        }
    }
    
    public int getAvailableSize()
    {
        return getMaximumSize() - getCurrentSize();
    }
    
    public List internalList()
    {
        return this.list;
    }
}