package com.towel.cfg;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ProgressiveString {
	private List<CharInterval> charsIntervals;
	private int charIntervalIndex;
	private int minChar;
	private int maxChar;
	private char[] string;

	public ProgressiveString(CharInterval... charIntervals) {
		this("", charIntervals);
	}

	public ProgressiveString(String original, CharInterval... charIntervals) {
		if (charIntervals.length == 0)
			throw new RuntimeException("CharIntervals can't be null!");
		string = original.toCharArray();
		charsIntervals = Arrays.asList(charIntervals);
		Collections.sort(charsIntervals);
		charIntervalIndex = 0;
		minChar = (int) charsIntervals.get(0).first;
		maxChar = (int) charsIntervals.get(charsIntervals.size() - 1).last;
	}

	private char[] copyChars(int start, char[] old) {
		char[] str = new char[start + old.length];
		for (int i = 0; i < old.length; i++)
			str[start + i] = old[i];
		return str;
	}

	public void increase() {
		char[] str = string.clone();
		for (int i = str.length - 1; i >= 0; i--) {
			IncreaseResult result = tryIncrease(str[i]);
			str[i] = result.newChar;
			if (result.result == IncreaseResult.INCREASED)
				break;
			if (result.result == IncreaseResult.DECREASED) {
				if (i - 1 == -1) {
					str = copyChars(1, str);
					str[0] = (char) minChar;
					break;
				}
			}
		}
		string = str.clone();
	}

	private IncreaseResult tryIncrease(char c) {
		if (((int) c) == maxChar) {
			charIntervalIndex = 0;
			return new IncreaseResult((char) minChar, IncreaseResult.DECREASED);
		} else
			return new IncreaseResult(nextChar(c), IncreaseResult.INCREASED);
	}

	private char nextChar(char c) {
		int i = (int) c;
		if (i == charsIntervals.get(charIntervalIndex).last) {
			charIntervalIndex++;
			return (char) charsIntervals.get(charIntervalIndex).first;
		}
		return (char) (((int) c) + 1);
	}

	@Override
	public String toString() {
		return new String(string);
	}

	public static void main(String[] args) {
		ProgressiveString str = new ProgressiveString(
				String.valueOf((char) 33), new CharInterval('a', 'm'), new CharInterval('n', 'z'));
//		JFrame frame = new JFrame("MutableString");
//		JLabel label = new JLabel(" ");
//		frame.add(label);
//		frame.pack();
//		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		frame.setLocationRelativeTo(null);
//		frame.setVisible(true);
		int loops = 2500000;
		for (int i = 0; i < loops; i++, str.increase(), System.out.println(str))
			;
	}

	public static class CharInterval implements Comparable<CharInterval> {
		protected int first;
		protected int last;

		public CharInterval(int first, int last) {
			this.first = first;
			this.last = last;
		}

		public boolean canIncrease(char character) {
			int i = (int) character;
			return i >= first && i <= last;
		}

		@Override
		public int compareTo(CharInterval arg0) {
			if (first < arg0.first)
				return -1;
			if (first > arg0.first)
				return 1;
			return 0;
		}
	}

	private class IncreaseResult {
		protected char newChar;
		protected int result;

		public IncreaseResult(char newC, int result) {
			newChar = newC;
			this.result = result;
		}

		protected static final int INCREASED = 0;
		protected static final int DECREASED = 1;
	}
}
