/*
 * 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.wifi;

import android.annotation.Nullable;
import android.os.SystemClock;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.nano.WifiMetricsProto.WifiWakeStats;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Holds WifiWake metrics and converts them to a protobuf included in WifiLog.
 */
public class WifiWakeMetrics {

    /** Maximum number of sessions to store in WifiWakeStats proto. */
    @VisibleForTesting
    static final int MAX_RECORDED_SESSIONS = 10;

    @GuardedBy("mLock")
    private final List<Session> mSessions = new ArrayList<>();
    @GuardedBy("mLock")
    private Session mCurrentSession;

    private boolean mIsInSession = false;
    private int mTotalSessions = 0;
    private int mTotalWakeups = 0;
    private int mIgnoredStarts = 0;

    private final Object mLock = new Object();

    /**
     * Records the beginning of a Wifi Wake session.
     *
     * <p>Starts the session.
     *
     * @param numNetworks The total number of networks stored in the WakeupLock at start.
     */
    public void recordStartEvent(int numNetworks) {
        synchronized (mLock) {
            mCurrentSession = new Session(numNetworks, SystemClock.elapsedRealtime());
            mIsInSession = true;
        }
    }

    /**
     * Records the initialize event of the current Wifi Wake session.
     *
     * <p>Note: The start event must be recorded before this event, otherwise this call will be
     * ignored.
     *
     * @param numScans The total number of elapsed scans since start.
     * @param numNetworks The total number of networks in the lock.
     */
    public void recordInitializeEvent(int numScans, int numNetworks) {
        synchronized (mLock) {
            if (!mIsInSession) {
                return;
            }
            mCurrentSession.recordInitializeEvent(numScans, numNetworks,
                    SystemClock.elapsedRealtime());
        }
    }

    /**
     * Records the unlock event of the current Wifi Wake session.
     *
     * <p>The unlock event occurs when the WakeupLock has all of its networks removed. This event
     * will not be recorded if the initialize event recorded 0 locked networks.
     *
     * <p>Note: The start event must be recorded before this event, otherwise this call will be
     * ignored.
     *
     * @param numScans The total number of elapsed scans since start.
     */
    public void recordUnlockEvent(int numScans) {
        synchronized (mLock) {
            if (!mIsInSession) {
                return;
            }
            mCurrentSession.recordUnlockEvent(numScans, SystemClock.elapsedRealtime());
        }
    }

    /**
     * Records the wakeup event of the current Wifi Wake session.
     *
     * <p>The wakeup event occurs when Wifi is re-enabled by the WakeupController.
     *
     * <p>Note: The start event must be recorded before this event, otherwise this call will be
     * ignored.
     *
     * @param numScans The total number of elapsed scans since start.
     */
    public void recordWakeupEvent(int numScans) {
        synchronized (mLock) {
            if (!mIsInSession) {
                return;
            }
            mCurrentSession.recordWakeupEvent(numScans, SystemClock.elapsedRealtime());
        }
    }

    /**
     * Records the reset event of the current Wifi Wake session.
     *
     * <p>The reset event occurs when Wifi enters client mode. Stores the first
     * {@link #MAX_RECORDED_SESSIONS} in the session list.
     *
     * <p>Note: The start event must be recorded before this event, otherwise this call will be
     * ignored. This event ends the current session.
     *
     * @param numScans The total number of elapsed scans since start.
     */
    public void recordResetEvent(int numScans) {
        synchronized (mLock) {
            if (!mIsInSession) {
                return;
            }
            mCurrentSession.recordResetEvent(numScans, SystemClock.elapsedRealtime());

            // tally successful wakeups here since this is the actual point when wifi is turned on
            if (mCurrentSession.hasWakeupTriggered()) {
                mTotalWakeups++;
            }

            mTotalSessions++;
            if (mSessions.size() < MAX_RECORDED_SESSIONS) {
                mSessions.add(mCurrentSession);
            }
            mIsInSession = false;
        }
    }

    /**
     * Records instance of the start event being ignored due to the controller already being active.
     */
    public void recordIgnoredStart() {
        mIgnoredStarts++;
    }

    /**
     * Returns the consolidated WifiWakeStats proto for WifiMetrics.
     */
    public WifiWakeStats buildProto() {
        WifiWakeStats proto = new WifiWakeStats();

        proto.numSessions = mTotalSessions;
        proto.numWakeups = mTotalWakeups;
        proto.numIgnoredStarts = mIgnoredStarts;
        proto.sessions = new WifiWakeStats.Session[mSessions.size()];

        for (int i = 0; i < mSessions.size(); i++) {
            proto.sessions[i] = mSessions.get(i).buildProto();
        }

        return proto;
    }

    /**
     * Dump all WifiWake stats to console (pw)
     * @param pw
     */
    public void dump(PrintWriter pw) {
        synchronized (mLock) {
            pw.println("-------WifiWake metrics-------");
            pw.println("mTotalSessions: " + mTotalSessions);
            pw.println("mTotalWakeups: " + mTotalWakeups);
            pw.println("mIgnoredStarts: " + mIgnoredStarts);
            pw.println("mIsInSession: " + mIsInSession);
            pw.println("Stored Sessions: " + mSessions.size());
            for (Session session : mSessions) {
                session.dump(pw);
            }
            if (mCurrentSession != null) {
                pw.println("Current Session: ");
                mCurrentSession.dump(pw);
            }
            pw.println("----end of WifiWake metrics----");
        }
    }

    /**
     * Clears WifiWakeMetrics.
     *
     * <p>Keeps the current WifiWake session.
     */
    public void clear() {
        synchronized (mLock) {
            mSessions.clear();
            mTotalSessions = 0;
            mTotalWakeups = 0;
            mIgnoredStarts = 0;
        }
    }

    /** A single WifiWake session. */
    public static class Session {

        private final long mStartTimestamp;
        private final int mStartNetworks;
        private int mInitializeNetworks = 0;

        @VisibleForTesting
        @Nullable
        Event mUnlockEvent;
        @VisibleForTesting
        @Nullable
        Event mInitEvent;
        @VisibleForTesting
        @Nullable
        Event mWakeupEvent;
        @VisibleForTesting
        @Nullable
        Event mResetEvent;

        /** Creates a new WifiWake session. */
        public Session(int numNetworks, long timestamp) {
            mStartNetworks = numNetworks;
            mStartTimestamp = timestamp;
        }

        /**
         * Records an initialize event.
         *
         * <p>Ignores subsequent calls.
         *
         * @param numScans Total number of scans at the time of this event.
         * @param numNetworks Total number of networks in the lock.
         * @param timestamp The timestamp of the event.
         */
        public void recordInitializeEvent(int numScans, int numNetworks, long timestamp) {
            if (mInitEvent == null) {
                mInitializeNetworks = numNetworks;
                mInitEvent = new Event(numScans, timestamp - mStartTimestamp);
            }
        }

        /**
         * Records an unlock event.
         *
         * <p>Ignores subsequent calls.
         *
         * @param numScans Total number of scans at the time of this event.
         * @param timestamp The timestamp of the event.
         */
        public void recordUnlockEvent(int numScans, long timestamp) {
            if (mUnlockEvent == null) {
                mUnlockEvent = new Event(numScans, timestamp - mStartTimestamp);
            }
        }

        /**
         * Records a wakeup event.
         *
         * <p>Ignores subsequent calls.
         *
         * @param numScans Total number of scans at the time of this event.
         * @param timestamp The timestamp of the event.
         */
        public void recordWakeupEvent(int numScans, long timestamp) {
            if (mWakeupEvent == null) {
                mWakeupEvent = new Event(numScans, timestamp - mStartTimestamp);
            }
        }

        /**
         * Returns whether the current session has had its wakeup event triggered.
         */
        public boolean hasWakeupTriggered() {
            return mWakeupEvent != null;
        }

        /**
         * Records a reset event.
         *
         * <p>Ignores subsequent calls.
         *
         * @param numScans Total number of scans at the time of this event.
         * @param timestamp The timestamp of the event.
         */
        public void recordResetEvent(int numScans, long timestamp) {
            if (mResetEvent == null) {
                mResetEvent = new Event(numScans, timestamp - mStartTimestamp);
            }
        }

        /** Returns the proto representation of this session. */
        public WifiWakeStats.Session buildProto() {
            WifiWakeStats.Session sessionProto = new WifiWakeStats.Session();
            sessionProto.startTimeMillis = mStartTimestamp;
            sessionProto.lockedNetworksAtStart = mStartNetworks;

            if (mInitEvent != null) {
                sessionProto.lockedNetworksAtInitialize = mInitializeNetworks;
                sessionProto.initializeEvent = mInitEvent.buildProto();
            }
            if (mUnlockEvent != null) {
                sessionProto.unlockEvent = mUnlockEvent.buildProto();
            }
            if (mWakeupEvent != null) {
                sessionProto.wakeupEvent = mWakeupEvent.buildProto();
            }
            if (mResetEvent != null) {
                sessionProto.resetEvent = mResetEvent.buildProto();
            }

            return sessionProto;
        }

        /** Dumps the current state of the session. */
        public void dump(PrintWriter pw) {
            pw.println("WifiWakeMetrics.Session:");
            pw.println("mStartTimestamp: " + mStartTimestamp);
            pw.println("mStartNetworks: " + mStartNetworks);
            pw.println("mInitializeNetworks: " + mInitializeNetworks);
            pw.println("mInitEvent: " + (mInitEvent == null ? "{}" : mInitEvent.toString()));
            pw.println("mUnlockEvent: " + (mUnlockEvent == null ? "{}" : mUnlockEvent.toString()));
            pw.println("mWakeupEvent: " + (mWakeupEvent == null ? "{}" : mWakeupEvent.toString()));
            pw.println("mResetEvent: " + (mResetEvent == null ? "{}" : mResetEvent.toString()));
        }
    }

    /** An event in a WifiWake session. */
    public static class Event {

        /** Total number of scans that have elapsed prior to this event. */
        public final int mNumScans;
        /** Total elapsed time in milliseconds at the instant of this event. */
        public final long mElapsedTime;

        public Event(int numScans, long elapsedTime) {
            mNumScans = numScans;
            mElapsedTime = elapsedTime;
        }

        /** Returns the proto representation of this event. */
        public WifiWakeStats.Session.Event buildProto() {
            WifiWakeStats.Session.Event eventProto = new WifiWakeStats.Session.Event();
            eventProto.elapsedScans = mNumScans;
            eventProto.elapsedTimeMillis = mElapsedTime;
            return eventProto;
        }

        @Override
        public String toString() {
            return "{ mNumScans: " + mNumScans + ", elapsedTime: " + mElapsedTime + " }";
        }
    }
}
