/*
 * Copyright 2020 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.location;

import android.os.SystemClock;
import android.util.Log;
import android.util.TimeUtils;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Holds statistics for location requests (active requests by provider).
 *
 * <p>Must be externally synchronized.
 */
public class LocationRequestStatistics {
    private static final String TAG = "LocationStats";

    // Maps package name and provider to location request statistics.
    public final HashMap<PackageProviderKey, PackageStatistics> statistics
            = new HashMap<PackageProviderKey, PackageStatistics>();

    public final RequestSummaryLimitedHistory history = new RequestSummaryLimitedHistory();

    /**
     * Signals that a package has started requesting locations.
     *
     * @param packageName Name of package that has requested locations.
     * @param providerName Name of provider that is requested (e.g. "gps").
     * @param intervalMs The interval that is requested in ms.
     */
    public void startRequesting(String packageName, String providerName, long intervalMs,
            boolean isForeground) {
        PackageProviderKey key = new PackageProviderKey(packageName, providerName);
        PackageStatistics stats = statistics.get(key);
        if (stats == null) {
            stats = new PackageStatistics();
            statistics.put(key, stats);
        }
        stats.startRequesting(intervalMs);
        stats.updateForeground(isForeground);
        history.addRequest(packageName, providerName, intervalMs);
    }

    /**
     * Signals that a package has stopped requesting locations.
     *
     * @param packageName Name of package that has stopped requesting locations.
     * @param providerName Provider that is no longer being requested.
     */
    public void stopRequesting(String packageName, String providerName) {
        PackageProviderKey key = new PackageProviderKey(packageName, providerName);
        PackageStatistics stats = statistics.get(key);
        if (stats != null) {
            stats.stopRequesting();
        }
        history.removeRequest(packageName, providerName);
    }

    /**
     * Signals that a package possibly switched background/foreground.
     *
     * @param packageName Name of package that has stopped requesting locations.
     * @param providerName Provider that is no longer being requested.
     */
    public void updateForeground(String packageName, String providerName, boolean isForeground) {
        PackageProviderKey key = new PackageProviderKey(packageName, providerName);
        PackageStatistics stats = statistics.get(key);
        if (stats != null) {
            stats.updateForeground(isForeground);
        }
    }

    /**
     * A key that holds both package and provider names.
     */
    public static class PackageProviderKey {
        /**
         * Name of package requesting location.
         */
        public final String packageName;
        /**
         * Name of provider being requested (e.g. "gps").
         */
        public final String providerName;

        PackageProviderKey(String packageName, String providerName) {
            this.packageName = packageName;
            this.providerName = providerName;
        }

        @Override
        public boolean equals(Object other) {
            if (!(other instanceof PackageProviderKey)) {
                return false;
            }

            PackageProviderKey otherKey = (PackageProviderKey) other;
            return packageName.equals(otherKey.packageName)
                    && providerName.equals(otherKey.providerName);
        }

        @Override
        public int hashCode() {
            return packageName.hashCode() + 31 * providerName.hashCode();
        }
    }

    /**
     * A data structure to hold past requests
     */
    public static class RequestSummaryLimitedHistory {
        @VisibleForTesting
        static final int MAX_SIZE = 100;

        final ArrayList<RequestSummary> mList = new ArrayList<>(MAX_SIZE);

        /**
         * Append an added location request to the history
         */
        @VisibleForTesting
        void addRequest(String packageName, String providerName, long intervalMs) {
            addRequestSummary(new RequestSummary(packageName, providerName, intervalMs));
        }

        /**
         * Append a removed location request to the history
         */
        @VisibleForTesting
        void removeRequest(String packageName, String providerName) {
            addRequestSummary(new RequestSummary(
                    packageName, providerName, RequestSummary.REQUEST_ENDED_INTERVAL));
        }

        private void addRequestSummary(RequestSummary summary) {
            while (mList.size() >= MAX_SIZE) {
                mList.remove(0);
            }
            mList.add(summary);
        }

        /**
         * Dump history to a printwriter (for dumpsys location)
         */
        public void dump(IndentingPrintWriter ipw) {
            long systemElapsedOffsetMillis = System.currentTimeMillis()
                    - SystemClock.elapsedRealtime();

            ipw.println("Last Several Location Requests:");
            ipw.increaseIndent();

            for (RequestSummary requestSummary : mList) {
                requestSummary.dump(ipw, systemElapsedOffsetMillis);
            }

            ipw.decreaseIndent();
        }
    }

    /**
     * A data structure to hold a single request
     */
    static class RequestSummary {
        /**
         * Name of package requesting location.
         */
        private final String mPackageName;
        /**
         * Name of provider being requested (e.g. "gps").
         */
        private final String mProviderName;
        /**
         * Interval Requested, or REQUEST_ENDED_INTERVAL indicating request has ended
         */
        private final long mIntervalMillis;
        /**
         * Elapsed time of request
         */
        private final long mElapsedRealtimeMillis;

        /**
         * Placeholder for requested ending (other values indicate request started/changed)
         */
        static final long REQUEST_ENDED_INTERVAL = -1;

        RequestSummary(String packageName, String providerName, long intervalMillis) {
            this.mPackageName = packageName;
            this.mProviderName = providerName;
            this.mIntervalMillis = intervalMillis;
            this.mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
        }

        void dump(IndentingPrintWriter ipw, long systemElapsedOffsetMillis) {
            StringBuilder s = new StringBuilder();
            long systemTimeMillis = systemElapsedOffsetMillis + mElapsedRealtimeMillis;
            s.append("At ").append(TimeUtils.formatForLogging(systemTimeMillis)).append(": ")
                    .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ")
                    .append(String.format("%7s", mProviderName)).append(" request from ")
                    .append(mPackageName);
            if (mIntervalMillis != REQUEST_ENDED_INTERVAL) {
                s.append(" at interval ").append(mIntervalMillis / 1000).append(" seconds");
            }
            ipw.println(s);
        }
    }

    /**
     * Usage statistics for a package/provider pair.
     */
    public static class PackageStatistics {
        // Time when this package first requested location.
        private final long mInitialElapsedTimeMs;
        // Number of active location requests this package currently has.
        private int mNumActiveRequests;
        // Time when this package most recently went from not requesting location to requesting.
        private long mLastActivitationElapsedTimeMs;
        // The fastest interval this package has ever requested.
        private long mFastestIntervalMs;
        // The slowest interval this package has ever requested.
        private long mSlowestIntervalMs;
        // The total time this app has requested location (not including currently running requests).
        private long mTotalDurationMs;

        // Time when this package most recently went to foreground, requesting location. 0 means
        // not currently in foreground.
        private long mLastForegroundElapsedTimeMs;
        // The time this app has requested location (not including currently running requests), while
        // in foreground.
        private long mForegroundDurationMs;

        // Time when package last went dormant (stopped requesting location)
        private long mLastStopElapsedTimeMs;

        private PackageStatistics() {
            mInitialElapsedTimeMs = SystemClock.elapsedRealtime();
            mNumActiveRequests = 0;
            mTotalDurationMs = 0;
            mFastestIntervalMs = Long.MAX_VALUE;
            mSlowestIntervalMs = 0;
            mForegroundDurationMs = 0;
            mLastForegroundElapsedTimeMs = 0;
            mLastStopElapsedTimeMs = 0;
        }

        private void startRequesting(long intervalMs) {
            if (mNumActiveRequests == 0) {
                mLastActivitationElapsedTimeMs = SystemClock.elapsedRealtime();
            }

            if (intervalMs < mFastestIntervalMs) {
                mFastestIntervalMs = intervalMs;
            }

            if (intervalMs > mSlowestIntervalMs) {
                mSlowestIntervalMs = intervalMs;
            }

            mNumActiveRequests++;
        }

        private void updateForeground(boolean isForeground) {
            long nowElapsedTimeMs = SystemClock.elapsedRealtime();
            // if previous interval was foreground, accumulate before resetting start
            if (mLastForegroundElapsedTimeMs != 0) {
                mForegroundDurationMs += (nowElapsedTimeMs - mLastForegroundElapsedTimeMs);
            }
            mLastForegroundElapsedTimeMs = isForeground ? nowElapsedTimeMs : 0;
        }

        private void stopRequesting() {
            if (mNumActiveRequests <= 0) {
                // Shouldn't be a possible code path
                Log.e(TAG, "Reference counting corrupted in usage statistics.");
                return;
            }

            mNumActiveRequests--;
            if (mNumActiveRequests == 0) {
                mLastStopElapsedTimeMs = SystemClock.elapsedRealtime();
                long lastDurationMs = mLastStopElapsedTimeMs - mLastActivitationElapsedTimeMs;
                mTotalDurationMs += lastDurationMs;
                updateForeground(false);
            }
        }

        /**
         * Returns the duration that this request has been active.
         */
        public long getDurationMs() {
            long currentDurationMs = mTotalDurationMs;
            if (mNumActiveRequests > 0) {
                currentDurationMs
                        += SystemClock.elapsedRealtime() - mLastActivitationElapsedTimeMs;
            }
            return currentDurationMs;
        }

        /**
         * Returns the duration that this request has been active.
         */
        public long getForegroundDurationMs() {
            long currentDurationMs = mForegroundDurationMs;
            if (mLastForegroundElapsedTimeMs != 0 ) {
                currentDurationMs
                        += SystemClock.elapsedRealtime() - mLastForegroundElapsedTimeMs;
            }
            return currentDurationMs;
        }

        /**
         * Returns the time since the initial request in ms.
         */
        public long getTimeSinceFirstRequestMs() {
            return SystemClock.elapsedRealtime() - mInitialElapsedTimeMs;
        }

        /**
         * Returns the time since the last request stopped in ms.
         */
        public long getTimeSinceLastRequestStoppedMs() {
            return SystemClock.elapsedRealtime() - mLastStopElapsedTimeMs;
        }

        /**
         * Returns the fastest interval that has been tracked.
         */
        public long getFastestIntervalMs() {
            return mFastestIntervalMs;
        }

        /**
         * Returns the slowest interval that has been tracked.
         */
        public long getSlowestIntervalMs() {
            return mSlowestIntervalMs;
        }

        /**
         * Returns true if a request is active for these tracked statistics.
         */
        public boolean isActive() {
            return mNumActiveRequests > 0;
        }

        @Override
        public String toString() {
            StringBuilder s = new StringBuilder();
            if (mFastestIntervalMs == mSlowestIntervalMs) {
                s.append("Interval ").append(mFastestIntervalMs / 1000).append(" seconds");
            } else {
                s.append("Min interval ").append(mFastestIntervalMs / 1000).append(" seconds");
                s.append(": Max interval ").append(mSlowestIntervalMs / 1000).append(" seconds");
            }
            s.append(": Duration requested ")
                    .append((getDurationMs() / 1000) / 60)
                    .append(" total, ")
                    .append((getForegroundDurationMs() / 1000) / 60)
                    .append(" foreground, out of the last ")
                    .append((getTimeSinceFirstRequestMs() / 1000) / 60)
                    .append(" minutes");
            if (isActive()) {
                s.append(": Currently active");
            } else {
                s.append(": Last active ")
                        .append((getTimeSinceLastRequestStoppedMs() / 1000) / 60)
                        .append(" minutes ago");
            }
            return s.toString();
        }
    }
}
