content: package utils.nexus;
  
  import java.util.ArrayList;
  import org.apache.log4j.Logger;
  
  public class NexusRangesTranslator {
  		
  	private static final Logger logger = Logger.getLogger(NexusRangesTranslator.class);
  	private ArrayList<NexusRange> nexusRanges = new ArrayList<NexusRange>();
  
  	public void addNexusRanges(ArrayList<NexusRange> allRanges) {
  		nexusRanges.addAll(allRanges);
  	}
  	
  	public Ranges convertToCodonRanges(){
  		Ranges allRanges = new Ranges();
  		allRanges.addRange(CodonRange.newDefaultRange());
  
  		int min = getMinPos() - 1; // minus one because nexus index starts at 1
  		int max = getMaxPos() - 1; // minus one because nexus index starts at 1
  		int startVal = getPosVal(min -1);
  		
  		CodonRange codonRange = new CodonRange(min - 1, max - 1, startVal);
  //		logger.info("codonRange" + codonRange);
  		
  		int defaultStartVal = 1;
  		int startValOffset = startVal - defaultStartVal; // one is default startVal
  		
  		for(int n = min; n <= max; n++){ // minus one because Nexus 
  				
  			int target = (n % 3) + 1;
  			
  			int targetModifiedWithStartValOffset = target + startValOffset;
  			if(targetModifiedWithStartValOffset > 3){
  				targetModifiedWithStartValOffset = targetModifiedWithStartValOffset - 3;
  			}
  			
  //			logger.info("n=" + n + " startVal=" + startVal + " target=" + target + "getPosVal(n)=" + getPosVal(n));
  			
  			startVal = getPosVal(n);
  			if(startVal != targetModifiedWithStartValOffset){
  				
  
  				if(startVal == 0 && codonRange.startVal == 0){
  					// do nothing - same as before
  				}
  				else{
  					codonRange.end = n - 1; // la
  					
  					
  					codonRange = new CodonRange(n, max, startVal);
  					allRanges.addRange(codonRange);
  					
  					startValOffset = startVal - target;
  					if(startValOffset < 0){
  						startValOffset = startValOffset + 3;
  					}
  
  				}
  			}
  			
  			
  		}
  		allRanges.debug();
  		return allRanges;
  	}
  	
  	public Ranges convertToCharsetRanges(){
  		Ranges allRanges = new Ranges();
  		allRanges.addRange(CodonRange.newDefaultRange());
  
  		int min = getMinPos() - 1; // minus one because nexus index starts at 1
  		int max = getMaxPos() - 1; // minus one because nexus index starts at 1
  		int startVal = getPosVal(min -1);
  		
  		CodonRange codonRange = new CodonRange(min - 1, max - 1, startVal);
  //		logger.info("codonRange" + codonRange);
  		
  		int defaultStartVal = 1;
  		int startValOffset = startVal - defaultStartVal; // one is default startVal
  		
  		for(int n = min; n <= max; n++){ // minus one because Nexus 
  				
  			int target = (n % 3) + 1;
  			
  			int targetModifiedWithStartValOffset = target + startValOffset;
  			if(targetModifiedWithStartValOffset > 3){
  				targetModifiedWithStartValOffset = targetModifiedWithStartValOffset - 3;
  			}
  			
  //			logger.info("n=" + n + " startVal=" + startVal + " target=" + target + "getPosVal(n)=" + getPosVal(n));
  			
  			startVal = getPosVal(n);
  			if(startVal != targetModifiedWithStartValOffset){
  				
  
  				if(startVal == 0 && codonRange.startVal == 0){
  					// do nothing - same as before
  				}
  				else{
  					codonRange.end = n - 1; // la
  					
  					
  					codonRange = new CodonRange(n, max, startVal);
  					allRanges.addRange(codonRange);
  					
  					startValOffset = startVal - target;
  					if(startValOffset < 0){
  						startValOffset = startValOffset + 3;
  					}
  
  				}
  			}
  			
  			
  		}
  		allRanges.debug();
  		return allRanges;
  	}
  	
  
  	private int getMinPos() {
  		int minVal = Integer.MAX_VALUE;
  		
  		for(NexusRange range : nexusRanges){
  			minVal = Math.min(minVal, range.getMinimumInt());
  		}
  		return minVal;	
  	}
  	
  	private int getMaxPos() {
  		int maxVal = Integer.MIN_VALUE;
  		
  		for(NexusRange range : nexusRanges){
  			maxVal = Math.max(maxVal, range.getMaximumInt());
  		}
  		return maxVal;	
  	}
  	
  	private int getPosVal(int n) {
  		
  		n = n + 1; // nexus ranges are using index 1 as first pos
  		
  		for(NexusRange range : nexusRanges){
  			if(n >= range.getMinimumInt() && n <= range.getMaximumInt()){
  				
  				int posInRange = n - range.getMinimumInt();
  				int rest = (posInRange) % range.getSteps();
  				
  //				logger.info("rest=" + rest);
  				if(rest == 0){
  	//				logger.info("n=" + n + " range.positionVal=" + range.positionVal);
  					return range.positionVal;
  				}
  
  			}
  		}
  		// default to 0 for positions not in range
  		return 0;
  	}
  	
  	
  
  }
  