import java.util.*;

/**
 * This class represents a reference segmentation related to a video file
 * used in shot boundary detection task programs of TREC 2001.
 *
 * @author NIST-ITL-IAD-Retrieval Group
 * This software was produced by NIST, an agency of the
 * U.S. government, and by statute is not subject to copyright in the
 * United States. Recipients of this software assume all
 * responsibilities associated with its operation, modification and
 * maintenance.
 *
 */

public class RefSegmentation extends Segmentation{

	/**
     * The number of frames of the video.
     *
     * @see #getElements()
     */
	protected int totalFrameNumber = 0;
	/**
     * Constructs Segmentation object with an ordering comparator for its set of transitions.
     *
     * @param     videoName The video name the segmentation is related to.
     * @param     orderingComparator The comparator used to order transitions in the set of trnasitions.
     * @param     totalFrameNumber The number of frames of the video.
     */
	public RefSegmentation(String videoName, Comparator orderingComparator, int totalFrameNumber){
		this.totalFrameNumber = totalFrameNumber;
		this.videoName = videoName;
		this.transitionSet = new TreeSet(orderingComparator);
	}
	/**
     * Process the comparison between the current assumed reference segmentation and the given system segmentation.
     *
     * @param     sysId The system Id of the given system segmentation.
     * @param     systemSegmentation The system segmentation to be compared with.
     * @return    an object representing all the results (measures...) of the comparison.
     * @exception TransitionDefinitionException if the definition of a transition is not correct (pre-frame >= post-frame).
     */	
	public comparisonResult processComparison(String sysId, Segmentation systemSegmentation) 
		throws TransitionDefinitionException{
	
		comparisonResult result = new comparisonResult(sysId, this.videoName, 
										this.totalFrameNumber);
		
		OverlapComparator overlap = OverlapComparator.getInstance();
		ApproximateComparator rone = ApproximateComparator.getInstance();
		int insertedTransCount = 0;
		int deletedTransCount = 0;		
		int insertedTransCountCut = 0;
		int deletedTransCountCut = 0;
		int insertedTransCountGradual = 0;
		int deletedTransCountGradual = 0;
		
		String nl = System.getProperty("line.separator");
		String insertionsSection = nl+"<insertion>"+nl+nl;
		String cutMatchSection = nl;
		String gradualMatchSection = nl;
		String deletionsSection = nl+"<deletion>"+nl+nl;
		
		//For each transition within the systemSegmentation
		//detection of insertion or match.
		Iterator el = systemSegmentation.getElements();		
		while(el.hasNext()){
			
			Transition c = (Transition) el.next();			
			
			Iterator ii = this.transitionSet.iterator();
			//INTERSECTING TRANSITIONS
			TreeSet comparisonSubset = new TreeSet(this.transitionSet.comparator());
			//NOT INTERSECTING TRANSITIONS BUT INSIDE A ZONE			
			Vector distantCuts = new Vector();
			while(ii.hasNext()){
				Transition t = (Transition) ii.next();
				if(c.intersected(t)) comparisonSubset.add(t);
				else if((t.type.equals("CUT") || t.length() <= 5) &&
						(c.type.equals("CUT") || c.length() <= 5) &&
				   		(Math.abs(c.getPre()-t.getPre()) <= 5) &&
				   		(Math.abs(c.getPost()-t.getPost()) <= 5)){
					distantCuts.addElement(t);
				}
			}			
			if ((comparisonSubset == null || comparisonSubset.isEmpty()) &&
				distantCuts.size() == 0){
				insertionsSection += c.sysToString();
				insertedTransCount++;
				if(c.type.equals("CUT")) insertedTransCountCut++;
				else insertedTransCountGradual++;
			}
			else{				
				Iterator i = comparisonSubset.iterator();
				while(c.matched != 1 && i.hasNext()){
					//temp is a part of the reference and c a part of the system
					Transition temp = (Transition) i.next();
					//Comparison with a determined order in use of equalityComparators
					if(temp.sameType(c)){
						//RONE
						if((temp.length() == 1 || c.length() == 1) && rone.compare(temp, c) == 0){
							temp.matched = 1;
							c.matched = 1;
							cutMatchSection += nl+c.sysToString()+temp.refToString();
						}
						//RMIN RMAX
						else if (overlap.compare(temp, c) == 0){
							temp.matched = 1;
							c.matched = 1;
							gradualMatchSection += nl+c.sysToString()+temp.refToString();
						}
					}
				}
				//DISTANT CUTS or assimilate
				if(c.matched != 1){
					Transition shorterCut = null;
					
					Iterator dCutsIterator = distantCuts.iterator();					
					while(dCutsIterator.hasNext()){
						Transition temp = (Transition) dCutsIterator.next();						
						if(shorterCut == null){
							shorterCut = temp;
							c.matched = 1;
						}
						if(Math.abs(temp.getPre() - c.getPre()) <
							Math.abs(shorterCut.getPre() - c.getPre())){
							shorterCut = temp;
							c.matched = 1;
						}
						else if(Math.abs(temp.getPre() - c.getPre()) ==
								Math.abs(shorterCut.getPre() - c.getPre()) &&
								temp.matched != 1 && shorterCut.matched == 1){
							shorterCut = temp;
							c.matched = 1;
						}
					}
					if(c.matched == 1)
						cutMatchSection += nl+c.sysToString()+shorterCut.refToString();
					if(shorterCut != null){
						shorterCut.matched = 1;
						distantCuts.remove(shorterCut);
						dCutsIterator = distantCuts.iterator();						
						while(dCutsIterator.hasNext()){
							cutMatchSection += ((Transition) dCutsIterator.next()).refToString();
						}
					}
				}
				if(c.matched != 1){
					insertionsSection += c.sysToString();
					insertedTransCount++;
					if(c.type.equals("CUT")) insertedTransCountCut++;
					else insertedTransCountGradual++;
				}
			}
		}
		//For each transition within the refSegmentation
		//detection of DELETION with MATCHED attribute in transition objects
		Iterator m = this.getElements();
		while(m.hasNext()){
			Transition t = (Transition) m.next();
			if(t.matched == 0){
				deletionsSection += t.refToString();
				deletedTransCount++;
				if(t.type.equals("CUT")){
					deletedTransCountCut++;
				}
				else{
					deletedTransCountGradual++;
				}
			}			
		}
		insertionsSection += nl+"</insertion>"+nl;
		deletionsSection += nl+"</deletion>"+nl;
			
		result.setResults(this.getTransitionCount(),
						  insertedTransCount,
						  deletedTransCount, 
						  cutMatchSection,
						  this.getCutFrameCount(),
						  insertedTransCountCut,
						  deletedTransCountCut,
						  gradualMatchSection,
						  insertedTransCountGradual,
						  deletedTransCountGradual,
						  insertionsSection,
						  deletionsSection);
		return result;
	}
	
}