/*
 * 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.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 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 = (NotificationManager) context.getSystemService(
                Context.NOTIFICATION_SERVICE);
    }

    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 = new Notification.Builder(mContext);
            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);

            // Show relevant icon
            if (type == TYPE_ACTIVE) {
                builder.setSmallIcon(android.R.drawable.stat_sys_download);
            } else if (type == TYPE_WAITING) {
                builder.setSmallIcon(android.R.drawable.stat_sys_warning);
            } else if (type == TYPE_COMPLETE) {
                builder.setSmallIcon(android.R.drawable.stat_sys_download_done);
            }

            // 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.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.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 {
                    if (destination != Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION) {
                        action = Constants.ACTION_OPEN;
                    } else {
                        action = Constants.ACTION_LIST;
                    }
                }

                final Intent intent = new Intent(action, uri, mContext, DownloadReceiver.class);
                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);
                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);
    }
}
