/*
 * Copyright (C) 2018 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.server.inputmethod;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.icu.util.ULocale;
import android.os.Environment;
import android.os.FileUtils;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;

import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;

import libcore.io.IoUtils;

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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Utility class to read/write subtype.xml.
 */
final class AdditionalSubtypeUtils {
    private static final String TAG = "AdditionalSubtypeUtils";

    private static final String SYSTEM_PATH = "system";
    private static final String INPUT_METHOD_PATH = "inputmethod";
    private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
    private static final String NODE_SUBTYPES = "subtypes";
    private static final String NODE_SUBTYPE = "subtype";
    private static final String NODE_IMI = "imi";
    private static final String ATTR_ID = "id";
    private static final String ATTR_LABEL = "label";
    private static final String ATTR_NAME_OVERRIDE = "nameOverride";
    private static final String ATTR_NAME_PK_LANGUAGE_TAG = "pkLanguageTag";
    private static final String ATTR_NAME_PK_LAYOUT_TYPE = "pkLayoutType";
    private static final String ATTR_ICON = "icon";
    private static final String ATTR_IME_SUBTYPE_ID = "subtypeId";
    private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
    private static final String ATTR_IME_SUBTYPE_LANGUAGE_TAG = "languageTag";
    private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
    private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
    private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
    private static final String ATTR_IS_ASCII_CAPABLE = "isAsciiCapable";

    private AdditionalSubtypeUtils() {
    }

    /**
     * Returns a {@link File} that represents the directory at which subtype.xml will be placed.
     *
     * @param userId User ID with subtype.xml path should be determined.
     * @return {@link File} that represents the directory.
     */
    @NonNull
    private static File getInputMethodDir(@UserIdInt int userId) {
        final File systemDir = userId == UserHandle.USER_SYSTEM
                ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
                : Environment.getUserSystemDirectory(userId);
        return new File(systemDir, INPUT_METHOD_PATH);
    }

    /**
     * Returns an {@link AtomicFile} to read/write additional subtype for the given user id.
     *
     * @param inputMethodDir Directory at which subtype.xml will be placed
     * @return {@link AtomicFile} to be used to read/write additional subtype
     */
    @NonNull
    private static AtomicFile getAdditionalSubtypeFile(File inputMethodDir) {
        final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
        return new AtomicFile(subtypeFile, "input-subtypes");
    }

    /**
     * Write additional subtypes into "subtype.xml".
     *
     * <p>This method does not confer any data/file locking semantics. Caller must make sure that
     * multiple threads are not calling this method at the same time for the same {@code userId}.
     * </p>
     *
     * @param allSubtypes {@link ArrayMap} from IME ID to additional subtype list. Passing an empty
     *                    map deletes the file.
     * @param methodMap   {@link ArrayMap} from IME ID to {@link InputMethodInfo}.
     * @param userId      The user ID to be associated with.
     */
    static void save(ArrayMap<String, List<InputMethodSubtype>> allSubtypes,
            ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) {
        final File inputMethodDir = getInputMethodDir(userId);

        if (allSubtypes.isEmpty()) {
            if (!inputMethodDir.exists()) {
                // Even the parent directory doesn't exist.  There is nothing to clean up.
                return;
            }
            final AtomicFile subtypesFile = getAdditionalSubtypeFile(inputMethodDir);
            if (subtypesFile.exists()) {
                subtypesFile.delete();
            }
            if (FileUtils.listFilesOrEmpty(inputMethodDir).length == 0) {
                if (!inputMethodDir.delete()) {
                    Slog.e(TAG, "Failed to delete the empty parent directory " + inputMethodDir);
                }
            }
            return;
        }

        if (!inputMethodDir.exists() && !inputMethodDir.mkdirs()) {
            Slog.e(TAG, "Failed to create a parent directory " + inputMethodDir);
            return;
        }
        saveToFile(allSubtypes, methodMap, getAdditionalSubtypeFile(inputMethodDir));
    }

    @VisibleForTesting
    static void saveToFile(ArrayMap<String, List<InputMethodSubtype>> allSubtypes,
            ArrayMap<String, InputMethodInfo> methodMap, AtomicFile subtypesFile) {
        // Safety net for the case that this function is called before methodMap is set.
        final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
        FileOutputStream fos = null;
        try {
            fos = subtypesFile.startWrite();
            final TypedXmlSerializer out = Xml.resolveSerializer(fos);
            out.startDocument(null, true);
            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            out.startTag(null, NODE_SUBTYPES);
            for (String imiId : allSubtypes.keySet()) {
                if (isSetMethodMap && !methodMap.containsKey(imiId)) {
                    Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
                    continue;
                }
                final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
                if (subtypesList == null) {
                    Slog.e(TAG, "Null subtype list for IME " + imiId);
                    continue;
                }
                out.startTag(null, NODE_IMI);
                out.attribute(null, ATTR_ID, imiId);
                for (final InputMethodSubtype subtype : subtypesList) {
                    out.startTag(null, NODE_SUBTYPE);
                    if (subtype.hasSubtypeId()) {
                        out.attributeInt(null, ATTR_IME_SUBTYPE_ID, subtype.getSubtypeId());
                    }
                    out.attributeInt(null, ATTR_ICON, subtype.getIconResId());
                    out.attributeInt(null, ATTR_LABEL, subtype.getNameResId());
                    out.attribute(null, ATTR_NAME_OVERRIDE, subtype.getNameOverride().toString());
                    ULocale pkLanguageTag = subtype.getPhysicalKeyboardHintLanguageTag();
                    if (pkLanguageTag != null) {
                        out.attribute(null, ATTR_NAME_PK_LANGUAGE_TAG,
                                pkLanguageTag.toLanguageTag());
                    }
                    out.attribute(null, ATTR_NAME_PK_LAYOUT_TYPE,
                            subtype.getPhysicalKeyboardHintLayoutType());

                    out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
                    out.attribute(null, ATTR_IME_SUBTYPE_LANGUAGE_TAG,
                            subtype.getLanguageTag());
                    out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
                    out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
                    out.attributeInt(null, ATTR_IS_AUXILIARY, subtype.isAuxiliary() ? 1 : 0);
                    out.attributeInt(null, ATTR_IS_ASCII_CAPABLE, subtype.isAsciiCapable() ? 1 : 0);
                    out.endTag(null, NODE_SUBTYPE);
                }
                out.endTag(null, NODE_IMI);
            }
            out.endTag(null, NODE_SUBTYPES);
            out.endDocument();
            subtypesFile.finishWrite(fos);
        } catch (IOException e) {
            Slog.w(TAG, "Error writing subtypes", e);
            if (fos != null) {
                subtypesFile.failWrite(fos);
            }
        } finally {
            IoUtils.closeQuietly(fos);
        }
    }

    /**
     * Read additional subtypes from "subtype.xml".
     *
     * <p>This method does not confer any data/file locking semantics. Caller must make sure that
     * multiple threads are not calling this method at the same time for the same {@code userId}.
     * </p>
     *
     * @param allSubtypes {@link ArrayMap} from IME ID to additional subtype list. This parameter
     *                    will be used to return the result.
     * @param userId      The user ID to be associated with.
     */
    static void load(@NonNull ArrayMap<String, List<InputMethodSubtype>> allSubtypes,
            @UserIdInt int userId) {
        allSubtypes.clear();

        final AtomicFile subtypesFile = getAdditionalSubtypeFile(getInputMethodDir(userId));
        // Not having the file means there is no additional subtype.
        if (subtypesFile.exists()) {
            loadFromFile(allSubtypes, subtypesFile);
        }
    }

    @VisibleForTesting
    static void loadFromFile(@NonNull ArrayMap<String, List<InputMethodSubtype>> allSubtypes,
            AtomicFile subtypesFile) {
        try (FileInputStream fis = subtypesFile.openRead()) {
            final TypedXmlPullParser parser = Xml.resolvePullParser(fis);
            int type = parser.next();
            // Skip parsing until START_TAG
            while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
                type = parser.next();
            }
            String firstNodeName = parser.getName();
            if (!NODE_SUBTYPES.equals(firstNodeName)) {
                throw new XmlPullParserException("Xml doesn't start with subtypes");
            }
            final int depth = parser.getDepth();
            String currentImiId = null;
            ArrayList<InputMethodSubtype> tempSubtypesArray = null;
            while (((type = parser.next()) != XmlPullParser.END_TAG
                    || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
                if (type != XmlPullParser.START_TAG) {
                    continue;
                }
                final String nodeName = parser.getName();
                if (NODE_IMI.equals(nodeName)) {
                    currentImiId = parser.getAttributeValue(null, ATTR_ID);
                    if (TextUtils.isEmpty(currentImiId)) {
                        Slog.w(TAG, "Invalid imi id found in subtypes.xml");
                        continue;
                    }
                    tempSubtypesArray = new ArrayList<>();
                    allSubtypes.put(currentImiId, tempSubtypesArray);
                } else if (NODE_SUBTYPE.equals(nodeName)) {
                    if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
                        Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
                        continue;
                    }
                    final int icon = parser.getAttributeInt(null, ATTR_ICON);
                    final int label = parser.getAttributeInt(null, ATTR_LABEL);
                    final String untranslatableName = parser.getAttributeValue(null,
                            ATTR_NAME_OVERRIDE);
                    final String pkLanguageTag = parser.getAttributeValue(null,
                            ATTR_NAME_PK_LANGUAGE_TAG);
                    final String pkLayoutType = parser.getAttributeValue(null,
                            ATTR_NAME_PK_LAYOUT_TYPE);
                    final String imeSubtypeLocale =
                            parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
                    final String languageTag =
                            parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LANGUAGE_TAG);
                    final String imeSubtypeMode =
                            parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
                    final String imeSubtypeExtraValue =
                            parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
                    final boolean isAuxiliary = "1".equals(String.valueOf(
                            parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
                    final boolean isAsciiCapable = "1".equals(String.valueOf(
                            parser.getAttributeValue(null, ATTR_IS_ASCII_CAPABLE)));
                    final InputMethodSubtype.InputMethodSubtypeBuilder
                            builder = new InputMethodSubtype.InputMethodSubtypeBuilder()
                            .setSubtypeNameResId(label)
                            .setPhysicalKeyboardHint(
                                    pkLanguageTag == null ? null : new ULocale(pkLanguageTag),
                                    pkLayoutType == null ? "" : pkLayoutType)
                            .setSubtypeIconResId(icon)
                            .setSubtypeLocale(imeSubtypeLocale)
                            .setLanguageTag(languageTag)
                            .setSubtypeMode(imeSubtypeMode)
                            .setSubtypeExtraValue(imeSubtypeExtraValue)
                            .setIsAuxiliary(isAuxiliary)
                            .setIsAsciiCapable(isAsciiCapable);
                    final int subtypeId = parser.getAttributeInt(null, ATTR_IME_SUBTYPE_ID,
                            InputMethodSubtype.SUBTYPE_ID_NONE);
                    if (subtypeId != InputMethodSubtype.SUBTYPE_ID_NONE) {
                        builder.setSubtypeId(subtypeId);
                    }
                    if (untranslatableName != null) {
                        builder.setSubtypeNameOverride(untranslatableName);
                    }
                    tempSubtypesArray.add(builder.build());
                }
            }
        } catch (XmlPullParserException | IOException | NumberFormatException e) {
            Slog.w(TAG, "Error reading subtypes", e);
        }
    }
}
