/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 *
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.core.lang.escape;

import java.io.IOException;
import java.util.HashMap;

/**
 * Translates a value using a lookup table.
 * 
 */
public class LookupTranslator extends CharSequenceTranslator {

	private final HashMap<String, CharSequence> lookupMap;
	private final int shortest;
	private final int longest;

	/**
	 * Define the lookup table to be used in translation Note that, as of Lang 3.1, the key to the
	 * lookup table is converted to a java.lang.String, while the value remains as a
	 * java.lang.CharSequence. This is because we need the key to support hashCode and
	 * equals(Object), allowing it to be the key for a HashMap. See LANG-882.
	 * 
	 * @param lookup CharSequence[][] table of size [*][2]
	 */
	public LookupTranslator(final CharSequence[]... lookup) {
		lookupMap = new HashMap<String, CharSequence>();
		int _shortest = Integer.MAX_VALUE;
		int _longest = 0;
		if (lookup != null) {
			for (final CharSequence[] seq : lookup) {
				this.lookupMap.put(seq[0].toString(), seq[1]);
				final int sz = seq[0].length();
				if (sz < _shortest) {
					_shortest = sz;
				}
				if (sz > _longest) {
					_longest = sz;
				}
			}
		}
		shortest = _shortest;
		longest = _longest;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int translate(final CharSequence input, final int index, final Appendable out) throws IOException {
		int max = longest;
		if (index + longest > input.length()) {
			max = input.length() - index;
		}
		// descend so as to get a greedy algorithm
		for (int i = max; i >= shortest; i--) {
			final CharSequence subSeq = input.subSequence(index, index + i);
			final CharSequence result = lookupMap.get(subSeq.toString());
			if (result != null) {
				out.append(result);
				return i;
			}
		}
		return 0;
	}
}
