package ca.ucalgary.seahawk.services;

import java.util.*;
import java.util.regex.*;

/**
 * A utility class used by MobyComplexBuilder to "trick" rule
 * evaluation into seeing specific individual instances of 
 * quantified regex capture groups, e.g. By calling setIteration()
 * we can get the first, second, etc. value of $1 captured by (\S+(\s+))+ 
 */
public class IterativeMatchResult implements MatchResult{
    private int iteration = 0;
    private Map<Integer,String[]> captureGroupIterValues;
    private String group;
    private int groupCount = 0;
    private int start = 0;
    private int end = 0;
    private String[] captureValues;
    private int longestListLength;

    public IterativeMatchResult(MatchResult baseMatch, Map<Integer,String[]> iterCaptureValues){
	// Copy all the values because we don't want the source MatchResult to change
	// from underneath our feet!  We are capturing a snapshot of the values at this c-tor time.
	groupCount = baseMatch.groupCount();
	captureValues = new String[groupCount+1];
	for(int i = 0; i <= groupCount; i++){
	    captureValues[i] = baseMatch.group(i);
	}
	start = baseMatch.start();
	end = baseMatch.end();

	captureGroupIterValues = iterCaptureValues;	

	// Figure out which list is the longest, others will have
	// their values looped, like in the R language
	longestListLength = -1;
	for(Map.Entry<Integer,String[]> entry: captureGroupIterValues.entrySet()){
	    if(entry.getValue().length > longestListLength){
		longestListLength = entry.getValue().length;
	    }
	}

    }

    public int getNumIterations(){
	return longestListLength;
    }

    public void setIteration(int i) throws IndexOutOfBoundsException{
	if(i < 0 || i >= longestListLength){
	    throw new IndexOutOfBoundsException("Request to set iteration to " + i + 
						", but the valid range is 0 to " + 
						longestListLength);
	}
	iteration = i;
    }
    public int getIteration(){
	return iteration;
    }

    public int end(){
	return end;
    }
    public int end(int group){
	return end;
    }

    public String group(){
	return captureValues[0];
    }
    public String group(int group){
	// First see if it's in the iterative list, if not, use base values
	if(captureGroupIterValues != null &&
	   !captureGroupIterValues.containsKey(group)){ //int autoboxed
	    return captureValues[group]; //may throw index OOB exception, like doc specifies
	}

	// Got here if it's an iter value
	String[] values = captureGroupIterValues.get(group);
	if(values == null || values.length == 0){
	    return "";
	}
	else{
	    // The modulus loops values from smaller arrays
	    return values[iteration%values.length];
	}
    }

    public int groupCount(){
	return groupCount;
    }
    public int start(){
	return start;
    }
    public int start(int group){
	return start;
    }    
}
