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

import java.awt.event.KeyEvent;

import com.ibm.icu.dev.demo.impl.DumbTextComponent;
import com.ibm.icu.text.ReplaceableString;
import com.ibm.icu.text.Transliterator;

/**
 * A subclass of {@link DumbTextComponent} that passes key events through
 * a {@link com.ibm.icu.text.Transliterator}.
 *
 * @author Alan Liu
 */
public class TransliteratingTextComponent extends DumbTextComponent {

    /**
     * For serialization
     */
    private static final long serialVersionUID = -8672128213174154047L;

    private static boolean DEBUG = false;

    private Transliterator translit = null;
    
    // NOTE: DISABLE THE START AND CURSOR UNTIL WE CAN GET IT TO WORK AT ALL

    // Index into getText() where the start of transliteration is.
    // As we commit text during transliteration, we advance
    // this.
    //private int start = 0;

    // Index into getText() where the cursor is; cursor >= start
    //private int cursor = 0;

//    private static final String COPYRIGHT =
//        "\u00A9 IBM Corporation 1999. All rights reserved.";

    /**
     * Constructor.
     */
    public TransliteratingTextComponent() {
        super();
        /*
        addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // We get an ActionEvent only when the selection changes
                resetTransliterationStart();
            }
        });
        */
    }

    /**
     * {@link DumbTextComponent} API.  Framework method that is called
     * when a <code>KeyEvent</code> is received.  This implementation
     * runs the new character through the current
     * <code>Transliterator</code>, if one is set, and inserts the
     * transliterated text into the buffer.
     */
    protected void handleKeyTyped(KeyEvent e) {
        char ch = e.getKeyChar();
        
        if (translit == null) {
            setKeyStart(-1);
            super.handleKeyTyped(e);
            return;
        }

        transliterate(ch, false);
    }
    
    public void flush() {
        if (translit != null) transliterate('\uFFFF', true);
    }
    
    
    protected void transliterate(char ch, boolean flush) {

        // ------------------------------------------------------------
        // The following case motivates the two lines that recompute
        // start and cursor below.

        //      "     "   
        // a b c q r|s t u m m
        // 0 1 2 3 4 5 6 7 8 9
        //       0 1 2

        // start 3, cursor 5, sel 6 -> { 0, 3, 2 }
        // : new int[] { 0, sel - start, cursor - start };
        
        // sz>99|9

        //      "     {   "
        // a b c q r 9 9|9 t u m m
        // 0 1 2 3 4 5 6 7 8 9 a b
        //       0 1 2 3 4

        // { 3, 5, 4 } -> start 6, cursor 7, sel 8
        // : start += index[0];
        // : cursor = start + index[2] - index[0];
        // ------------------------------------------------------------

        // Need to save start because calls to replaceRange will update
        // start and cursor.
        //int saveStart = start;

        int end = flush ? getSelectionEnd() : getSelectionStart();
        String sourceText = getText().substring(0,end);
        ReplaceableString buf = new ReplaceableString(sourceText);
        /*buf.replace(0, 1, getText().substring(start,
                                              getSelectionStart()));*/

        Transliterator.Position index = new Transliterator.Position();
        index.contextLimit = buf.length();
        index.contextStart = 0;
        index.start = getKeyStart();
        if (index.start == -1) index.start = getSelectionStart();
        index.limit = buf.length();

      //  StringBuffer log = null;
        if (DEBUG) {
            System.out.println("Transliterator: " + translit.getID());
            System.out.println("From:\t" + '"' + buf.toString() + '"'
                + "; {cs: " + index.contextStart
                + ", s: " + index.start
                + ", l: " + index.limit
                + ", cl: " + index.contextLimit 
                + "}" + "; '" + ch + "'"
                + " " + getKeyStart()
            );
        }

        if (flush) {
            translit.finishTransliteration(buf, index);
        } else {
            translit.transliterate(buf, index, ch);
        }
        
        if (DEBUG) {
            System.out.println("To:\t" + '"' + buf.toString() + '"'
                + "; {cs: " + index.contextStart
                + ", s: " + index.start
                + ", l: " + index.limit
                + ", cl: " + index.contextLimit 
                + "}"
                );
            System.out.println();
        }
        /*
        buf.replace(buf.length(), buf.length(), String.valueOf(ch));
        translit.transliterate(buf);
        */
        
        String result = buf.toString();
        //if (result.equals(sourceText + ch)) return;
        
        replaceRange(result, 0, getSelectionEnd());
        setKeyStart(index.start);
        
        // At this point start has been changed by the callback to
        // resetTransliteratorStart() via replaceRange() -- so use our
        // local copy, saveStart.

        // The START index is zero-based.  On entry to transliterate(),
        // it was zero.  We can therefore just add it to our original
        // getText()-based index value of start (in saveStart) to get
        // the new getText()-based start.
//        start = saveStart + index.contextStart;

        // Make the cursor getText()-based.  The CURSOR index is zero-based.
//        cursor = start + index.start - index.contextStart;

/*
        if (DEBUG) {
            String out = buf.toString();
            log.append(out.substring(0, index.contextStart)).
                append('{').
                append(out.substring(index.contextStart, index.start)).
                append('|').
                append(out.substring(index.start)).
                append('"');
            log.append(", {" + index.contextStart + ", " + index.contextLimit + ", " + index.start + "}, ");
//            log.append("start " + start + ", cursor " + cursor);
            log.append(", sel " + getSelectionStart());
            System.out.println(escape(log.toString()));
        }
        */
    }
    
    /**
     * Set the {@link com.ibm.icu.text.Transliterator} and direction to
     * use to process incoming <code>KeyEvent</code>s.
     * @param t the {@link com.ibm.icu.text.Transliterator} to use
     */
    public void setTransliterator(Transliterator t) {
        /*
        if (translit != t) { // [sic] pointer compare ok; singletons
            resetTransliterationStart();
        }
        */
        translit = t;
    }

    public Transliterator getTransliterator() {
        return translit;
    }

    /**
     * Reset the start point at which transliteration begins.  This
     * needs to be done when the user moves the cursor or when the
     * current {@link com.ibm.icu.text.Transliterator} is changed. 
     */
     /*
    private void resetTransliterationStart() {
        start = getSelectionStart();
        cursor = start;
    }
    */

    /**
     * Escape non-ASCII characters as Unicode.
     * JUST FOR DEBUGGING OUTPUT.
     */
    public static final String escape(String s) {
        StringBuffer buf = new StringBuffer();
        for (int i=0; i<s.length(); ++i) {
            char c = s.charAt(i);
            if (c >= ' ' && c <= 0x007F) {
                if (c == '\\') {
                    buf.append("\\\\"); // That is, "\\"
                } else {
                    buf.append(c);
                }
            } else {
                buf.append("\\u");
                if (c < 0x1000) {
                    buf.append('0');
                    if (c < 0x100) {
                        buf.append('0');
                        if (c < 0x10) {
                            buf.append('0');
                        }
                    }
                }
                buf.append(Integer.toHexString(c));
            }
        }
        return buf.toString();
    }
}
