/*
 *******************************************************************************
 * Copyright (C) 1996-2009, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.text;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.ibm.icu.impl.NormalizerImpl;
import com.ibm.icu.impl.USerializedSet;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;

/**
 * This class allows one to iterate through all the strings that are canonically equivalent to a given
 * string. For example, here are some sample results:
 * Results for: {A WITH RING ABOVE}{d}{DOT ABOVE}{CEDILLA}
 * <pre>
 1: {A}{RING ABOVE}{d}{DOT ABOVE}{CEDILLA}
 2: {A}{RING ABOVE}{d}{CEDILLA}{DOT ABOVE}
 3: {A}{RING ABOVE}{d WITH DOT ABOVE}{CEDILLA}
 4: {A}{RING ABOVE}{d WITH CEDILLA}{DOT ABOVE}
 5: {A WITH RING ABOVE}{d}{DOT ABOVE}{CEDILLA}
 6: {A WITH RING ABOVE}{d}{CEDILLA}{DOT ABOVE}
 7: {A WITH RING ABOVE}{d WITH DOT ABOVE}{CEDILLA}
 8: {A WITH RING ABOVE}{d WITH CEDILLA}{DOT ABOVE}
 9: {ANGSTROM SIGN}{d}{DOT ABOVE}{CEDILLA}
10: {ANGSTROM SIGN}{d}{CEDILLA}{DOT ABOVE}
11: {ANGSTROM SIGN}{d WITH DOT ABOVE}{CEDILLA}
12: {ANGSTROM SIGN}{d WITH CEDILLA}{DOT ABOVE}
 *</pre>
 *<br>Note: the code is intended for use with small strings, and is not suitable for larger ones,
 * since it has not been optimized for that situation.
 * @author M. Davis
 * @stable ICU 2.4
 */

public final class CanonicalIterator {
    /**
     * Construct a CanonicalIterator object
     * @param source string to get results for
     * @stable ICU 2.4
     */
    public CanonicalIterator(String source) {
        setSource(source);
    }

    /**
     * Gets the NFD form of the current source we are iterating over.
     * @return gets the source: NOTE: it is the NFD form of the source originally passed in
     * @stable ICU 2.4
     */
    public String getSource() {
      return source;
    }

    /**
     * Resets the iterator so that one can start again from the beginning.
     * @stable ICU 2.4
     */
    public void reset() {
        done = false;
        for (int i = 0; i < current.length; ++i) {
            current[i] = 0;
        }
    }

    /**
     * Get the next canonically equivalent string.
     * <br><b>Warning: The strings are not guaranteed to be in any particular order.</b>
     * @return the next string that is canonically equivalent. The value null is returned when
     * the iteration is done.
     * @stable ICU 2.4
     */
    public String next() {
        if (done) return null;

        // construct return value

        buffer.setLength(0); // delete old contents
        for (int i = 0; i < pieces.length; ++i) {
            buffer.append(pieces[i][current[i]]);
        }
        String result = buffer.toString();

        // find next value for next time

        for (int i = current.length - 1; ; --i) {
            if (i < 0) {
                done = true;
                break;
            }
            current[i]++;
            if (current[i] < pieces[i].length) break; // got sequence
            current[i] = 0;
        }
        return result;
    }

    /**
     * Set a new source for this iterator. Allows object reuse.
     * @param newSource the source string to iterate against. This allows the same iterator to be used
     * while changing the source string, saving object creation.
     * @stable ICU 2.4
     */
    public void setSource(String newSource) {
        source = Normalizer.normalize(newSource, Normalizer.NFD);
        done = false;

        // catch degenerate case
        if (newSource.length() == 0) {
            pieces = new String[1][];
            current = new int[1];
            pieces[0] = new String[]{""};
            return;
        }

        // find the segments
        List<String> segmentList = new ArrayList<String>();
        int cp;
        int start = 0;

        // i should be the end of the first code point
        // break up the string into segements

        int i = UTF16.findOffsetFromCodePoint(source, 1);

        for (; i < source.length(); i += UTF16.getCharCount(cp)) {
            cp = UTF16.charAt(source, i);
            if (NormalizerImpl.isCanonSafeStart(cp)) {
                segmentList.add(source.substring(start, i)); // add up to i
                start = i;
            }
        }
        segmentList.add(source.substring(start, i)); // add last one

        // allocate the arrays, and find the strings that are CE to each segment
        pieces = new String[segmentList.size()][];
        current = new int[segmentList.size()];
        for (i = 0; i < pieces.length; ++i) {
            if (PROGRESS) System.out.println("SEGMENT");
            pieces[i] = getEquivalents(segmentList.get(i));
        }
    }

    /**
     * Simple implementation of permutation.
     * <br><b>Warning: The strings are not guaranteed to be in any particular order.</b>
     * @param source the string to find permutations for
     * @param skipZeros set to true to skip characters with canonical combining class zero
     * @param output the set to add the results to
     * @internal
     * @deprecated This API is ICU internal only.
     */
    public static void permute(String source, boolean skipZeros, Set<String> output) {
        // TODO: optimize
        //if (PROGRESS) System.out.println("Permute: " + source);

        // optimization:
        // if zero or one character, just return a set with it
        // we check for length < 2 to keep from counting code points all the time
        if (source.length() <= 2 && UTF16.countCodePoint(source) <= 1) {
            output.add(source);
            return;
        }

        // otherwise iterate through the string, and recursively permute all the other characters
        Set<String> subpermute = new HashSet<String>();
        int cp;
        for (int i = 0; i < source.length(); i += UTF16.getCharCount(cp)) {
            cp = UTF16.charAt(source, i);

            // optimization:
            // if the character is canonical combining class zero,
            // don't permute it
            if (skipZeros && i != 0 && UCharacter.getCombiningClass(cp) == 0) {
                //System.out.println("Skipping " + Utility.hex(UTF16.valueOf(source, i)));
                continue;
            }

            // see what the permutations of the characters before and after this one are
            subpermute.clear();
            permute(source.substring(0,i)
                + source.substring(i + UTF16.getCharCount(cp)), skipZeros, subpermute);

            // prefix this character to all of them
            String chStr = UTF16.valueOf(source, i);
            for (String s : subpermute) {
                String piece = chStr + s;
                //if (PROGRESS) System.out.println("  Piece: " + piece);
                output.add(piece);
            }
        }
    }

    // FOR TESTING

    /*
     *@return the set of "safe starts", characters that are class zero AND are never non-initial in a decomposition.
     *@internal
     *
    public static UnicodeSet getSafeStart() {
        return (UnicodeSet) SAFE_START.clone();
    }
    */
    /*
     *@return the set of characters whose decompositions start with the given character
     *@internal
     *
    public static UnicodeSet getStarts(int cp) {
        UnicodeSet result = AT_START.get(cp);
        if (result == null) result = EMPTY;
        return (UnicodeSet) result.clone();
    }
    */

    // ===================== PRIVATES ==============================

    // debug
    private static boolean PROGRESS = false; // debug progress
    //private static Transliterator NAME = PROGRESS ? Transliterator.getInstance("name") : null;
    private static boolean SKIP_ZEROS = true;

    // fields
    private String source;
    private boolean done;
    private String[][] pieces;
    private int[] current;
    // Note: C will need two more fields, since arrays there don't have lengths
    // int pieces_length;
    // int[] pieces_lengths;

    // transient fields
    private transient StringBuffer buffer = new StringBuffer();


    // we have a segment, in NFD. Find all the strings that are canonically equivalent to it.
    private String[] getEquivalents(String segment) {
        Set<String> result = new HashSet<String>();
        Set<String> basic = getEquivalents2(segment);
        Set<String> permutations = new HashSet<String>();

        // now get all the permutations
        // add only the ones that are canonically equivalent
        // TODO: optimize by not permuting any class zero.
        Iterator<String> it = basic.iterator();
        while (it.hasNext()) {
            String item = it.next();
            permutations.clear();
            permute(item, SKIP_ZEROS, permutations);
            Iterator<String> it2 = permutations.iterator();
            while (it2.hasNext()) {
                String possible = it2.next();

/*
                String attempt = Normalizer.normalize(possible, Normalizer.DECOMP, 0);
                if (attempt.equals(segment)) {
*/
                if (Normalizer.compare(possible, segment,0)==0) {

                    if (PROGRESS) System.out.println("Adding Permutation: " + Utility.hex(possible));
                    result.add(possible);

                } else {
                    if (PROGRESS) System.out.println("-Skipping Permutation: " + Utility.hex(possible));
                }
            }
        }

        // convert into a String[] to clean up storage
        String[] finalResult = new String[result.size()];
        result.toArray(finalResult);
        return finalResult;
    }


    private Set<String> getEquivalents2(String segment) {

        Set<String> result = new HashSet<String>();

        if (PROGRESS) System.out.println("Adding: " + Utility.hex(segment));

        result.add(segment);
        StringBuffer workingBuffer = new StringBuffer();

        // cycle through all the characters
        int cp=0;
        int[] range = new int[2];
        for (int i = 0; i < segment.length(); i += UTF16.getCharCount(cp)) {

            // see if any character is at the start of some decomposition
            cp = UTF16.charAt(segment, i);
            USerializedSet starts = new USerializedSet();

            if (!NormalizerImpl.getCanonStartSet(cp, starts)) {
              continue;
            }
            int j=0;
            // if so, see which decompositions match
            int rangeCount = starts.countRanges();
            for(j = 0; j < rangeCount; ++j) {
                starts.getRange(j, range);
                int end=range[1];
                for (int cp2 = range[0]; cp2 <= end; ++cp2) {
                    Set<String> remainder = extract(cp2, segment, i, workingBuffer);
                    if (remainder == null) {
                        continue;
                    }

                    // there were some matches, so add all the possibilities to the set.
                    String prefix= segment.substring(0,i);
                    prefix += UTF16.valueOf(cp2);
                    //int el = -1;
                    for (String item : remainder) {
                        String toAdd = new String(prefix);
                        toAdd += item;
                        result.add(toAdd);
                        //if (PROGRESS) printf("Adding: %s\n", UToS(Tr(*toAdd)));
                    }
                }
            }
        }
        return result;
        /*
        Set result = new HashSet();
        if (PROGRESS) System.out.println("Adding: " + NAME.transliterate(segment));
        result.add(segment);
        StringBuffer workingBuffer = new StringBuffer();

        // cycle through all the characters
        int cp;

        for (int i = 0; i < segment.length(); i += UTF16.getCharCount(cp)) {
            // see if any character is at the start of some decomposition
            cp = UTF16.charAt(segment, i);
            NormalizerImpl.getCanonStartSet(c,fillSet)
            UnicodeSet starts = AT_START.get(cp);
            if (starts == null) continue;
            UnicodeSetIterator usi = new UnicodeSetIterator(starts);
            // if so, see which decompositions match
            while (usi.next()) {
                int cp2 = usi.codepoint;
                // we know that there are no strings in it
                // so we don't have to check CharacterIterator.IS_STRING
                Set remainder = extract(cp2, segment, i, workingBuffer);
                if (remainder == null) continue;

                // there were some matches, so add all the possibilities to the set.
                String prefix = segment.substring(0, i) + UTF16.valueOf(cp2);
                Iterator it = remainder.iterator();
                while (it.hasNext()) {
                    String item = (String) it.next();
                    if (PROGRESS) System.out.println("Adding: " + NAME.transliterate(prefix + item));
                    result.add(prefix + item);
                }
            }
        }
        return result;
        */
    }

    /**
     * See if the decomposition of cp2 is at segment starting at segmentPos
     * (with canonical rearrangment!)
     * If so, take the remainder, and return the equivalents
     */
    private Set<String> extract(int comp, String segment, int segmentPos, StringBuffer buf) {
        if (PROGRESS) System.out.println(" extract: " + Utility.hex(UTF16.valueOf(comp))
            + ", " + Utility.hex(segment.substring(segmentPos)));

        //String decomp = Normalizer.normalize(UTF16.valueOf(comp), Normalizer.DECOMP, 0);
        String decomp = Normalizer.normalize(comp, Normalizer.NFD);

        // See if it matches the start of segment (at segmentPos)
        boolean ok = false;
        int cp;
        int decompPos = 0;
        int decompCp = UTF16.charAt(decomp,0);
        decompPos += UTF16.getCharCount(decompCp); // adjust position to skip first char
        //int decompClass = getClass(decompCp);
        buf.setLength(0); // initialize working buffer, shared among callees

        for (int i = segmentPos; i < segment.length(); i += UTF16.getCharCount(cp)) {
            cp = UTF16.charAt(segment, i);
            if (cp == decompCp) { // if equal, eat another cp from decomp
                if (PROGRESS) System.out.println("  matches: " + Utility.hex(UTF16.valueOf(cp)));
                if (decompPos == decomp.length()) { // done, have all decomp characters!
                    buf.append(segment.substring(i + UTF16.getCharCount(cp))); // add remaining segment chars
                    ok = true;
                    break;
                }
                decompCp = UTF16.charAt(decomp, decompPos);
                decompPos += UTF16.getCharCount(decompCp);
                //decompClass = getClass(decompCp);
            } else {
                if (PROGRESS) System.out.println("  buffer: " + Utility.hex(UTF16.valueOf(cp)));
                // brute force approach
                UTF16.append(buf, cp);
                /* TODO: optimize
                // since we know that the classes are monotonically increasing, after zero
                // e.g. 0 5 7 9 0 3
                // we can do an optimization
                // there are only a few cases that work: zero, less, same, greater
                // if both classes are the same, we fail
                // if the decomp class < the segment class, we fail

                segClass = getClass(cp);
                if (decompClass <= segClass) return null;
                */
            }
        }
        if (!ok) return null; // we failed, characters left over
        if (PROGRESS) System.out.println("Matches");
        if (buf.length() == 0) return SET_WITH_NULL_STRING; // succeed, but no remainder
        String remainder = buf.toString();

        // brute force approach
        // to check to make sure result is canonically equivalent
        /*
        String trial = Normalizer.normalize(UTF16.valueOf(comp) + remainder, Normalizer.DECOMP, 0);
        if (!segment.regionMatches(segmentPos, trial, 0, segment.length() - segmentPos)) return null;
        */

        if (0!=Normalizer.compare(UTF16.valueOf(comp) + remainder, segment.substring(segmentPos), 0)) return null;

        // get the remaining combinations
        return getEquivalents2(remainder);
    }

    /*
    // TODO: fix once we have a codepoint interface to get the canonical combining class
    // TODO: Need public access to canonical combining class in UCharacter!
    private static int getClass(int cp) {
        return Normalizer.getClass((char)cp);
    }
    */

   // ================= BUILDER =========================
    // TODO: Flatten this data so it doesn't have to be reconstructed each time!

    //private static final UnicodeSet EMPTY = new UnicodeSet(); // constant, don't change
    private static final Set<String> SET_WITH_NULL_STRING = new HashSet<String>(); // constant, don't change
    static {
        SET_WITH_NULL_STRING.add("");
    }

  //  private static UnicodeSet SAFE_START = new UnicodeSet();
  //  private static CharMap AT_START = new CharMap();

        // TODO: WARNING, NORMALIZER doesn't have supplementaries yet !!;
        // Change FFFF to 10FFFF in C, and in Java when normalizer is upgraded.
  //  private static int LAST_UNICODE = 0x10FFFF;
    /*
    static {
        buildData();
    }
    */
    /*
    private static void buildData() {

        if (PROGRESS) System.out.println("Getting Safe Start");
        for (int cp = 0; cp <= LAST_UNICODE; ++cp) {
            if (PROGRESS & (cp & 0x7FF) == 0) System.out.print('.');
            int cc = UCharacter.getCombiningClass(cp);
            if (cc == 0) SAFE_START.add(cp);
            // will fix to be really safe below
        }
        if (PROGRESS) System.out.println();

        if (PROGRESS) System.out.println("Getting Containment");
        for (int cp = 0; cp <= LAST_UNICODE; ++cp) {
            if (PROGRESS & (cp & 0x7FF) == 0) System.out.print('.');

            if (Normalizer.isNormalized(cp, Normalizer.NFD)) continue;

            //String istr = UTF16.valueOf(cp);
            String decomp = Normalizer.normalize(cp, Normalizer.NFD);
            //if (decomp.equals(istr)) continue;

            // add each character in the decomposition to canBeIn

            int component;
            for (int i = 0; i < decomp.length(); i += UTF16.getCharCount(component)) {
                component = UTF16.charAt(decomp, i);
                if (i == 0) {
                    AT_START.add(component, cp);
                } else if (UCharacter.getCombiningClass(component) == 0) {
                    SAFE_START.remove(component);
                }
            }
        }
        if (PROGRESS) System.out.println();
    }
        // the following is just for a map from characters to a set of characters

    private static class CharMap {
        Map storage = new HashMap();
        MutableInt probe = new MutableInt();
        boolean converted = false;

        public void add(int cp, int whatItIsIn) {
            UnicodeSet result = (UnicodeSet) storage.get(probe.set(cp));
            if (result == null) {
                result = new UnicodeSet();
                storage.put(probe, result);
            }
            result.add(whatItIsIn);
        }

        public UnicodeSet get(int cp) {
            return (UnicodeSet) storage.get(probe.set(cp));
        }
    }

    private static class MutableInt {
        public int contents;
        public int hashCode() { return contents; }
        public boolean equals(Object other) {
            return ((MutableInt)other).contents == contents;
        }
        // allows chaining
        public MutableInt set(int contents) {
            this.contents = contents;
            return this;
        }
    }
    */

}
