/*
 * Copyright (C) 2017 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.metrics.LogMaker;
import android.util.ArrayMap;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;

/**
 * A helper for logging calls to generateLinks.
 * @hide
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public final class GenerateLinksLogger {

    private static final String LOG_TAG = "GenerateLinksLogger";
    private static final String ZERO = "0";

    private final MetricsLogger mMetricsLogger;
    private final Random mRng;
    private final int mSampleRate;

    /**
     * @param sampleRate the rate at which log events are written. (e.g. 100 means there is a 0.01
     *                   chance that a call to logGenerateLinks results in an event being written).
     *                   To write all events, pass 1.
     */
    public GenerateLinksLogger(int sampleRate) {
        mSampleRate = sampleRate;
        mRng = new Random(System.nanoTime());
        mMetricsLogger = new MetricsLogger();
    }

    @VisibleForTesting
    public GenerateLinksLogger(int sampleRate, MetricsLogger metricsLogger) {
        mSampleRate = sampleRate;
        mRng = new Random(System.nanoTime());
        mMetricsLogger = metricsLogger;
    }

    /** Logs statistics about a call to generateLinks. */
    public void logGenerateLinks(CharSequence text, TextLinks links, String callingPackageName,
            long latencyMs) {
        Objects.requireNonNull(text);
        Objects.requireNonNull(links);
        Objects.requireNonNull(callingPackageName);
        if (!shouldLog()) {
            return;
        }

        // Always populate the total stats, and per-entity stats for each entity type detected.
        final LinkifyStats totalStats = new LinkifyStats();
        final Map<String, LinkifyStats> perEntityTypeStats = new ArrayMap<>();
        for (TextLinks.TextLink link : links.getLinks()) {
            if (link.getEntityCount() == 0) continue;
            final String entityType = link.getEntity(0);
            if (entityType == null
                    || TextClassifier.TYPE_OTHER.equals(entityType)
                    || TextClassifier.TYPE_UNKNOWN.equals(entityType)) {
                continue;
            }
            totalStats.countLink(link);
            perEntityTypeStats.computeIfAbsent(entityType, k -> new LinkifyStats()).countLink(link);
        }

        final String callId = UUID.randomUUID().toString();
        writeStats(callId, callingPackageName, null, totalStats, text, latencyMs);
        for (Map.Entry<String, LinkifyStats> entry : perEntityTypeStats.entrySet()) {
            writeStats(callId, callingPackageName, entry.getKey(), entry.getValue(), text,
                       latencyMs);
        }
    }

    /**
     * Returns whether this particular event should be logged.
     *
     * Sampling is used to reduce the amount of logging data generated.
     **/
    private boolean shouldLog() {
        if (mSampleRate <= 1) {
            return true;
        } else {
            return mRng.nextInt(mSampleRate) == 0;
        }
    }

    /** Writes a log event for the given stats. */
    private void writeStats(String callId, String callingPackageName, @Nullable String entityType,
                            LinkifyStats stats, CharSequence text, long latencyMs) {
        final LogMaker log = new LogMaker(MetricsEvent.TEXT_CLASSIFIER_GENERATE_LINKS)
                .setPackageName(callingPackageName)
                .addTaggedData(MetricsEvent.FIELD_LINKIFY_CALL_ID, callId)
                .addTaggedData(MetricsEvent.FIELD_LINKIFY_NUM_LINKS, stats.mNumLinks)
                .addTaggedData(MetricsEvent.FIELD_LINKIFY_LINK_LENGTH, stats.mNumLinksTextLength)
                .addTaggedData(MetricsEvent.FIELD_LINKIFY_TEXT_LENGTH, text.length())
                .addTaggedData(MetricsEvent.FIELD_LINKIFY_LATENCY, latencyMs);
        if (entityType != null) {
            log.addTaggedData(MetricsEvent.FIELD_LINKIFY_ENTITY_TYPE, entityType);
        }
        mMetricsLogger.write(log);
        debugLog(log);
    }

    private static void debugLog(LogMaker log) {
        if (!Log.ENABLE_FULL_LOGGING) {
            return;
        }
        final String callId = Objects.toString(
                log.getTaggedData(MetricsEvent.FIELD_LINKIFY_CALL_ID), "");
        final String entityType = Objects.toString(
                log.getTaggedData(MetricsEvent.FIELD_LINKIFY_ENTITY_TYPE), "ANY_ENTITY");
        final int numLinks = Integer.parseInt(
                Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_NUM_LINKS), ZERO));
        final int linkLength = Integer.parseInt(
                Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_LINK_LENGTH), ZERO));
        final int textLength = Integer.parseInt(
                Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_TEXT_LENGTH), ZERO));
        final int latencyMs = Integer.parseInt(
                Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_LATENCY), ZERO));

        Log.v(LOG_TAG,
                String.format(Locale.US, "%s:%s %d links (%d/%d chars) %dms %s", callId, entityType,
                        numLinks, linkLength, textLength, latencyMs, log.getPackageName()));
    }

    /** Helper class for storing per-entity type statistics. */
    private static final class LinkifyStats {
        int mNumLinks;
        int mNumLinksTextLength;

        void countLink(TextLinks.TextLink link) {
            mNumLinks += 1;
            mNumLinksTextLength += link.getEnd() - link.getStart();
        }
    }
}
