/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.inputmethod.event;

import android.util.SparseArray;
import android.view.KeyEvent;

import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.LatinIME;

import java.util.ArrayList;

/**
 * This class implements the logic between receiving events and generating code points.
 *
 * Event sources are multiple. It may be a hardware keyboard, a D-PAD, a software keyboard,
 * or any exotic input source.
 * This class will orchestrate the decoding chain that starts with an event and ends up with
 * a stream of code points + decoding state.
 */
public class EventInterpreter {
    // TODO: Implement an object pool for events, as we'll create a lot of them
    // TODO: Create a combiner
    // TODO: Create an object type to represent input material + visual feedback + decoding state
    // TODO: Create an interface to call back to Latin IME through the above object

    final EventDecoderSpec mDecoderSpec;
    final SparseArray<HardwareEventDecoder> mHardwareEventDecoders;
    final SoftwareEventDecoder mSoftwareEventDecoder;
    final LatinIME mLatinIme;
    final ArrayList<Combiner> mCombiners;

    /**
     * Create a default interpreter.
     *
     * This creates a default interpreter that does nothing. A default interpreter should normally
     * only be used for fallback purposes, when we really don't know what we want to do with input.
     *
     * @param latinIme a reference to the ime.
     */
    public EventInterpreter(final LatinIME latinIme) {
        this(null, latinIme);
    }

    /**
     * Create an event interpreter according to a specification.
     *
     * The specification contains information about what to do with events. Typically, it will
     * contain information about the type of keyboards - for example, if hardware keyboard(s) is/are
     * attached, their type will be included here so that the decoder knows what to do with each
     * keypress (a 10-key keyboard is not handled like a qwerty-ish keyboard).
     * It also contains information for combining characters. For example, if the input language
     * is Japanese, the specification will typically request kana conversion.
     * Also note that the specification can be null. This means that we need to create a default
     * interpreter that does no specific combining, and assumes the most common cases.
     *
     * @param specification the specification for event interpretation. null for default.
     * @param latinIme a reference to the ime.
     */
    public EventInterpreter(final EventDecoderSpec specification, final LatinIME latinIme) {
        mDecoderSpec = null != specification ? specification : new EventDecoderSpec();
        // For both, we expect to have only one decoder in almost all cases, hence the default
        // capacity of 1.
        mHardwareEventDecoders = new SparseArray<HardwareEventDecoder>(1);
        mSoftwareEventDecoder = new SoftwareKeyboardEventDecoder();
        mCombiners = CollectionUtils.newArrayList();
        mCombiners.add(new DeadKeyCombiner());
        mLatinIme = latinIme;
    }

    // Helper method to decode a hardware key event into a generic event, and execute any
    // necessary action.
    public boolean onHardwareKeyEvent(final KeyEvent hardwareKeyEvent) {
        final Event decodedEvent = getHardwareKeyEventDecoder(hardwareKeyEvent.getDeviceId())
                .decodeHardwareKey(hardwareKeyEvent);
        return onEvent(decodedEvent);
    }

    public boolean onSoftwareEvent() {
        final Event decodedEvent = getSoftwareEventDecoder().decodeSoftwareEvent();
        return onEvent(decodedEvent);
    }

    private HardwareEventDecoder getHardwareKeyEventDecoder(final int deviceId) {
        final HardwareEventDecoder decoder = mHardwareEventDecoders.get(deviceId);
        if (null != decoder) return decoder;
        // TODO: create the decoder according to the specification
        final HardwareEventDecoder newDecoder = new HardwareKeyboardEventDecoder(deviceId);
        mHardwareEventDecoders.put(deviceId, newDecoder);
        return newDecoder;
    }

    private SoftwareEventDecoder getSoftwareEventDecoder() {
        // Within the context of Latin IME, since we never present several software interfaces
        // at the time, we should never need multiple software event decoders at a time.
        return mSoftwareEventDecoder;
    }

    private boolean onEvent(final Event event) {
        Event currentlyProcessingEvent = event;
        boolean processed = false;
        for (int i = 0; i < mCombiners.size(); ++i) {
            currentlyProcessingEvent = mCombiners.get(i).combine(event);
        }
        while (null != currentlyProcessingEvent) {
            if (currentlyProcessingEvent.isCommittable()) {
                mLatinIme.onCodeInput(currentlyProcessingEvent.mCodePoint,
                        Constants.EXTERNAL_KEYBOARD_COORDINATE,
                        Constants.EXTERNAL_KEYBOARD_COORDINATE);
                processed = true;
            } else if (event.isDead()) {
                processed = true;
            }
            currentlyProcessingEvent = currentlyProcessingEvent.mNextEvent;
        }
        return processed;
    }
}
