/*
 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.awt.event;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.font.TextHitInfo;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import javax.tools.annotation.GenerateNativeHeader;

/**
 * Input method events contain information about text that is being
 * composed using an input method. Whenever the text changes, the
 * input method sends an event. If the text component that's currently
 * using the input method is an active client, the event is dispatched
 * to that component. Otherwise, it is dispatched to a separate
 * composition window.
 *
 * <p>
 * The text included with the input method event consists of two parts:
 * committed text and composed text. Either part may be empty. The two
 * parts together replace any uncommitted composed text sent in previous events,
 * or the currently selected committed text.
 * Committed text should be integrated into the text component's persistent
 * data, it will not be sent again. Composed text may be sent repeatedly,
 * with changes to reflect the user's editing operations. Committed text
 * always precedes composed text.
 *
 * @author JavaSoft Asia/Pacific
 * @since 1.2
 */
/* No native methods here, but the constants are needed in the supporting JNI code */
@GenerateNativeHeader
public class InputMethodEvent extends AWTEvent {

    /**
     * Serial Version ID.
     */
    private static final long serialVersionUID = 4727190874778922661L;

    /**
     * Marks the first integer id for the range of input method event ids.
     */
    public static final int INPUT_METHOD_FIRST = 1100;

    /**
     * The event type indicating changed input method text. This event is
     * generated by input methods while processing input.
     */
    public static final int INPUT_METHOD_TEXT_CHANGED = INPUT_METHOD_FIRST;

    /**
     * The event type indicating a changed insertion point in input method text.
     * This event is
     * generated by input methods while processing input if only the caret changed.
     */
    public static final int CARET_POSITION_CHANGED = INPUT_METHOD_FIRST + 1;

    /**
     * Marks the last integer id for the range of input method event ids.
     */
    public static final int INPUT_METHOD_LAST = INPUT_METHOD_FIRST + 1;

    /**
     * The time stamp that indicates when the event was created.
     *
     * @serial
     * @see #getWhen
     * @since 1.4
     */
    long when;

    // Text object
    private transient AttributedCharacterIterator text;
    private transient int committedCharacterCount;
    private transient TextHitInfo caret;
    private transient TextHitInfo visiblePosition;

    /**
     * Constructs an <code>InputMethodEvent</code> with the specified
     * source component, type, time, text, caret, and visiblePosition.
     * <p>
     * The offsets of caret and visiblePosition are relative to the current
     * composed text; that is, the composed text within <code>text</code>
     * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
     * the composed text within the <code>text</code> of the
     * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
     * <p>Note that passing in an invalid <code>id</code> results in
     * unspecified behavior. This method throws an
     * <code>IllegalArgumentException</code> if <code>source</code>
     * is <code>null</code>.
     *
     * @param source the object where the event originated
     * @param id the event type
     * @param when a long integer that specifies the time the event occurred
     * @param text the combined committed and composed text,
     *      committed text first; must be <code>null</code>
     *      when the event type is <code>CARET_POSITION_CHANGED</code>;
     *      may be <code>null</code> for
     *      <code>INPUT_METHOD_TEXT_CHANGED</code> if there's no
     *      committed or composed text
     * @param committedCharacterCount the number of committed
     *      characters in the text
     * @param caret the caret (a.k.a. insertion point);
     *      <code>null</code> if there's no caret within current
     *      composed text
     * @param visiblePosition the position that's most important
     *      to be visible; <code>null</code> if there's no
     *      recommendation for a visible position within current
     *      composed text
     * @throws IllegalArgumentException if <code>id</code> is not
     *      in the range
     *      <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>;
     *      or if id is <code>CARET_POSITION_CHANGED</code> and
     *      <code>text</code> is not <code>null</code>;
     *      or if <code>committedCharacterCount</code> is not in the range
     *      <code>0</code>..<code>(text.getEndIndex() - text.getBeginIndex())</code>
     * @throws IllegalArgumentException if <code>source</code> is null
     *
     * @since 1.4
     */
    public InputMethodEvent(Component source, int id, long when,
            AttributedCharacterIterator text, int committedCharacterCount,
            TextHitInfo caret, TextHitInfo visiblePosition) {
        super(source, id);
        if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST) {
            throw new IllegalArgumentException("id outside of valid range");
        }

        if (id == CARET_POSITION_CHANGED && text != null) {
            throw new IllegalArgumentException("text must be null for CARET_POSITION_CHANGED");
        }

        this.when = when;
        this.text = text;
        int textLength = 0;
        if (text != null) {
            textLength = text.getEndIndex() - text.getBeginIndex();
        }

        if (committedCharacterCount < 0 || committedCharacterCount > textLength) {
            throw new IllegalArgumentException("committedCharacterCount outside of valid range");
        }
        this.committedCharacterCount = committedCharacterCount;

        this.caret = caret;
        this.visiblePosition = visiblePosition;
   }

    /**
     * Constructs an <code>InputMethodEvent</code> with the specified
     * source component, type, text, caret, and visiblePosition.
     * <p>
     * The offsets of caret and visiblePosition are relative to the current
     * composed text; that is, the composed text within <code>text</code>
     * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
     * the composed text within the <code>text</code> of the
     * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
     * The time stamp for this event is initialized by invoking
     * {@link java.awt.EventQueue#getMostRecentEventTime()}.
     * <p>Note that passing in an invalid <code>id</code> results in
     * unspecified behavior. This method throws an
     * <code>IllegalArgumentException</code> if <code>source</code>
     * is <code>null</code>.
     *
     * @param source the object where the event originated
     * @param id the event type
     * @param text the combined committed and composed text,
     *      committed text first; must be <code>null</code>
     *      when the event type is <code>CARET_POSITION_CHANGED</code>;
     *      may be <code>null</code> for
     *      <code>INPUT_METHOD_TEXT_CHANGED</code> if there's no
     *      committed or composed text
     * @param committedCharacterCount the number of committed
     *      characters in the text
     * @param caret the caret (a.k.a. insertion point);
     *      <code>null</code> if there's no caret within current
     *      composed text
     * @param visiblePosition the position that's most important
     *      to be visible; <code>null</code> if there's no
     *      recommendation for a visible position within current
     *      composed text
     * @throws IllegalArgumentException if <code>id</code> is not
     *      in the range
     *      <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>;
     *      or if id is <code>CARET_POSITION_CHANGED</code> and
     *      <code>text</code> is not <code>null</code>;
     *      or if <code>committedCharacterCount</code> is not in the range
     *      <code>0</code>..<code>(text.getEndIndex() - text.getBeginIndex())</code>
     * @throws IllegalArgumentException if <code>source</code> is null
     */
    public InputMethodEvent(Component source, int id,
            AttributedCharacterIterator text, int committedCharacterCount,
            TextHitInfo caret, TextHitInfo visiblePosition) {
        this(source, id, EventQueue.getMostRecentEventTime(), text,
             committedCharacterCount, caret, visiblePosition);
    }

    /**
     * Constructs an <code>InputMethodEvent</code> with the
     * specified source component, type, caret, and visiblePosition.
     * The text is set to <code>null</code>,
     * <code>committedCharacterCount</code> to 0.
     * <p>
     * The offsets of <code>caret</code> and <code>visiblePosition</code>
     * are relative to the current composed text; that is,
     * the composed text within the <code>text</code> of the
     * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event if the
     * event being constructed as a <code>CARET_POSITION_CHANGED</code> event.
     * For an <code>INPUT_METHOD_TEXT_CHANGED</code> event without text,
     * <code>caret</code> and <code>visiblePosition</code> must be
     * <code>null</code>.
     * The time stamp for this event is initialized by invoking
     * {@link java.awt.EventQueue#getMostRecentEventTime()}.
     * <p>Note that passing in an invalid <code>id</code> results in
     * unspecified behavior. This method throws an
     * <code>IllegalArgumentException</code> if <code>source</code>
     * is <code>null</code>.
     *
     * @param source the object where the event originated
     * @param id the event type
     * @param caret the caret (a.k.a. insertion point);
     *      <code>null</code> if there's no caret within current
     *      composed text
     * @param visiblePosition the position that's most important
     *      to be visible; <code>null</code> if there's no
     *      recommendation for a visible position within current
     *      composed text
     * @throws IllegalArgumentException if <code>id</code> is not
     *      in the range
     *      <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>
     * @throws IllegalArgumentException if <code>source</code> is null
     */
    public InputMethodEvent(Component source, int id, TextHitInfo caret,
            TextHitInfo visiblePosition) {
        this(source, id, EventQueue.getMostRecentEventTime(), null,
             0, caret, visiblePosition);
    }

    /**
     * Gets the combined committed and composed text.
     * Characters from index 0 to index <code>getCommittedCharacterCount() - 1</code> are committed
     * text, the remaining characters are composed text.
     *
     * @return the text.
     * Always null for CARET_POSITION_CHANGED;
     * may be null for INPUT_METHOD_TEXT_CHANGED if there's no composed or committed text.
     */
    public AttributedCharacterIterator getText() {
        return text;
    }

    /**
     * Gets the number of committed characters in the text.
     */
    public int getCommittedCharacterCount() {
        return committedCharacterCount;
    }

    /**
     * Gets the caret.
     * <p>
     * The offset of the caret is relative to the current
     * composed text; that is, the composed text within getText()
     * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
     * the composed text within getText() of the
     * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
     *
     * @return the caret (a.k.a. insertion point).
     * Null if there's no caret within current composed text.
     */
    public TextHitInfo getCaret() {
        return caret;
    }

    /**
     * Gets the position that's most important to be visible.
     * <p>
     * The offset of the visible position is relative to the current
     * composed text; that is, the composed text within getText()
     * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
     * the composed text within getText() of the
     * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
     *
     * @return the position that's most important to be visible.
     * Null if there's no recommendation for a visible position within current composed text.
     */
    public TextHitInfo getVisiblePosition() {
        return visiblePosition;
    }

    /**
     * Consumes this event so that it will not be processed
     * in the default manner by the source which originated it.
     */
    public void consume() {
        consumed = true;
    }

    /**
     * Returns whether or not this event has been consumed.
     * @see #consume
     */
    public boolean isConsumed() {
        return consumed;
    }

    /**
     * Returns the time stamp of when this event occurred.
     *
     * @return this event's timestamp
     * @since 1.4
     */
    public long getWhen() {
      return when;
    }

    /**
     * Returns a parameter string identifying this event.
     * This method is useful for event-logging and for debugging.
     * It contains the event ID in text form, the characters of the
     * committed and composed text
     * separated by "+", the number of committed characters,
     * the caret, and the visible position.
     *
     * @return a string identifying the event and its attributes
     */
    public String paramString() {
        String typeStr;
        switch(id) {
          case INPUT_METHOD_TEXT_CHANGED:
              typeStr = "INPUT_METHOD_TEXT_CHANGED";
              break;
          case CARET_POSITION_CHANGED:
              typeStr = "CARET_POSITION_CHANGED";
              break;
          default:
              typeStr = "unknown type";
        }

        String textString;
        if (text == null) {
            textString = "no text";
        } else {
            StringBuilder textBuffer = new StringBuilder("\"");
            int committedCharacterCount = this.committedCharacterCount;
            char c = text.first();
            while (committedCharacterCount-- > 0) {
                textBuffer.append(c);
                c = text.next();
            }
            textBuffer.append("\" + \"");
            while (c != CharacterIterator.DONE) {
                textBuffer.append(c);
                c = text.next();
            }
            textBuffer.append("\"");
            textString = textBuffer.toString();
        }

        String countString = committedCharacterCount + " characters committed";

        String caretString;
        if (caret == null) {
            caretString = "no caret";
        } else {
            caretString = "caret: " + caret.toString();
        }

        String visiblePositionString;
        if (visiblePosition == null) {
            visiblePositionString = "no visible position";
        } else {
            visiblePositionString = "visible position: " + visiblePosition.toString();
        }

        return typeStr + ", " + textString + ", " + countString + ", " + caretString + ", " + visiblePositionString;
    }

    /**
     * Initializes the <code>when</code> field if it is not present in the
     * object input stream. In that case, the field will be initialized by
     * invoking {@link java.awt.EventQueue#getMostRecentEventTime()}.
     */
    private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
        s.defaultReadObject();
        if (when == 0) {
            when = EventQueue.getMostRecentEventTime();
        }
    }
}
