/*
 * 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 com.android.systemui.statusbar.policy;

import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NUM_STATUS_ICONS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.STATUS_BAR_ICONS_CHANGED;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;

import android.content.Context;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;

import com.android.internal.logging.MetricsLogger;

import java.util.Arrays;
import java.util.List;

public class IconLoggerImpl implements IconLogger {

    // Minimum ms between log statements.
    // NonFinalForTesting
    @VisibleForTesting
    protected static long MIN_LOG_INTERVAL = 1000;

    private final Context mContext;
    private final Handler mHandler;
    private final MetricsLogger mLogger;
    private final ArraySet<String> mIcons = new ArraySet<>();
    private final List<String> mIconIndex;
    private long mLastLog = System.currentTimeMillis();

    public IconLoggerImpl(Context context, Looper bgLooper, MetricsLogger logger) {
        mContext = context;
        mHandler = new Handler(bgLooper);
        mLogger = logger;
        String[] icons = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_statusBarIcons);
        mIconIndex = Arrays.asList(icons);
        doLog();
    }

    @Override
    public void onIconShown(String tag) {
        synchronized (mIcons) {
            if (mIcons.contains(tag)) return;
            mIcons.add(tag);
        }
        if (!mHandler.hasCallbacks(mLog)) {
            mHandler.postDelayed(mLog, MIN_LOG_INTERVAL);
        }
    }

    @Override
    public void onIconHidden(String tag) {
        synchronized (mIcons) {
            if (!mIcons.contains(tag)) return;
            mIcons.remove(tag);
        }
        if (!mHandler.hasCallbacks(mLog)) {
            mHandler.postDelayed(mLog, MIN_LOG_INTERVAL);
        }
    }

    private void doLog() {
        long time = System.currentTimeMillis();
        long timeSinceLastLog = time - mLastLog;
        mLastLog = time;

        ArraySet<String> icons;
        synchronized (mIcons) {
            icons = new ArraySet<>(mIcons);
        }
        mLogger.write(new LogMaker(STATUS_BAR_ICONS_CHANGED)
                .setType(TYPE_ACTION)
                .setLatency(timeSinceLastLog)
                .addTaggedData(FIELD_NUM_STATUS_ICONS, icons.size())
                .addTaggedData(FIELD_STATUS_ICONS, getBitField(icons)));
    }

    private int getBitField(ArraySet<String> icons) {
        int iconsVisible = 0;
        for (String icon : icons) {
            int index = mIconIndex.indexOf(icon);
            if (index >= 0) {
                iconsVisible |= (1 << index);
            }
        }
        return iconsVisible;
    }

    private final Runnable mLog = this::doLog;
}
