package au.edu.wehi.idsv.picard;

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

import htsjdk.samtools.QueryInterval;
import htsjdk.samtools.reference.ReferenceSequenceFile;

public interface ReferenceLookup extends ReferenceSequenceFile {
	public byte getBase(int referenceIndex, int position);
	/**
	 * Gets a list of intervals generated by splitting each contig
	 * into intervals of the given size
	 * @param intervalSize size of interval. The final interval of each sequence may be shorter than the given size.
	 * @param contigChangePenalty penalty for for changing contigs. A penalty of intervalSize will ensure that no two reference
	 * sequences are return in the same QueryInterval set, and a penalty of 0 ensures that every QueryInterval set contains the
	 * same number of bases. 
	 * @return enture reference sequence separated into chunks of the given intervalSize
	 */
	default List<QueryInterval[]> getIntervals(int intervalSize, int changePenalty) {
		if (intervalSize <= 1) throw new IllegalArgumentException("intervalSize must be at least 1");
		if (changePenalty < 0) throw new IllegalArgumentException("changePenalty cannot be negative");
		if (changePenalty > intervalSize) {
			changePenalty = intervalSize;
		}
		List<QueryInterval[]> result = new ArrayList<>();
		int currentReferenceIndex = 0;
		int startPosition = 1;
		while (currentReferenceIndex < getSequenceDictionary().getSequences().size()) {
			int currentIntervalSize = 0;
			List<QueryInterval> currentIntervals = new ArrayList<>();
			// build the current interval set
			while (currentIntervalSize < intervalSize && currentReferenceIndex < getSequenceDictionary().getSequences().size()) {
				int currentReferenceSize = getSequenceDictionary().getSequence(currentReferenceIndex).getSequenceLength();
				int remainingIntervalSize = intervalSize - currentIntervalSize;
				int endPosition = Math.min(startPosition + remainingIntervalSize - 1, currentReferenceSize);
				currentIntervals.add(new QueryInterval(currentReferenceIndex, startPosition, endPosition));
				currentIntervalSize += endPosition - startPosition + 1;
				startPosition = endPosition + 1;
				if (startPosition > currentReferenceSize) {
					// used up all of our contig - move onto the next one
					currentReferenceIndex++;
					startPosition = 1;
					currentIntervalSize += changePenalty;
				}
			}
			result.add(currentIntervals.toArray(new QueryInterval[0]));
		}
		return result;
	}
}
