/*
 * Copyright (C) 2011 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.keyboard;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.Log;
import android.util.Xml;
import android.view.inputmethod.EditorInfo;

import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.Utils;
import com.android.inputmethod.latin.XmlParseUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * This class represents a set of keyboards. Each of them represents a different keyboard
 * specific to a keyboard state, such as alphabet, symbols, and so on.  Layouts in the same
 * {@link KeyboardSet} are related to each other.
 * A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}.
 */
public class KeyboardSet {
    private static final String TAG = KeyboardSet.class.getSimpleName();
    private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;

    private static final String TAG_KEYBOARD_SET = TAG;
    private static final String TAG_ELEMENT = "Element";

    private final Context mContext;
    private final Params mParams;
    private final KeysCache mKeysCache = new KeysCache();

    public static class KeysCache {
        private final Map<Key, Key> mMap;

        public KeysCache() {
            mMap = new HashMap<Key, Key>();
        }

        public Key get(Key key) {
            final Key existingKey = mMap.get(key);
            if (existingKey != null) {
                // Reuse the existing element that equals to "key" without adding "key" to the map.
                return existingKey;
            }
            mMap.put(key, key);
            return key;
        }
    }

    static class KeyboardElement {
        final int mElementId;
        final int mLayoutId;
        final boolean mAutoGenerate;
        KeyboardElement(int elementId, int layoutId, boolean autoGenerate) {
            mElementId = elementId;
            mLayoutId = layoutId;
            mAutoGenerate = autoGenerate;
        }
    }

    static class Params {
        int mMode;
        int mInputType;
        int mImeOptions;
        boolean mTouchPositionCorrectionEnabled;
        boolean mSettingsKeyEnabled;
        boolean mVoiceKeyEnabled;
        boolean mVoiceKeyOnMain;
        boolean mNoSettingsKey;
        Locale mLocale;
        int mOrientation;
        int mWidth;
        final Map<Integer, KeyboardElement> mElementKeyboards =
                new HashMap<Integer, KeyboardElement>();
        Params() {}
    }

    private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
            new HashMap<KeyboardId, SoftReference<Keyboard>>();

    public static void clearKeyboardCache() {
        sKeyboardCache.clear();
    }

    private KeyboardSet(Context context, Params params) {
        mContext = context;
        mParams = params;
    }

    public Keyboard getMainKeyboard() {
        return getKeyboard(false, false, false);
    }

    public Keyboard getSymbolsKeyboard() {
        return getKeyboard(true, false, false);
    }

    public Keyboard getSymbolsShiftedKeyboard() {
        final Keyboard keyboard = getKeyboard(true, false, true);
        // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
        // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a.
        // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked()
        // that takes care of the current keyboard having such shift key or not.
        keyboard.setShiftLocked(keyboard.hasShiftLockKey());
        return keyboard;
    }

    private Keyboard getKeyboard(boolean isSymbols, boolean isShiftLock, boolean isShift) {
        final int elementId = KeyboardSet.getElementId(
                mParams.mMode, isSymbols, isShiftLock, isShift);
        final KeyboardElement keyboardElement = mParams.mElementKeyboards.get(elementId);
        // TODO: If keyboardElement.mAutoGenerate is true, the keyboard will be auto generated
        // based on keyboardElement.mKayoutId Keyboard XML definition.
        final KeyboardId id = KeyboardSet.getKeyboardId(elementId, isSymbols, mParams);
        final Keyboard keyboard = getKeyboard(mContext, keyboardElement, id);
        return keyboard;
    }

    public KeyboardId getMainKeyboardId() {
        final int elementId = KeyboardSet.getElementId(mParams.mMode, false, false, false);
        return KeyboardSet.getKeyboardId(elementId, false, mParams);
    }

    private Keyboard getKeyboard(Context context, KeyboardElement element, KeyboardId id) {
        final Resources res = context.getResources();
        final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
        Keyboard keyboard = (ref == null) ? null : ref.get();
        if (keyboard == null) {
            final Locale savedLocale = LocaleUtils.setSystemLocale(res, id.mLocale);
            try {
                final Keyboard.Builder<Keyboard.Params> builder =
                        new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params());
                if (element.mAutoGenerate) {
                    builder.setAutoGenerate(mKeysCache);
                }
                builder.load(element.mLayoutId, id);
                builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled);
                keyboard = builder.build();
            } finally {
                LocaleUtils.setSystemLocale(res, savedLocale);
            }
            sKeyboardCache.put(id, new SoftReference<Keyboard>(keyboard));

            if (DEBUG_CACHE) {
                Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": "
                        + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
            }
        } else if (DEBUG_CACHE) {
            Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT  id=" + id);
        }

        // TODO: Remove setShiftLocked and setShift calls.
        keyboard.setShiftLocked(false);
        keyboard.setShifted(false);
        return keyboard;
    }

    private static int getElementId(int mode, boolean isSymbols, boolean isShiftLock,
            boolean isShift) {
        switch (mode) {
        case KeyboardId.MODE_PHONE:
            return (isSymbols && isShift)
                    ? KeyboardId.ELEMENT_PHONE_SHIFTED : KeyboardId.ELEMENT_PHONE;
        case KeyboardId.MODE_NUMBER:
            return KeyboardId.ELEMENT_NUMBER;
        default:
            if (isSymbols) {
                return isShift
                        ? KeyboardId.ELEMENT_SYMBOLS_SHIFTED : KeyboardId.ELEMENT_SYMBOLS;
            }
            // TODO: Consult isShiftLock and isShift to determine the element.
            return KeyboardId.ELEMENT_ALPHABET;
        }
    }

    private static KeyboardId getKeyboardId(int elementId, boolean isSymbols, Params params) {
        final boolean hasShortcutKey = params.mVoiceKeyEnabled
                && (isSymbols != params.mVoiceKeyOnMain);
        return new KeyboardId(elementId, params.mLocale, params.mOrientation, params.mWidth,
                params.mMode, params.mInputType, params.mImeOptions, params.mSettingsKeyEnabled,
                params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey);
    }

    public static class Builder {
        private final Context mContext;
        private final String mPackageName;
        private final Resources mResources;
        private final EditorInfo mEditorInfo;

        private final Params mParams = new Params();

        public Builder(Context context, EditorInfo editorInfo) {
            mContext = context;
            mPackageName = context.getPackageName();
            mResources = context.getResources();
            mEditorInfo = editorInfo;
            final Params params = mParams;

            params.mMode = Utils.getKeyboardMode(editorInfo);
            if (editorInfo != null) {
                params.mInputType = editorInfo.inputType;
                params.mImeOptions = editorInfo.imeOptions;
            }
            params.mNoSettingsKey = Utils.inPrivateImeOptions(
                    mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo);
        }

        public Builder setScreenGeometry(int orientation, int widthPixels) {
            mParams.mOrientation = orientation;
            mParams.mWidth = widthPixels;
            return this;
        }

        // TODO: Use InputMethodSubtype object as argument.
        public Builder setSubtype(Locale inputLocale, boolean asciiCapable,
                boolean touchPositionCorrectionEnabled) {
            final boolean deprecatedForceAscii = Utils.inPrivateImeOptions(
                    mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo);
            final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(mParams.mImeOptions)
                    || deprecatedForceAscii;
            mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale;
            mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled;
            return this;
        }

        public Builder setOptions(boolean settingsKeyEnabled, boolean voiceKeyEnabled,
                boolean voiceKeyOnMain) {
            mParams.mSettingsKeyEnabled = settingsKeyEnabled;
            @SuppressWarnings("deprecation")
            final boolean deprecatedNoMicrophone = Utils.inPrivateImeOptions(
                    null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo);
            final boolean noMicrophone = Utils.inPrivateImeOptions(
                    mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, mEditorInfo)
                    || deprecatedNoMicrophone;
            mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone;
            mParams.mVoiceKeyOnMain = voiceKeyOnMain;
            return this;
        }

        public KeyboardSet build() {
            if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED)
                throw new RuntimeException("Screen geometry is not specified");
            if (mParams.mLocale == null)
                throw new RuntimeException("KeyboardSet subtype is not specified");

            final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mParams.mLocale);
            try {
                parseKeyboardSet(mResources, R.xml.keyboard_set);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage() + " in "
                        + mResources.getResourceName(R.xml.keyboard_set)
                        + " of locale " + mParams.mLocale);
            } finally {
                LocaleUtils.setSystemLocale(mResources, savedLocale);
            }
            return new KeyboardSet(mContext, mParams);
        }

        private void parseKeyboardSet(Resources res, int resId) throws XmlPullParserException,
                IOException {
            final XmlResourceParser parser = res.getXml(resId);
            try {
                int event;
                while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
                    if (event == XmlPullParser.START_TAG) {
                        final String tag = parser.getName();
                        if (TAG_KEYBOARD_SET.equals(tag)) {
                            parseKeyboardSetContent(parser);
                        } else {
                            throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
                        }
                    }
                }
            } finally {
                parser.close();
            }
        }

        private void parseKeyboardSetContent(XmlPullParser parser) throws XmlPullParserException,
                IOException {
            int event;
            while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
                if (event == XmlPullParser.START_TAG) {
                    final String tag = parser.getName();
                    if (TAG_ELEMENT.equals(tag)) {
                        parseKeyboardSetElement(parser);
                    } else {
                        throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
                    }
                } else if (event == XmlPullParser.END_TAG) {
                    final String tag = parser.getName();
                    if (TAG_KEYBOARD_SET.equals(tag)) {
                        break;
                    } else {
                        throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEYBOARD_SET);
                    }
                }
            }
        }

        private void parseKeyboardSetElement(XmlPullParser parser) throws XmlPullParserException,
                IOException {
            final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
                    R.styleable.KeyboardSet_Element);
            try {
                XmlParseUtils.checkAttributeExists(a,
                        R.styleable.KeyboardSet_Element_elementName, "elementName",
                        TAG_ELEMENT, parser);
                XmlParseUtils.checkAttributeExists(a,
                        R.styleable.KeyboardSet_Element_elementKeyboard, "elementKeyboard",
                        TAG_ELEMENT, parser);
                XmlParseUtils.checkEndTag(TAG_ELEMENT, parser);

                final int elementName = a.getInt(
                        R.styleable.KeyboardSet_Element_elementName, 0);
                final int elementKeyboard = a.getResourceId(
                        R.styleable.KeyboardSet_Element_elementKeyboard, 0);
                final boolean elementAutoGenerate = a.getBoolean(
                        R.styleable.KeyboardSet_Element_elementAutoGenerate, false);
                mParams.mElementKeyboards.put(elementName, new KeyboardElement(
                        elementName, elementKeyboard, elementAutoGenerate));
            } finally {
                a.recycle();
            }
        }
    }

    public static String parseKeyboardLocale(Resources res, int resId)
            throws XmlPullParserException, IOException {
        final XmlPullParser parser = res.getXml(resId);
        if (parser == null)
            return "";
        int event;
        while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
            if (event == XmlPullParser.START_TAG) {
                final String tag = parser.getName();
                if (TAG_KEYBOARD_SET.equals(tag)) {
                    final TypedArray keyboardSetAttr = res.obtainAttributes(
                            Xml.asAttributeSet(parser), R.styleable.KeyboardSet);
                    final String locale = keyboardSetAttr.getString(
                            R.styleable.KeyboardSet_keyboardLocale);
                    keyboardSetAttr.recycle();
                    return locale;
                } else {
                    throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET);
                }
            }
        }
        return "";
    }
}
