package savi.StateSynchronization;

import java.util.ArrayList;
import java.util.List;

import jason.asSyntax.Literal;

/**
 * Snapshot of perceptions. Contains a list of perceptions.
 * @author patrickgavigan
 *
 */
public class PerceptionSnapshot {

	private ArrayList<Perception> perceptionList;	// List of perceptions in the snapshot

	public PerceptionSnapshot() {
		this.perceptionList = new ArrayList<Perception>();
	}
	
	/**
	 * 
	 * @param snapshot
	 */
	public PerceptionSnapshot(PerceptionSnapshot snapshot) {
		this.perceptionList = snapshot.getPerceptionList();
	}
	
	/**
	 * 
	 * @param newPerception
	 */
	public void addPerception(Perception newPerception) {
		if (newPerception != null) {
			this.perceptionList.add(newPerception);
		}
	}

	/**
	 * 
	 * @param newPerceptions
	 */
	public void addPerceptionsFromSnapshot(PerceptionSnapshot newPerceptions) {
		List<Perception> newPerceptionList = new ArrayList<Perception>(newPerceptions.getPerceptionList());
		for (int i = 0; i < newPerceptionList.size(); i++) {
			this.addPerception(newPerceptionList.get(i));
		}
	}
	
	/**
	 * 
	 * @return
	 */
	public ArrayList<Perception> getPerceptionList() {
		return new ArrayList<Perception>(this.perceptionList);
	}
	
	
	/**
	 * Get the versionID of the most recent data in the snapshot
	 * @return
	 */
	public double getLatestTimeStamp() {
		double latestTimeStamp = -1;
		
		for (int i = 0; i < this.perceptionList.size(); i++) {
			double current = this.perceptionList.get(i).getTimeStamp();
			if (current > latestTimeStamp) {
				latestTimeStamp = current;
			}
		}
		return latestTimeStamp;		
	}
	
	
	/**
	 * Gets the most similar perception from the store and returns it.
	 * Removes this perception from the snapshot
	 * @param percept
	 * @return The most similar perception, null if none are similar enough
	 */
	public Perception pullSimilarPerception(Perception otherPerception) {
		Perception similar = null;
		double difference = 100;
		int bestI = -1;
		
		for (int i = 0; i < this.perceptionList.size(); i++) {
			if (this.perceptionList.get(i).isSimilar(otherPerception)) {
				double currentDifference = this.perceptionList.get(i).getDifference(otherPerception);
				if (Math.abs(currentDifference) < Math.abs(difference)) {
					bestI = i;
					difference = currentDifference;
				}
			}
		}
		
		// Get the best one
		if (bestI != -1) {
			similar = this.perceptionList.get(bestI);
			this.perceptionList.remove(bestI);
		}
		return similar;
	}
	
	/**
	 * Get the output literals for this snapshot
	 * @return
	 */
	public List<Literal> getLiterals() {
		List<Literal> outputLiterals = new ArrayList<Literal>();
		for (int i = 0; i < this.perceptionList.size(); i++) {
			outputLiterals.add(this.perceptionList.get(i).getLiteral());
		}
		return outputLiterals;
	}
	
	/**
	 * Returns the perception literals as a string 
	 */
	public String toString() {
		return this.getLiterals().toString();
	}
}
