package net.anotheria.moskito.core.threshold.alerts;

import net.anotheria.moskito.core.config.MoskitoConfigurationHolder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * This class contains all generated alerts at runtime. This class is an one-value-enum-singleton described by J. Bloch.
 * @author lrosenberg
 *
 */
public enum AlertHistory {
	/**
	 * Singleton instance.
	 */
	INSTANCE;
	//its ok to return the original list, since all operations create a copy. The only thing we need to care about is 
	//simultaneous add, and that is guarded by the lock.
	/**
	 * List of alerts.
	 */
	private List<ThresholdAlert> alerts = new CopyOnWriteArrayList<ThresholdAlert>();
	/**
	 * Lock for write operations.
	 */
	private ReadWriteLock lock = new ReentrantReadWriteLock();

	/**
	 * Adds a new alert. If the number of totally saved alerts is greater than AlertHistoryConfig.getToleratedNumberOfItems() the list is cut.
	 * @param alert
	 */
	public void addAlert(ThresholdAlert alert){
		lock.writeLock().lock();
		try{
			alerts.add(alert);
			if (alerts.size()>MoskitoConfigurationHolder.getConfiguration().getThresholdsAlertsConfig().getAlertHistoryConfig().getToleratedNumberOfItems()){
				//Changed the logic, not to use sublist anymore, but instead create a new list, if the size is growing too large.
				//Question remains, if we should get rid of copyonwrite and add a read lock instead.
				CopyOnWriteArrayList<ThresholdAlert> newAlerts = new CopyOnWriteArrayList<ThresholdAlert>();
				for (int i=alerts.size()-MoskitoConfigurationHolder.getConfiguration().getThresholdsAlertsConfig().getAlertHistoryConfig().getMaxNumberOfItems(); i< alerts.size(); i++){
					newAlerts.add(alerts.get(i));
				}
				alerts = newAlerts;
			}
		}finally{
			lock.writeLock().unlock();
		}
	}
	/**
	 * Returns the alerts sofar.
	 * @return
	 */
	public List<ThresholdAlert> getAlerts(){
		List<ThresholdAlert> ret = new ArrayList<ThresholdAlert>(alerts);
		Collections.reverse(ret);
		return ret;
	}
}
