/**
 *******************************************************************************
 * Copyright (C) 2001-2002, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/demo/translit/AnyTransliterator.java,v $
 * $Date: 2002/08/13 21:50:44 $
 * $Revision: 1.3 $
 *
 *******************************************************************************
 */
package com.ibm.icu.dev.demo.translit;
import com.ibm.icu.dev.demo.impl.*;
import com.ibm.icu.lang.*;
import com.ibm.icu.text.*;
import java.util.*;

public class AnyTransliterator extends Transliterator {
	
	static final boolean DEBUG = false;
	private String targetName;
	private RunIterator it;
	private Position run;
	
	
	public AnyTransliterator(String targetName, UnicodeFilter filter, RunIterator it){
		super("Any-" + targetName, filter);
		this.targetName = targetName;
		this.it = it;
		run = new Position();
	}
	
	public AnyTransliterator(String targetName, UnicodeFilter filter){
		this(targetName, filter, new ScriptRunIterator());
	}
	
	static private Transliterator hex = Transliterator.getInstance("[^\\u0020-\\u007E] hex");
	
    protected void handleTransliterate(Replaceable text,
                                       Position offsets, boolean isIncremental) {
    	if (DEBUG) {
    		System.out.println("- handleTransliterate " + hex.transliterate(text.toString())
    			+ ", " + toString(offsets));
    	}
		it.reset(text, offsets);
		
        while (it.next(run)) {
			if (targetName.equalsIgnoreCase(it.getName())) {
				if (DEBUG) System.out.println("Skipping identical: " + targetName);
				run.start = run.limit; // show we processed
				continue; // skip if same
			}
        	
			Transliterator t;
			String id = it.getName() + '-' + targetName;
			try {
        		t = Transliterator.getInstance(id);
        	} catch (IllegalArgumentException ex) {
        		if (DEBUG) System.out.println("Couldn't find: " + id + ", Trying Latin as Pivot");
				id = it.getName() + "-Latin; Latin-" + targetName;
				try {
        			t = Transliterator.getInstance(id);
        		} catch (IllegalArgumentException ex2) {
        			if (DEBUG) System.out.println("Couldn't find: " + id);
        			continue;
        		}
        	}
        	// TODO catch error later!!
        		
        	if (DEBUG) {
        		System.out.println(t.getID());
        		System.out.println("input: " + hex.transliterate(text.toString())
        		 + ", " + toString(run));
        	}
        	
        	if (isIncremental && it.atEnd()) {
        		t.transliterate(text, run);
        	} else {
        		t.finishTransliteration(text, run);
        	}
        	// adjust the offsets in line with the changes
        	it.adjust(run.limit);
        	
        	if (DEBUG) {
        		System.out.println("output: " + hex.transliterate(text.toString())
        		 + ", " + toString(run));
        	}
        }

		// show how far we got!
		it.getExpanse(offsets);
		if (run.start == run.limit) offsets.start = offsets.limit;
		else offsets.start = run.start;
    	if (DEBUG) {
    		System.out.println("+ handleTransliterate: " + ", " + toString(offsets));
        	System.out.println();
    	}
    }
    
    // should be method on Position
    public static String toString(Position offsets) {
    	return "[cs: " + offsets.contextStart
    			+ ", s: " + offsets.start
    			+ ", l: " + offsets.limit
    			+ ", cl: " + offsets.contextLimit
    			+ "]";
    }
    
    public interface RunIterator {
    	public void reset(Replaceable text, Position expanse);
    	public void getExpanse(Position run);
    	public void reset();
    	public boolean next(Position run);
    	public void getCurrent(Position run);
    	public String getName();
    	public void adjust(int newCurrentLimit);
    	public boolean atEnd();
    }
    
    /**
     * Returns a series of ranges corresponding to scripts. They will be of the form:
     * ccccSScSSccccTTcTcccc	- where c is common, S is the first script and T is the second
     *|            |			- first run
     *         |            |	- second run
     * That is, the runs will overlap. The reason for this is so that a transliterator can
     * consider common characters both before and after the scripts.
     * The only time that contextStart != start is for the first run 
     *	(the context is the start context of the entire expanse)
     * The only time that contextLimit != limit is for the last run 
     *	(the context is the end context of the entire expanse)
     */
    public static class ScriptRunIterator implements RunIterator {
    	private Replaceable text;
    	private Position expanse = new Position();
    	private Position current = new Position();
    	private int script;
    	private boolean done = true;
    	

    	public void reset(Replaceable text, Position expanse) {
    		set(this.expanse, expanse);
    		this.text = text;
    		reset();
    	}
    		
    	public void reset() {
    		done = false;
    		this.expanse = expanse;
    		script = UScript.INVALID_CODE;
    		// set up first range to be empty, at beginning
    		current.contextStart = expanse.contextStart;
    		current.start = current.limit = current.contextLimit = expanse.start;    		
    	}
    		
    	public boolean next(Position run) {
    		if (done) return false;
    		if (DEBUG) {
    			System.out.println("+cs: " + current.contextStart
    				+ ", s: " + current.start
    				+ ", l: " + current.limit
    				+ ", cl: " + current.contextLimit);
    		}
    		// reset start context run to the last end
    		current.start = current.limit;
    		
    		// Phase 1. Backup the START value through COMMON until we get to expanse.start or a real script.
    		int i, cp;
    		int limit = expanse.start;
    		for (i = current.start; i > limit; i -= UTF16.getCharCount(cp)) {
    			cp = text.char32At(i);
    			int script = UScript.getScript(cp);
    			if (script != UScript.COMMON && script != UScript.INHERITED) break;
    		}
    		current.start = i;
    		current.contextStart = (i == limit) ? expanse.contextStart : i; // extend at start
    		
    		// PHASE 2. Move up the LIMIT value through COMMON or single script until we get to expanse.limit
    		int lastScript = UScript.COMMON;
    		int veryLastScript = UScript.COMMON;
    		limit = expanse.limit; 
    		for (i = current.limit; i < limit; i += UTF16.getCharCount(cp)) {
    			cp = text.char32At(i);
    			int script = UScript.getScript(cp);
    			if (script == UScript.INHERITED) script = UScript.COMMON;
    			if (script != UScript.COMMON) {
    				// if we find a real script:
    				//   if we already had a script, bail
    				//   otherwise set our script
    				if (lastScript == UScript.COMMON) lastScript = script;
    				else if (lastScript != script) break;
    			}
    		}
    		current.limit = i;
    		current.contextLimit = (i == limit) ? expanse.contextLimit : i; // extend at end
    		done = (i == limit);
    		script = lastScript;
    		
    		if (DEBUG) {
    			System.out.println("-cs: " + current.contextStart
    				+ ", s: " + current.start
    				+ ", l: " + current.limit
    				+ ", cl: " + current.contextLimit);
    		}
    		
    		set(run, current);
    		return true;
    	}
    	
    	// SHOULD BE METHOD ON POSITION
    	public static void set(Position run, Position current) {
    		run.contextStart = current.contextStart;
    		run.start = current.start;
    		run.limit = current.limit;
    		run.contextLimit = current.contextLimit;
    	}
    	
    	public boolean atEnd() {
    		return current.limit == expanse.limit;
    	}
    	
    	public void getCurrent(Position run) {
    		set(run, current);
    	}
    	
    	public void getExpanse(Position run) {
    		set(run, expanse);
    	}
    	
    	public String getName() {
    		return UScript.getName(script);
    	}
    	
    	public void adjust(int newCurrentLimit) {
    		if (expanse == null) {
    			throw new IllegalArgumentException("Must reset() before calling");
    		}
    		int delta = newCurrentLimit - current.limit;
    		current.limit += delta;
    		current.contextLimit += delta;
    		expanse.limit += delta;
    		expanse.contextLimit += delta;
    	}
    	
    	// register Any-Script for every script.
    	
    	private static Set scriptList = new HashSet();
    	
    	public static void registerAnyToScript() {
    		synchronized (scriptList) {
        		Enumeration sources = Transliterator.getAvailableSources();
        		while(sources.hasMoreElements()) {
            		String source = (String) sources.nextElement();
            		if (source.equals("Any")) continue; // to keep from looping
	            	
            		Enumeration targets = Transliterator.getAvailableTargets(source);
            		while(targets.hasMoreElements()) {
                		String target = (String) targets.nextElement();
            			if (UScript.getCode(target) == null) continue; // SKIP unless we have a script (or locale)
            			if (scriptList.contains(target)) continue; // already encountered
            			scriptList.add(target); // otherwise add for later testing
	            		
                		Set variantSet = add(new TreeSet(), Transliterator.getAvailableVariants(source, target));
                		if (variantSet.size() < 2) {
    						AnyTransliterator at = new AnyTransliterator(target, null);
    						DummyFactory.add(at.getID(), at);
                		} else {
                    		Iterator variants = variantSet.iterator();
                    		while(variants.hasNext()) {
                        		String variant = (String) variants.next();
    							AnyTransliterator at = new AnyTransliterator(
    								(variant.length() > 0) ? target + "/" + variant : target, null);
    							DummyFactory.add(at.getID(), at);
                    		}
                		}
            		}
        		}
        	}
    	}
    	
    	static class DummyFactory implements Transliterator.Factory {
        	static DummyFactory singleton = new DummyFactory();
        	static HashMap m = new HashMap();

        	// Since Transliterators are immutable, we don't have to clone on set & get
        	static void add(String ID, Transliterator t) {
            	m.put(ID, t);
            	System.out.println("Registering: " + ID + ", " + t.toRules(true));
            	Transliterator.registerFactory(ID, singleton);
        	}
        	public Transliterator getInstance(String ID) {
            	return (Transliterator) m.get(ID);
        	}
    	}
    	
    	// Nice little Utility for converting Enumeration to collection
    	static Set add(Set s, Enumeration enum) {
        	while(enum.hasMoreElements()) {
            	s.add(enum.nextElement());
        	}
        	return s;
    	}
    	
    	
    }
}
