// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2000-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.dev.tool.ime.indic;

import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
import java.awt.font.TextAttribute;
import java.awt.font.TextHitInfo;
import java.awt.im.spi.InputMethodContext;
import java.text.AttributedCharacterIterator;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

class IndicInputMethodImpl {
    
    protected char[] KBD_MAP;
    
    private static final char SUBSTITUTION_BASE = '\uff00';

    // Indexed by map value - SUBSTITUTION_BASE
    protected char[][] SUBSTITUTION_TABLE;

    // Invalid character.
    private static final char INVALID_CHAR              = '\uffff';

    // Unmapped versions of some interesting characters.
    private static final char KEY_SIGN_VIRAMA           = '\u0064'; // or just 'd'??
    private static final char KEY_SIGN_NUKTA            = '\u005d';  // or just ']'??

    // Two succeeding viramas are replaced by one virama and one ZWNJ.
    // Viram followed by Nukta is replaced by one VIRAMA and one ZWJ
    private static final char ZWJ                       = '\u200d';
    private static final char ZWNJ                      = '\u200c';
    
    // Backspace
    private static final char BACKSPACE                 = '\u0008';

    // Sorted list of characters which can be followed by Nukta
    protected char[] JOIN_WITH_NUKTA;
    
    // Nukta form of the above characters
    protected char[] NUKTA_FORM;
        
    //private int log2;
    private int power;
    private int extra;

    // cached TextHitInfo. Only one type of TextHitInfo is required.
    private static final TextHitInfo ZERO_TRAILING_HIT_INFO = TextHitInfo.trailing(0);

    /**
     * Returns the index of the given character in the JOIN_WITH_NUKTA array.
     * If character is not found, -1 is returned.
     */
    private int nuktaIndex(char ch) {
        if (JOIN_WITH_NUKTA == null) {
            return -1;
        }
        
        int probe = power;
        int index = 0;

        if (JOIN_WITH_NUKTA[extra] <= ch) {
            index = extra;
        }
         
        while (probe > (1 << 0)) {
            probe >>= 1;

            if (JOIN_WITH_NUKTA[index + probe] <= ch) {
                index += probe;
            }
        }

        if (JOIN_WITH_NUKTA[index] != ch) {
            index = -1;
        }

        return index;
    }
    
    /**
     * Returns the equivalent character for hindi locale.
     * @param originalChar The original character.
     */
    private char getMappedChar(char originalChar) {
        if (originalChar <= KBD_MAP.length) {
            return KBD_MAP[originalChar];
        }
        
        return originalChar;
    }
    
    // Array used to hold the text to be sent.
    // If the last character was not committed it is stored in text[0].
    // The variable totalChars give an indication of whether the last
    // character was committed or not. If at any time ( but not within a
    // a call to dispatchEvent ) totalChars is not equal to 0 ( it can
    // only be 1 otherwise ) the last character was not committed.
    private char [] text = new char[4];

    // this is always 0 before and after call to dispatchEvent. This character assumes
    // significance only within a call to dispatchEvent.
    private int committedChars = 0;// number of committed characters

    // the total valid characters in variable text currently.
    private int totalChars = 0;//number of total characters ( committed + composed )

    private boolean lastCharWasVirama = false;
    
    private InputMethodContext context;

    //
    // Finds the high bit by binary searching
    // through the bits in n.
    //
    private static byte highBit(int n) {
        if (n <= 0) {
            return -32;
        }

        byte bit = 0;

        if (n >= 1 << 16) {
            n >>= 16;
            bit += 16;
        }

        if (n >= 1 << 8) {
            n >>= 8;
            bit += 8;
        }

        if (n >= 1 << 4) {
            n >>= 4;
            bit += 4;
        }

        if (n >= 1 << 2) {
            n >>= 2;
            bit += 2;
        }

        if (n >= 1 << 1) {
            n >>= 1;
            bit += 1;
        }

        return bit;
    }

    IndicInputMethodImpl(char[] keyboardMap, char[] joinWithNukta, char[] nuktaForm, 
                         char[][] substitutionTable) {
        KBD_MAP = keyboardMap;
        JOIN_WITH_NUKTA = joinWithNukta;
        NUKTA_FORM = nuktaForm;
        SUBSTITUTION_TABLE = substitutionTable;
        
        if (JOIN_WITH_NUKTA != null) {
            int log2 = highBit(JOIN_WITH_NUKTA.length);
            
            power = 1 << log2;
            extra = JOIN_WITH_NUKTA.length - power;
        } else {
            power = extra = 0;
        }
        
    }
    
    void setInputMethodContext(InputMethodContext context) {
        this.context = context;
    }
    
    void handleKeyTyped(KeyEvent kevent) {
        char keyChar = kevent.getKeyChar();
        char currentChar = getMappedChar(keyChar);
        
        // The Explicit and Soft Halanta case.
        if ( lastCharWasVirama ) {
            switch (keyChar) {
            case KEY_SIGN_NUKTA:
                currentChar = ZWJ;
                break;
            case KEY_SIGN_VIRAMA:
                currentChar = ZWNJ;
                break;
            default:
            }//endSwitch
        }//endif

        if (currentChar == INVALID_CHAR) {
            kevent.consume();
            return;
        }

        if (currentChar == BACKSPACE) {
            lastCharWasVirama = false;
            
            if (totalChars > 0) {
                totalChars = committedChars = 0;
            } else {
                return;
            }                            
        }
        else if (keyChar == KEY_SIGN_NUKTA) {
            int nuktaIndex = nuktaIndex(text[0]);
            
            if (nuktaIndex != -1) {
                text[0] = NUKTA_FORM[nuktaIndex];
            } else {
                // the last character was committed, commit just Nukta.
                // Note : the lastChar must have been committed if it is not one of
                // the characters which combine with nukta.
                // the state must be totalChars = committedChars = 0;
                text[totalChars++] = currentChar;
            }
            
            committedChars += 1;
        }
        else {
            int nuktaIndex = nuktaIndex(currentChar);
            
            if (nuktaIndex != -1) {
                // Commit everything but currentChar
                text[totalChars++] = currentChar;
                committedChars = totalChars-1;
            } else {
                if (currentChar >= SUBSTITUTION_BASE) {
                    char[] sub = SUBSTITUTION_TABLE[currentChar - SUBSTITUTION_BASE];
                    
                    System.arraycopy(sub, 0, text, totalChars, sub.length);
                    totalChars += sub.length;
                } else {
                    text[totalChars++] = currentChar;
                }
                
                committedChars = totalChars;
            }
        }
        
        ACIText aText = new ACIText( text, 0, totalChars, committedChars );
        int composedCharLength = totalChars - committedChars;
        TextHitInfo caret=null,visiblePosition=null;
        switch( composedCharLength ) {
            case 0:
                break;
            case 1:
                visiblePosition = caret = ZERO_TRAILING_HIT_INFO;
                break;
            default:
                // The code should not reach here. There is no case where there can be
                // more than one character pending.
        }
                        
        context.dispatchInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                         aText,
                                         committedChars,
                                         caret,
                                         visiblePosition);
                                        
        if (totalChars == 0) {
            text[0] = INVALID_CHAR;
        } else {
            text[0] = text[totalChars - 1];// make text[0] hold the last character
        }
        
        lastCharWasVirama =  keyChar == KEY_SIGN_VIRAMA && !lastCharWasVirama;
                    
        totalChars -= committedChars;
        committedChars = 0;
        // state now text[0] = last character
        // totalChars = ( last character committed )? 0 : 1;
        // committedChars = 0;

        kevent.consume();// prevent client from getting this event.
    }

    void endComposition() {
        if( totalChars != 0 ) {// if some character is not committed.
            ACIText aText = new ACIText( text, 0, totalChars, totalChars );
            context.dispatchInputMethodEvent( InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                aText, totalChars, null, null );
            totalChars = committedChars = 0;
            text[0] = INVALID_CHAR;
            lastCharWasVirama = false;
        }
    }
    
    // custom AttributedCharacterIterator -- much lightweight since currently there is no
    // attribute defined on the text being generated by the input method.
    private class ACIText implements AttributedCharacterIterator {
        private char [] text = null;
        private int committed = 0;
        private int index = 0;

        ACIText( char [] chArray, int offset, int length, int committed ) {
            this.text = new char[length];
            this.committed = committed;
            System.arraycopy( chArray, offset, text, 0, length );
        }

        // CharacterIterator methods.
        public char first() {
            return _setIndex( 0 );
        }

        public char last() {
            if( text.length == 0 ) {
                return _setIndex( text.length );
            }
            return _setIndex( text.length - 1 );
        }

        public char current() {
            if( index == text.length )
                return DONE;
            return text[index];
        }

        public char next() {
            if( index == text.length ) {
                return DONE;
            }
            return _setIndex( index + 1 );
        }

        public char previous() {
            if( index == 0 )
                return DONE;
            return _setIndex( index - 1 );
        }

        public char setIndex(int position) {
            if( position < 0 || position > text.length ) {
                throw new IllegalArgumentException();
            }
            return _setIndex( position );
        }

        public int getBeginIndex() {
            return 0;
        }

        public int getEndIndex() {
            return text.length;
        }

        public int getIndex() {
            return index;
        }

        public Object clone() {
            try {
                ACIText clone = (ACIText) super.clone();
                return clone;
            } catch (CloneNotSupportedException e) {
                throw new IllegalStateException();
            }
        }

        // AttributedCharacterIterator methods.
        public int getRunStart() {
            return index >= committed ? committed : 0;
        }

        public int getRunStart(AttributedCharacterIterator.Attribute attribute) {
            return (index >= committed &&
                attribute == TextAttribute.INPUT_METHOD_UNDERLINE) ? committed : 0;
        }

        public int getRunStart(Set attributes) {
            return (index >= committed &&
                    attributes.contains(TextAttribute.INPUT_METHOD_UNDERLINE)) ? committed : 0;
        }

        public int getRunLimit() {
            return index < committed ? committed : text.length;
        }

        public int getRunLimit(AttributedCharacterIterator.Attribute attribute) {
            return (index < committed && 
                    attribute == TextAttribute.INPUT_METHOD_UNDERLINE) ? committed : text.length;
        }

        public int getRunLimit(Set attributes) {
            return (index < committed &&
                    attributes.contains(TextAttribute.INPUT_METHOD_UNDERLINE)) ? committed : text.length;
        }

        public Map getAttributes() {
            Hashtable result = new Hashtable();
            if (index >= committed && committed < text.length) {
                result.put(TextAttribute.INPUT_METHOD_UNDERLINE, 
                           TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
            }
            return result;
        }

        public Object getAttribute(AttributedCharacterIterator.Attribute attribute) {
            if (index >= committed && 
                committed < text.length &&
                attribute == TextAttribute.INPUT_METHOD_UNDERLINE) {

                return TextAttribute.UNDERLINE_LOW_ONE_PIXEL;
            }
            return null;
        }

        public Set getAllAttributeKeys() {
            HashSet result = new HashSet();
            if (committed < text.length) {
                result.add(TextAttribute.INPUT_METHOD_UNDERLINE);
            }
            return result;
        }

        // private methods

        /**
         * This is always called with valid i ( 0 < i <= text.length )
         */
        private char _setIndex( int i ) {
            index = i;
            if( i == text.length ) {
                return DONE;
            }
            return text[i];
        }

    }
}
