/*
 * Copyright (C) 2012 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.providers.downloads;

import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE;
import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED;
import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION;
import static android.provider.Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
import static android.provider.Downloads.Impl.STATUS_RUNNING;

import static com.android.providers.downloads.Constants.TAG;

import android.app.DownloadManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.SystemClock;
import android.provider.Downloads;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Log;
import android.util.LongSparseLongArray;

import com.android.internal.util.ArrayUtils;

import java.text.NumberFormat;

import javax.annotation.concurrent.GuardedBy;

/**
 * Update {@link NotificationManager} to reflect current download states.
 * Collapses similar downloads into a single notification, and builds
 * {@link PendingIntent} that launch towards {@link DownloadReceiver}.
 */
public class DownloadNotifier {

    private static final int TYPE_ACTIVE = 1;
    private static final int TYPE_WAITING = 2;
    private static final int TYPE_COMPLETE = 3;

    private static final String CHANNEL_ACTIVE = "active";
    private static final String CHANNEL_WAITING = "waiting";
    private static final String CHANNEL_COMPLETE = "complete";

    private final Context mContext;
    private final NotificationManager mNotifManager;

    /**
     * Currently active notifications, mapped from clustering tag to timestamp
     * when first shown.
     *
     * @see #buildNotificationTag(Cursor)
     */
    @GuardedBy("mActiveNotifs")
    private final ArrayMap<String, Long> mActiveNotifs = new ArrayMap<>();

    /**
     * Current speed of active downloads, mapped from download ID to speed in
     * bytes per second.
     */
    @GuardedBy("mDownloadSpeed")
    private final LongSparseLongArray mDownloadSpeed = new LongSparseLongArray();

    /**
     * Last time speed was reproted, mapped from download ID to
     * {@link SystemClock#elapsedRealtime()}.
     */
    @GuardedBy("mDownloadSpeed")
    private final LongSparseLongArray mDownloadTouch = new LongSparseLongArray();

    public DownloadNotifier(Context context) {
        mContext = context;
        mNotifManager = context.getSystemService(NotificationManager.class);

        // Ensure that all our channels are ready to use
        mNotifManager.createNotificationChannel(new NotificationChannel(CHANNEL_ACTIVE,
                context.getText(R.string.download_running),
                NotificationManager.IMPORTANCE_MIN));
        mNotifManager.createNotificationChannel(new NotificationChannel(CHANNEL_WAITING,
                context.getText(R.string.download_queued),
                NotificationManager.IMPORTANCE_DEFAULT));
        mNotifManager.createNotificationChannel(new NotificationChannel(CHANNEL_COMPLETE,
                context.getText(com.android.internal.R.string.done_label),
                NotificationManager.IMPORTANCE_DEFAULT));
    }

    public void init() {
        synchronized (mActiveNotifs) {
            mActiveNotifs.clear();
            final StatusBarNotification[] notifs = mNotifManager.getActiveNotifications();
            if (!ArrayUtils.isEmpty(notifs)) {
                for (StatusBarNotification notif : notifs) {
                    mActiveNotifs.put(notif.getTag(), notif.getPostTime());
                }
            }
        }
    }

    /**
     * Notify the current speed of an active download, used for calculating
     * estimated remaining time.
     */
    public void notifyDownloadSpeed(long id, long bytesPerSecond) {
        synchronized (mDownloadSpeed) {
            if (bytesPerSecond != 0) {
                mDownloadSpeed.put(id, bytesPerSecond);
                mDownloadTouch.put(id, SystemClock.elapsedRealtime());
            } else {
                mDownloadSpeed.delete(id);
                mDownloadTouch.delete(id);
            }
        }
    }

    private interface UpdateQuery {
        final String[] PROJECTION = new String[] {
                Downloads.Impl._ID,
                Downloads.Impl.COLUMN_STATUS,
                Downloads.Impl.COLUMN_VISIBILITY,
                Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
                Downloads.Impl.COLUMN_CURRENT_BYTES,
                Downloads.Impl.COLUMN_TOTAL_BYTES,
                Downloads.Impl.COLUMN_DESTINATION,
                Downloads.Impl.COLUMN_TITLE,
                Downloads.Impl.COLUMN_DESCRIPTION,
        };

        final int _ID = 0;
        final int STATUS = 1;
        final int VISIBILITY = 2;
        final int NOTIFICATION_PACKAGE = 3;
        final int CURRENT_BYTES = 4;
        final int TOTAL_BYTES = 5;
        final int DESTINATION = 6;
        final int TITLE = 7;
        final int DESCRIPTION = 8;
    }

    public void update() {
        try (Cursor cursor = mContext.getContentResolver().query(
                Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, UpdateQuery.PROJECTION,
                Downloads.Impl.COLUMN_DELETED + " == '0'", null, null)) {
            synchronized (mActiveNotifs) {
                updateWithLocked(cursor);
            }
        }
    }

    private void updateWithLocked(Cursor cursor) {
        final Resources res = mContext.getResources();

        // Cluster downloads together
        final ArrayMap<String, IntArray> clustered = new ArrayMap<>();
        while (cursor.moveToNext()) {
            final String tag = buildNotificationTag(cursor);
            if (tag != null) {
                IntArray cluster = clustered.get(tag);
                if (cluster == null) {
                    cluster = new IntArray();
                    clustered.put(tag, cluster);
                }
                cluster.add(cursor.getPosition());
            }
        }

        // Build notification for each cluster
        for (int i = 0; i < clustered.size(); i++) {
            final String tag = clustered.keyAt(i);
            final IntArray cluster = clustered.valueAt(i);
            final int type = getNotificationTagType(tag);

            final Notification.Builder builder;
            if (type == TYPE_ACTIVE) {
                builder = new Notification.Builder(mContext, CHANNEL_ACTIVE);
                builder.setSmallIcon(android.R.drawable.stat_sys_download);
            } else if (type == TYPE_WAITING) {
                builder = new Notification.Builder(mContext, CHANNEL_WAITING);
                builder.setSmallIcon(android.R.drawable.stat_sys_warning);
            } else if (type == TYPE_COMPLETE) {
                builder = new Notification.Builder(mContext, CHANNEL_COMPLETE);
                builder.setSmallIcon(android.R.drawable.stat_sys_download_done);
            } else {
                continue;
            }

            builder.setColor(res.getColor(
                    com.android.internal.R.color.system_notification_accent_color));

            // Use time when cluster was first shown to avoid shuffling
            final long firstShown;
            if (mActiveNotifs.containsKey(tag)) {
                firstShown = mActiveNotifs.get(tag);
            } else {
                firstShown = System.currentTimeMillis();
                mActiveNotifs.put(tag, firstShown);
            }
            builder.setWhen(firstShown);
            builder.setOnlyAlertOnce(true);

            // Build action intents
            if (type == TYPE_ACTIVE || type == TYPE_WAITING) {
                final long[] downloadIds = getDownloadIds(cursor, cluster);

                // build a synthetic uri for intent identification purposes
                final Uri uri = new Uri.Builder().scheme("active-dl").appendPath(tag).build();
                final Intent intent = new Intent(Constants.ACTION_LIST,
                        uri, mContext, DownloadReceiver.class);
                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
                        downloadIds);
                builder.setContentIntent(PendingIntent.getBroadcast(mContext,
                        0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
                if (type == TYPE_ACTIVE) {
                    builder.setOngoing(true);
                }

                // Add a Cancel action
                final Uri cancelUri = new Uri.Builder().scheme("cancel-dl").appendPath(tag).build();
                final Intent cancelIntent = new Intent(Constants.ACTION_CANCEL,
                        cancelUri, mContext, DownloadReceiver.class);
                cancelIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
                cancelIntent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, tag);

                builder.addAction(
                    android.R.drawable.ic_menu_close_clear_cancel,
                    res.getString(R.string.button_cancel_download),
                    PendingIntent.getBroadcast(mContext,
                            0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT));

            } else if (type == TYPE_COMPLETE) {
                cursor.moveToPosition(cluster.get(0));
                final long id = cursor.getLong(UpdateQuery._ID);
                final int status = cursor.getInt(UpdateQuery.STATUS);
                final int destination = cursor.getInt(UpdateQuery.DESTINATION);

                final Uri uri = ContentUris.withAppendedId(
                        Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id);
                builder.setAutoCancel(true);

                final String action;
                if (Downloads.Impl.isStatusError(status)) {
                    action = Constants.ACTION_LIST;
                } else {
                    action = Constants.ACTION_OPEN;
                }

                final Intent intent = new Intent(action, uri, mContext, DownloadReceiver.class);
                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
                        getDownloadIds(cursor, cluster));
                builder.setContentIntent(PendingIntent.getBroadcast(mContext,
                        0, intent, PendingIntent.FLAG_UPDATE_CURRENT));

                final Intent hideIntent = new Intent(Constants.ACTION_HIDE,
                        uri, mContext, DownloadReceiver.class);
                hideIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                builder.setDeleteIntent(PendingIntent.getBroadcast(mContext, 0, hideIntent, 0));
            }

            // Calculate and show progress
            String remainingText = null;
            String percentText = null;
            if (type == TYPE_ACTIVE) {
                long current = 0;
                long total = 0;
                long speed = 0;
                synchronized (mDownloadSpeed) {
                    for (int j = 0; j < cluster.size(); j++) {
                        cursor.moveToPosition(cluster.get(j));

                        final long id = cursor.getLong(UpdateQuery._ID);
                        final long currentBytes = cursor.getLong(UpdateQuery.CURRENT_BYTES);
                        final long totalBytes = cursor.getLong(UpdateQuery.TOTAL_BYTES);

                        if (totalBytes != -1) {
                            current += currentBytes;
                            total += totalBytes;
                            speed += mDownloadSpeed.get(id);
                        }
                    }
                }

                if (total > 0) {
                    percentText =
                            NumberFormat.getPercentInstance().format((double) current / total);

                    if (speed > 0) {
                        final long remainingMillis = ((total - current) * 1000) / speed;
                        remainingText = res.getString(R.string.download_remaining,
                                DateUtils.formatDuration(remainingMillis));
                    }

                    final int percent = (int) ((current * 100) / total);
                    builder.setProgress(100, percent, false);
                } else {
                    builder.setProgress(100, 0, true);
                }
            }

            // Build titles and description
            final Notification notif;
            if (cluster.size() == 1) {
                cursor.moveToPosition(cluster.get(0));
                builder.setContentTitle(getDownloadTitle(res, cursor));

                if (type == TYPE_ACTIVE) {
                    final String description = cursor.getString(UpdateQuery.DESCRIPTION);
                    if (!TextUtils.isEmpty(description)) {
                        builder.setContentText(description);
                    } else {
                        builder.setContentText(remainingText);
                    }
                    builder.setContentInfo(percentText);

                } else if (type == TYPE_WAITING) {
                    builder.setContentText(
                            res.getString(R.string.notification_need_wifi_for_size));

                } else if (type == TYPE_COMPLETE) {
                    final int status = cursor.getInt(UpdateQuery.STATUS);
                    if (Downloads.Impl.isStatusError(status)) {
                        builder.setContentText(res.getText(R.string.notification_download_failed));
                    } else if (Downloads.Impl.isStatusSuccess(status)) {
                        builder.setContentText(
                                res.getText(R.string.notification_download_complete));
                    }
                }

                notif = builder.build();

            } else {
                final Notification.InboxStyle inboxStyle = new Notification.InboxStyle(builder);

                for (int j = 0; j < cluster.size(); j++) {
                    cursor.moveToPosition(cluster.get(j));
                    inboxStyle.addLine(getDownloadTitle(res, cursor));
                }

                if (type == TYPE_ACTIVE) {
                    builder.setContentTitle(res.getQuantityString(
                            R.plurals.notif_summary_active, cluster.size(), cluster.size()));
                    builder.setContentText(remainingText);
                    builder.setContentInfo(percentText);
                    inboxStyle.setSummaryText(remainingText);

                } else if (type == TYPE_WAITING) {
                    builder.setContentTitle(res.getQuantityString(
                            R.plurals.notif_summary_waiting, cluster.size(), cluster.size()));
                    builder.setContentText(
                            res.getString(R.string.notification_need_wifi_for_size));
                    inboxStyle.setSummaryText(
                            res.getString(R.string.notification_need_wifi_for_size));
                }

                notif = inboxStyle.build();
            }

            mNotifManager.notify(tag, 0, notif);
        }

        // Remove stale tags that weren't renewed
        for (int i = 0; i < mActiveNotifs.size();) {
            final String tag = mActiveNotifs.keyAt(i);
            if (clustered.containsKey(tag)) {
                i++;
            } else {
                mNotifManager.cancel(tag, 0);
                mActiveNotifs.removeAt(i);
            }
        }
    }

    private static CharSequence getDownloadTitle(Resources res, Cursor cursor) {
        final String title = cursor.getString(UpdateQuery.TITLE);
        if (!TextUtils.isEmpty(title)) {
            return title;
        } else {
            return res.getString(R.string.download_unknown_title);
        }
    }

    private long[] getDownloadIds(Cursor cursor, IntArray cluster) {
        final long[] ids = new long[cluster.size()];
        for (int i = 0; i < cluster.size(); i++) {
            cursor.moveToPosition(cluster.get(i));
            ids[i] = cursor.getLong(UpdateQuery._ID);
        }
        return ids;
    }

    public void dumpSpeeds() {
        synchronized (mDownloadSpeed) {
            for (int i = 0; i < mDownloadSpeed.size(); i++) {
                final long id = mDownloadSpeed.keyAt(i);
                final long delta = SystemClock.elapsedRealtime() - mDownloadTouch.get(id);
                Log.d(TAG, "Download " + id + " speed " + mDownloadSpeed.valueAt(i) + "bps, "
                        + delta + "ms ago");
            }
        }
    }

    /**
     * Build tag used for collapsing several downloads into a single
     * {@link Notification}.
     */
    private static String buildNotificationTag(Cursor cursor) {
        final long id = cursor.getLong(UpdateQuery._ID);
        final int status = cursor.getInt(UpdateQuery.STATUS);
        final int visibility = cursor.getInt(UpdateQuery.VISIBILITY);
        final String notifPackage = cursor.getString(UpdateQuery.NOTIFICATION_PACKAGE);

        if (isQueuedAndVisible(status, visibility)) {
            return TYPE_WAITING + ":" + notifPackage;
        } else if (isActiveAndVisible(status, visibility)) {
            return TYPE_ACTIVE + ":" + notifPackage;
        } else if (isCompleteAndVisible(status, visibility)) {
            // Complete downloads always have unique notifs
            return TYPE_COMPLETE + ":" + id;
        } else {
            return null;
        }
    }

    /**
     * Return the cluster type of the given tag, as created by
     * {@link #buildNotificationTag(Cursor)}.
     */
    private static int getNotificationTagType(String tag) {
        return Integer.parseInt(tag.substring(0, tag.indexOf(':')));
    }

    private static boolean isQueuedAndVisible(int status, int visibility) {
        return status == STATUS_QUEUED_FOR_WIFI &&
                (visibility == VISIBILITY_VISIBLE
                || visibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    }

    private static boolean isActiveAndVisible(int status, int visibility) {
        return status == STATUS_RUNNING &&
                (visibility == VISIBILITY_VISIBLE
                || visibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    }

    private static boolean isCompleteAndVisible(int status, int visibility) {
        return Downloads.Impl.isStatusCompleted(status) &&
                (visibility == VISIBILITY_VISIBLE_NOTIFY_COMPLETED
                || visibility == VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION);
    }
}
