/*
 * 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 android.view.textclassifier;

import android.annotation.Nullable;
import android.app.Person;
import android.app.RemoteAction;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.textclassifier.intent.LabeledIntent;
import android.view.textclassifier.intent.TemplateIntentFactory;

import com.android.internal.annotations.VisibleForTesting;

import com.google.android.textclassifier.ActionsSuggestionsModel;
import com.google.android.textclassifier.RemoteActionTemplate;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Helper class for action suggestions.
 *
 * @hide
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class ActionsSuggestionsHelper {
    private static final String TAG = "ActionsSuggestions";
    private static final int USER_LOCAL = 0;
    private static final int FIRST_NON_LOCAL_USER = 1;

    private ActionsSuggestionsHelper() {}

    /**
     * Converts the messages to a list of native messages object that the model can understand.
     * <p>
     * User id encoding - local user is represented as 0, Other users are numbered according to
     * how far before they spoke last time in the conversation. For example, considering this
     * conversation:
     * <ul>
     * <li> User A: xxx
     * <li> Local user: yyy
     * <li> User B: zzz
     * </ul>
     * User A will be encoded as 2, user B will be encoded as 1 and local user will be encoded as 0.
     */
    public static ActionsSuggestionsModel.ConversationMessage[] toNativeMessages(
            List<ConversationActions.Message> messages,
            Function<CharSequence, String> languageDetector) {
        List<ConversationActions.Message> messagesWithText =
                messages.stream()
                        .filter(message -> !TextUtils.isEmpty(message.getText()))
                        .collect(Collectors.toCollection(ArrayList::new));
        if (messagesWithText.isEmpty()) {
            return new ActionsSuggestionsModel.ConversationMessage[0];
        }
        Deque<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayDeque<>();
        PersonEncoder personEncoder = new PersonEncoder();
        int size = messagesWithText.size();
        for (int i = size - 1; i >= 0; i--) {
            ConversationActions.Message message = messagesWithText.get(i);
            long referenceTime = message.getReferenceTime() == null
                    ? 0
                    : message.getReferenceTime().toInstant().toEpochMilli();
            String timeZone = message.getReferenceTime() == null
                    ? null
                    : message.getReferenceTime().getZone().getId();
            nativeMessages.push(new ActionsSuggestionsModel.ConversationMessage(
                    personEncoder.encode(message.getAuthor()),
                    message.getText().toString(), referenceTime, timeZone,
                    languageDetector.apply(message.getText())));
        }
        return nativeMessages.toArray(
                new ActionsSuggestionsModel.ConversationMessage[nativeMessages.size()]);
    }

    /**
     * Returns the result id for logging.
     */
    public static String createResultId(
            Context context,
            List<ConversationActions.Message> messages,
            int modelVersion,
            List<Locale> modelLocales) {
        final StringJoiner localesJoiner = new StringJoiner(",");
        for (Locale locale : modelLocales) {
            localesJoiner.add(locale.toLanguageTag());
        }
        final String modelName = String.format(
                Locale.US, "%s_v%d", localesJoiner.toString(), modelVersion);
        final int hash = Objects.hash(
                messages.stream().mapToInt(ActionsSuggestionsHelper::hashMessage),
                context.getPackageName(),
                System.currentTimeMillis());
        return SelectionSessionLogger.SignatureParser.createSignature(
                SelectionSessionLogger.CLASSIFIER_ID, modelName, hash);
    }

    /**
     * Generated labeled intent from an action suggestion and return the resolved result.
     */
    @Nullable
    public static LabeledIntent.Result createLabeledIntentResult(
            Context context,
            TemplateIntentFactory templateIntentFactory,
            ActionsSuggestionsModel.ActionSuggestion nativeSuggestion) {
        RemoteActionTemplate[] remoteActionTemplates =
                nativeSuggestion.getRemoteActionTemplates();
        if (remoteActionTemplates == null) {
            Log.w(TAG, "createRemoteAction: Missing template for type "
                    + nativeSuggestion.getActionType());
            return null;
        }
        List<LabeledIntent> labeledIntents = templateIntentFactory.create(remoteActionTemplates);
        if (labeledIntents.isEmpty()) {
            return null;
        }
        // Given that we only support implicit intent here, we should expect there is just one
        // intent for each action type.
        LabeledIntent.TitleChooser titleChooser =
                ActionsSuggestionsHelper.createTitleChooser(nativeSuggestion.getActionType());
        return labeledIntents.get(0).resolve(context, titleChooser, null);
    }

    /**
     * Returns a {@link LabeledIntent.TitleChooser} for conversation actions use case.
     */
    @Nullable
    public static LabeledIntent.TitleChooser createTitleChooser(String actionType) {
        if (ConversationAction.TYPE_OPEN_URL.equals(actionType)) {
            return (labeledIntent, resolveInfo) -> {
                if (resolveInfo.handleAllWebDataURI) {
                    return labeledIntent.titleWithEntity;
                }
                if ("android".equals(resolveInfo.activityInfo.packageName)) {
                    return labeledIntent.titleWithEntity;
                }
                return labeledIntent.titleWithoutEntity;
            };
        }
        return null;
    }

    /**
     * Returns a list of {@link ConversationAction}s that have 0 duplicates. Two actions are
     * duplicates if they may look the same to users. This function assumes every
     * ConversationActions with a non-null RemoteAction also have a non-null intent in the extras.
     */
    public static List<ConversationAction> removeActionsWithDuplicates(
            List<ConversationAction> conversationActions) {
        // Ideally, we should compare title and icon here, but comparing icon is expensive and thus
        // we use the component name of the target handler as the heuristic.
        Map<Pair<String, String>, Integer> counter = new ArrayMap<>();
        for (ConversationAction conversationAction : conversationActions) {
            Pair<String, String> representation = getRepresentation(conversationAction);
            if (representation == null) {
                continue;
            }
            Integer existingCount = counter.getOrDefault(representation, 0);
            counter.put(representation, existingCount + 1);
        }
        List<ConversationAction> result = new ArrayList<>();
        for (ConversationAction conversationAction : conversationActions) {
            Pair<String, String> representation = getRepresentation(conversationAction);
            if (representation == null || counter.getOrDefault(representation, 0) == 1) {
                result.add(conversationAction);
            }
        }
        return result;
    }

    @Nullable
    private static Pair<String, String> getRepresentation(
            ConversationAction conversationAction) {
        RemoteAction remoteAction = conversationAction.getAction();
        if (remoteAction == null) {
            return null;
        }
        Intent actionIntent = ExtrasUtils.getActionIntent(conversationAction.getExtras());
        ComponentName componentName = actionIntent.getComponent();
        // Action without a component name will be considered as from the same app.
        String packageName = componentName == null ? null : componentName.getPackageName();
        return new Pair<>(
                conversationAction.getAction().getTitle().toString(), packageName);
    }

    private static final class PersonEncoder {
        private final Map<Person, Integer> mMapping = new ArrayMap<>();
        private int mNextUserId = FIRST_NON_LOCAL_USER;

        private int encode(Person person) {
            if (ConversationActions.Message.PERSON_USER_SELF.equals(person)) {
                return USER_LOCAL;
            }
            Integer result = mMapping.get(person);
            if (result == null) {
                mMapping.put(person, mNextUserId);
                result = mNextUserId;
                mNextUserId++;
            }
            return result;
        }
    }

    private static int hashMessage(ConversationActions.Message message) {
        return Objects.hash(message.getAuthor(), message.getText(), message.getReferenceTime());
    }
}
