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

import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.hardware.display.AmbientBrightnessDayStats;
import android.os.SystemClock;
import android.os.UserManager;
import android.util.Slog;
import android.util.Xml;

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

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

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

/**
 * Class that stores stats of ambient brightness regions as histogram.
 */
public class AmbientBrightnessStatsTracker {

    private static final String TAG = "AmbientBrightnessStatsTracker";
    private static final boolean DEBUG = false;

    @VisibleForTesting
    static final float[] BUCKET_BOUNDARIES_FOR_NEW_STATS =
            {0, 0.1f, 0.3f, 1, 3, 10, 30, 100, 300, 1000, 3000, 10000};
    @VisibleForTesting
    static final int MAX_DAYS_TO_TRACK = 7;

    private final AmbientBrightnessStats mAmbientBrightnessStats;
    private final Timer mTimer;
    private final Injector mInjector;
    private final UserManager mUserManager;
    private float mCurrentAmbientBrightness;
    private @UserIdInt int mCurrentUserId;

    public AmbientBrightnessStatsTracker(UserManager userManager, @Nullable Injector injector) {
        mUserManager = userManager;
        if (injector != null) {
            mInjector = injector;
        } else {
            mInjector = new Injector();
        }
        mAmbientBrightnessStats = new AmbientBrightnessStats();
        mTimer = new Timer(() -> mInjector.elapsedRealtimeMillis());
        mCurrentAmbientBrightness = -1;
    }

    public synchronized void start() {
        mTimer.reset();
        mTimer.start();
    }

    public synchronized void stop() {
        if (mTimer.isRunning()) {
            mAmbientBrightnessStats.log(mCurrentUserId, mInjector.getLocalDate(),
                    mCurrentAmbientBrightness, mTimer.totalDurationSec());
        }
        mTimer.reset();
        mCurrentAmbientBrightness = -1;
    }

    public synchronized void add(@UserIdInt int userId, float newAmbientBrightness) {
        if (mTimer.isRunning()) {
            if (userId == mCurrentUserId) {
                mAmbientBrightnessStats.log(mCurrentUserId, mInjector.getLocalDate(),
                        mCurrentAmbientBrightness, mTimer.totalDurationSec());
            } else {
                if (DEBUG) {
                    Slog.v(TAG, "User switched since last sensor event.");
                }
                mCurrentUserId = userId;
            }
            mTimer.reset();
            mTimer.start();
            mCurrentAmbientBrightness = newAmbientBrightness;
        } else {
            if (DEBUG) {
                Slog.e(TAG, "Timer not running while trying to add brightness stats.");
            }
        }
    }

    public synchronized void writeStats(OutputStream stream) throws IOException {
        mAmbientBrightnessStats.writeToXML(stream);
    }

    public synchronized void readStats(InputStream stream) throws IOException {
        mAmbientBrightnessStats.readFromXML(stream);
    }

    public synchronized ArrayList<AmbientBrightnessDayStats> getUserStats(int userId) {
        return mAmbientBrightnessStats.getUserStats(userId);
    }

    public synchronized void dump(PrintWriter pw) {
        pw.println("AmbientBrightnessStats:");
        pw.print(mAmbientBrightnessStats);
    }

    /**
     * AmbientBrightnessStats tracks ambient brightness stats across users over multiple days.
     * This class is not ThreadSafe.
     */
    class AmbientBrightnessStats {

        private static final String TAG_AMBIENT_BRIGHTNESS_STATS = "ambient-brightness-stats";
        private static final String TAG_AMBIENT_BRIGHTNESS_DAY_STATS =
                "ambient-brightness-day-stats";
        private static final String ATTR_USER = "user";
        private static final String ATTR_LOCAL_DATE = "local-date";
        private static final String ATTR_BUCKET_BOUNDARIES = "bucket-boundaries";
        private static final String ATTR_BUCKET_STATS = "bucket-stats";

        private Map<Integer, Deque<AmbientBrightnessDayStats>> mStats;

        public AmbientBrightnessStats() {
            mStats = new HashMap<>();
        }

        public void log(@UserIdInt int userId, LocalDate localDate, float ambientBrightness,
                float durationSec) {
            Deque<AmbientBrightnessDayStats> userStats = getOrCreateUserStats(mStats, userId);
            AmbientBrightnessDayStats dayStats = getOrCreateDayStats(userStats, localDate);
            dayStats.log(ambientBrightness, durationSec);
        }

        public ArrayList<AmbientBrightnessDayStats> getUserStats(@UserIdInt int userId) {
            if (mStats.containsKey(userId)) {
                return new ArrayList<>(mStats.get(userId));
            } else {
                return null;
            }
        }

        public void writeToXML(OutputStream stream) throws IOException {
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(stream, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

            final LocalDate cutOffDate = mInjector.getLocalDate().minusDays(MAX_DAYS_TO_TRACK);
            out.startTag(null, TAG_AMBIENT_BRIGHTNESS_STATS);
            for (Map.Entry<Integer, Deque<AmbientBrightnessDayStats>> entry : mStats.entrySet()) {
                for (AmbientBrightnessDayStats userDayStats : entry.getValue()) {
                    int userSerialNumber = mInjector.getUserSerialNumber(mUserManager,
                            entry.getKey());
                    if (userSerialNumber != -1 && userDayStats.getLocalDate().isAfter(cutOffDate)) {
                        out.startTag(null, TAG_AMBIENT_BRIGHTNESS_DAY_STATS);
                        out.attribute(null, ATTR_USER, Integer.toString(userSerialNumber));
                        out.attribute(null, ATTR_LOCAL_DATE,
                                userDayStats.getLocalDate().toString());
                        StringBuilder bucketBoundariesValues = new StringBuilder();
                        StringBuilder timeSpentValues = new StringBuilder();
                        for (int i = 0; i < userDayStats.getBucketBoundaries().length; i++) {
                            if (i > 0) {
                                bucketBoundariesValues.append(",");
                                timeSpentValues.append(",");
                            }
                            bucketBoundariesValues.append(userDayStats.getBucketBoundaries()[i]);
                            timeSpentValues.append(userDayStats.getStats()[i]);
                        }
                        out.attribute(null, ATTR_BUCKET_BOUNDARIES,
                                bucketBoundariesValues.toString());
                        out.attribute(null, ATTR_BUCKET_STATS, timeSpentValues.toString());
                        out.endTag(null, TAG_AMBIENT_BRIGHTNESS_DAY_STATS);
                    }
                }
            }
            out.endTag(null, TAG_AMBIENT_BRIGHTNESS_STATS);
            out.endDocument();
            stream.flush();
        }

        public void readFromXML(InputStream stream) throws IOException {
            try {
                Map<Integer, Deque<AmbientBrightnessDayStats>> parsedStats = new HashMap<>();
                XmlPullParser parser = Xml.newPullParser();
                parser.setInput(stream, StandardCharsets.UTF_8.name());

                int type;
                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                        && type != XmlPullParser.START_TAG) {
                }
                String tag = parser.getName();
                if (!TAG_AMBIENT_BRIGHTNESS_STATS.equals(tag)) {
                    throw new XmlPullParserException(
                            "Ambient brightness stats not found in tracker file " + tag);
                }

                final LocalDate cutOffDate = mInjector.getLocalDate().minusDays(MAX_DAYS_TO_TRACK);
                parser.next();
                int outerDepth = parser.getDepth();
                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                        && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                        continue;
                    }
                    tag = parser.getName();
                    if (TAG_AMBIENT_BRIGHTNESS_DAY_STATS.equals(tag)) {
                        String userSerialNumber = parser.getAttributeValue(null, ATTR_USER);
                        LocalDate localDate = LocalDate.parse(
                                parser.getAttributeValue(null, ATTR_LOCAL_DATE));
                        String[] bucketBoundaries = parser.getAttributeValue(null,
                                ATTR_BUCKET_BOUNDARIES).split(",");
                        String[] bucketStats = parser.getAttributeValue(null,
                                ATTR_BUCKET_STATS).split(",");
                        if (bucketBoundaries.length != bucketStats.length
                                || bucketBoundaries.length < 1) {
                            throw new IOException("Invalid brightness stats string.");
                        }
                        float[] parsedBucketBoundaries = new float[bucketBoundaries.length];
                        float[] parsedBucketStats = new float[bucketStats.length];
                        for (int i = 0; i < bucketBoundaries.length; i++) {
                            parsedBucketBoundaries[i] = Float.parseFloat(bucketBoundaries[i]);
                            parsedBucketStats[i] = Float.parseFloat(bucketStats[i]);
                        }
                        int userId = mInjector.getUserId(mUserManager,
                                Integer.parseInt(userSerialNumber));
                        if (userId != -1 && localDate.isAfter(cutOffDate)) {
                            Deque<AmbientBrightnessDayStats> userStats = getOrCreateUserStats(
                                    parsedStats, userId);
                            userStats.offer(
                                    new AmbientBrightnessDayStats(localDate,
                                            parsedBucketBoundaries, parsedBucketStats));
                        }
                    }
                }
                mStats = parsedStats;
            } catch (NullPointerException | NumberFormatException | XmlPullParserException |
                    DateTimeParseException | IOException e) {
                throw new IOException("Failed to parse brightness stats file.", e);
            }
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (Map.Entry<Integer, Deque<AmbientBrightnessDayStats>> entry : mStats.entrySet()) {
                for (AmbientBrightnessDayStats dayStats : entry.getValue()) {
                    builder.append("  ");
                    builder.append(entry.getKey()).append(" ");
                    builder.append(dayStats).append("\n");
                }
            }
            return builder.toString();
        }

        private Deque<AmbientBrightnessDayStats> getOrCreateUserStats(
                Map<Integer, Deque<AmbientBrightnessDayStats>> stats, @UserIdInt int userId) {
            if (!stats.containsKey(userId)) {
                stats.put(userId, new ArrayDeque<>());
            }
            return stats.get(userId);
        }

        private AmbientBrightnessDayStats getOrCreateDayStats(
                Deque<AmbientBrightnessDayStats> userStats, LocalDate localDate) {
            AmbientBrightnessDayStats lastBrightnessStats = userStats.peekLast();
            if (lastBrightnessStats != null && lastBrightnessStats.getLocalDate().equals(
                    localDate)) {
                return lastBrightnessStats;
            } else {
                AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(localDate,
                        BUCKET_BOUNDARIES_FOR_NEW_STATS);
                if (userStats.size() == MAX_DAYS_TO_TRACK) {
                    userStats.poll();
                }
                userStats.offer(dayStats);
                return dayStats;
            }
        }
    }

    @VisibleForTesting
    interface Clock {
        long elapsedTimeMillis();
    }

    @VisibleForTesting
    static class Timer {

        private final Clock clock;
        private long startTimeMillis;
        private boolean started;

        public Timer(Clock clock) {
            this.clock = clock;
        }

        public void reset() {
            started = false;
        }

        public void start() {
            if (!started) {
                startTimeMillis = clock.elapsedTimeMillis();
                started = true;
            }
        }

        public boolean isRunning() {
            return started;
        }

        public float totalDurationSec() {
            if (started) {
                return (float) ((clock.elapsedTimeMillis() - startTimeMillis) / 1000.0);
            }
            return 0;
        }
    }

    @VisibleForTesting
    static class Injector {
        public long elapsedRealtimeMillis() {
            return SystemClock.elapsedRealtime();
        }

        public int getUserSerialNumber(UserManager userManager, int userId) {
            return userManager.getUserSerialNumber(userId);
        }

        public int getUserId(UserManager userManager, int userSerialNumber) {
            return userManager.getUserHandle(userSerialNumber);
        }

        public LocalDate getLocalDate() {
            return LocalDate.now();
        }
    }
}