package de.ugoe.cs.eventbench.models;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import de.ugoe.cs.eventbench.data.Event;

public class PredictionByPartialMatch extends TrieBasedModel {
	
	/**
	 * Id for object serialization.
	 */
	private static final long serialVersionUID = 1L;
	
	double probEscape;
	
	public PredictionByPartialMatch(int markovOrder, Random r) {
		this(markovOrder, r, 0.1);
	}
	
	public PredictionByPartialMatch(int markovOrder, Random r, double probEscape) {
		super(markovOrder, r);
		this.probEscape = probEscape;
	}
	
	public void setProbEscape(double probEscape) {
		this.probEscape = probEscape;
	}
	
	public double getProbEscape() {
		return probEscape;
	}
	
	@Override
	public double getProbability(List<Event<?>> context, Event<?> symbol) {
		double result = 0.0d;
		double resultCurrentContex = 0.0d;
		double resultShorterContex = 0.0d;
		
		List<Event<?>> contextCopy;
		if( context.size()>=trieOrder ) {
			contextCopy = new LinkedList<Event<?>>(context.subList(context.size()-trieOrder+1, context.size()));
		} else {
			contextCopy = new LinkedList<Event<?>>(context);
		}

	
		List<Event<?>> followers = trie.getFollowingSymbols(contextCopy); // \Sigma'
		int sumCountFollowers = 0; // N(s\sigma')
		for( Event<?> follower : followers ) {
			sumCountFollowers += trie.getCount(contextCopy, follower);
		}
		
		int countSymbol = trie.getCount(contextCopy, symbol); // N(s\sigma)
		if( contextCopy.size()==0 ) {
			resultCurrentContex = ((double) countSymbol) / sumCountFollowers;
		} else {
			if( sumCountFollowers==0 ) {
				resultCurrentContex = 0.0;
			}
			else {
				resultCurrentContex = ((double) countSymbol / sumCountFollowers)*(1-probEscape);
			}
			contextCopy.remove(0); 
			double probSuffix = getProbability(contextCopy, symbol);
			if( followers.size()==0 ) {
				resultShorterContex = probSuffix;
			} else {
				resultShorterContex = probEscape*probSuffix;
			}
		}
		result = resultCurrentContex+resultShorterContex;
		
		return result;
	}
}
