package de.nplusc.izc.tools.baseTools;


//import java.lang.reflect.Array;
import java.util.LinkedList;
//import java.util.concurrent.TimeUnit;
//import java.util.concurrent.locks.Condition;
//import java.util.concurrent.locks.Lock;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author LH
 */
public class RingBuffer<T>
{
     // <editor-fold defaultstate="collapsed" desc="Altlast">
    /*private T[] BufferContent;
    private int[] BufferConfig = new int[]{0,0,0};//0=currentbasePoint1=currentWritePoint2=max
   
    public RingBuffer(Class<T> clazz)
    {
         BufferConfig[2] = 10;//DefaultValue
         BufferConfig[0] = 0;
         BufferConfig[1] = 0;
         initStorage(clazz);
    }
        public RingBuffer(Class<T> clazz,T defaultValue)
    {
         BufferConfig[2] = 10;//DefaultValue
         BufferConfig[0] = 0;
         BufferConfig[1] = 0;
         initStorage(clazz,defaultValue);
    }
    
    public RingBuffer(Class<T> clazz,int length,T defaultValue)
    {
        BufferConfig[2] = length;
        BufferConfig[0] = 0;
        BufferConfig[1] = 0;
        initStorage(clazz,defaultValue);
    }
        public RingBuffer(Class<T> clazz,int length)
    {
        BufferConfig[0] = 0;
        BufferConfig[1] = 0;
        BufferConfig[2] = length;
        initStorage(clazz);
    }
    
    private void initStorage(Class<T> clazz,T defaultValue)
    {
       // Class<T> c = new Class<T>();
        BufferContent =(T[])Array.newInstance(clazz,BufferConfig[2]);
        for (int i=0;i<BufferConfig[2];i++)
        {
            T t = BufferContent[i];
            if(clazz==String.class)
            {
                  t =  (T) (defaultValue.toString()+i);
            }
            else
            {
                t = defaultValue;
            }
            BufferContent[i] = t;
        }
                //new T[length];
    }
    private void initStorage(Class<T> clazz)
    {
       // Class<T> c = new Class<T>();
        BufferContent =(T[])Array.newInstance(clazz,BufferConfig[2]);
                //new T[length];
    }
    public int getWriteIdx()
    {
        int[]c = BufferConfig;
        int ret = 0;
        if(c[0]>c[1])
        {
            c[1]+=c[2];
        }
        ret=c[1]-c[0];
        return ret;
    }
    public T getContentAt(int pos)
    {
        System.err.println("1|"+pos);
        pos = BufferConfig[0]+pos;
        System.err.println("2|"+pos);
        if(pos>BufferConfig[2])//keine 3 hier sonst AIOOBX(ArrayIndexOutOfBoundsException)
        {
            pos-=BufferConfig[2];
            System.err.println("3|"+pos);
        }
        return BufferContent[pos];
        //return null;//teturn null;
    }
    public T getOldestItem(boolean rmv)
    {
        T ret = BufferContent[BufferConfig[0]];
        if(rmv)
        {
            BufferConfig[0]++;
            if(BufferConfig[0]>=BufferConfig[2])
            {
                BufferConfig[0]-=BufferConfig[2];
            }
        }
        return ret;
    }
    public void addItem(T item)
    {
        if(BufferConfig[1]+1==BufferConfig[0])
        {
            getOldestItem(true);
        }
        addItem(item,BufferConfig[1]);
        BufferConfig[1]++;
        if(BufferConfig[1]>=BufferConfig[2])
        {
            BufferConfig[1]-=BufferConfig[2];
        }
       
    }
    public void addItem(T item,int pos)//Dränglercode
    {
        BufferContent[pos] = item;
    }*/
    //</editor-fold>
    private int lengthUsed;
    private int length;
    private T defaults;
    private Class T;
    private Lock lo = new Lock();
    private LinkedList<T> l = new LinkedList<>();
    private boolean retDefault = false;
    
    public RingBuffer(Class<T> clazz)
    {
        length=10;
        defaults = null;
    }
        public RingBuffer(Class<T> clazz,T defaultValue)
    {
        length=10;
        defaults = defaultValue;
        retDefault=true;
    }
    
    public RingBuffer(Class<T> clazz,int length,T defaultValue)
    {
        this.length=length;
        defaults = defaultValue;
        retDefault=true;
    }
        public RingBuffer(Class<T> clazz,int length)
    {
        this.length=length;
        defaults = null;
    }
    
    public T getContentAt(int idx)
    {
        T ret = null;
        boolean c = false;
        boolean s = false;
        if(idx<length&&idx<l.size())
        {
            ret = l.get(idx);
            if(T==String.class)
            {
                s=true;
            }
            c=true;
        }
        if(!c)
        {
            ret=defaults;
            if(s)
            {
                ret=(T)(defaults.toString()+"|"+idx);
            }
            if(!retDefault)
            {
               // throw new Exception();
                ret=null;
            }
        }
        return ret;
    }
    public T getOldestElement()
    {
        return l.peekFirst();
    }
    public T getNewestElement()
    {
        return l.peekLast();
    }
    
    public void addItem(T item)
    {
        try
        {
            lo.lock();
            if(lengthUsed>=length)
            {
                lengthUsed--;
               l.removeFirst();
            }
            lengthUsed++;
            l.add(item);
            lo.unlock();
        }
        catch (InterruptedException ex)
        {
            ex.printStackTrace();
        }
    }
    public void addItem(T item,int pos)
    {
        l.remove(pos);
        l.add(pos, item);
    }
}
