// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.download;

import static android.app.DownloadManager.ACTION_NOTIFICATION_CLICKED;

import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_CANCEL;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_OPEN;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_PAUSE;
import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_RESUME;
import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_DOWNLOAD_CONTENTID_ID;
import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_DOWNLOAD_CONTENTID_NAMESPACE;
import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_DOWNLOAD_STATE_AT_CANCEL;
import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_IS_OFF_THE_RECORD;
import static org.chromium.chrome.browser.download.DownloadNotificationService.clearResumptionAttemptLeft;

import android.app.DownloadManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;

import com.google.ipc.invalidation.util.Preconditions;

import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.download.DownloadNotificationUmaHelper.UmaDownloadResumption;
import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotificationBridgeUiFactory;
import org.chromium.chrome.browser.init.BrowserParts;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
import org.chromium.chrome.browser.init.EmptyBrowserParts;
import org.chromium.chrome.browser.util.IntentUtils;
import org.chromium.components.offline_items_collection.ContentId;
import org.chromium.components.offline_items_collection.LegacyHelpers;
import org.chromium.components.offline_items_collection.PendingState;
import org.chromium.content_public.browser.BrowserStartupController;

/**
 * Class that spins up native when an interaction with a notification happens and passes the
 * relevant information on to native.
 */
public class DownloadBroadcastManager extends Service {
    private static final String TAG = "DLBroadcastManager";
    private static final int WAIT_TIME_MS = 5000;

    private final DownloadSharedPreferenceHelper mDownloadSharedPreferenceHelper =
            DownloadSharedPreferenceHelper.getInstance();

    private final DownloadNotificationService mDownloadNotificationService;
    private final Handler mHandler = new Handler();
    private final Runnable mStopSelfRunnable = new Runnable() {
        @Override
        public void run() {
            stopSelf();
        }
    };

    public DownloadBroadcastManager() {
        mDownloadNotificationService = DownloadNotificationService.getInstance();
    }

    // The service is only explicitly started in the resume case.
    // TODO(dtrainor): Start DownloadBroadcastManager explicitly in resumption refactor.
    public static void startDownloadBroadcastManager(Context context, Intent source) {
        Intent intent = source != null ? new Intent(source) : new Intent();
        intent.setComponent(new ComponentName(context, DownloadBroadcastManager.class));
        context.startService(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Handle the download operation.
        onNotificationInteraction(intent);

        // If Chrome gets killed, do not restart the service.
        return START_NOT_STICKY;
    }

    /**
     * Passes down information about a notification interaction to native.
     * @param intent with information about the notification interaction (action, contentId, etc).
     */
    public void onNotificationInteraction(final Intent intent) {
        if (!isActionHandled(intent)) return;

        // Remove delayed stop of service until after native library is loaded.
        mHandler.removeCallbacks(mStopSelfRunnable);

        // Since there is a user interaction, resumption is not needed, so clear any queued.
        cancelQueuedResumptions();

        // Update notification appearance immediately in case it takes a while for native to load.
        updateNotification(intent);

        // Handle the intent and propagate it through the native library.
        loadNativeAndPropagateInteraction(intent);
    }

    /**
     * Cancel any download resumption tasks and reset the number of resumption attempts available.
     */
    void cancelQueuedResumptions() {
        DownloadResumptionScheduler.getDownloadResumptionScheduler().cancel();
        // Reset number of attempts left if the action is triggered by user.
        clearResumptionAttemptLeft();
    }

    /**
     * Immediately update notification appearance without changing stored notification state.
     * @param intent with information about the notification.
     */
    void updateNotification(Intent intent) {
        String action = intent.getAction();
        if (!immediateNotificationUpdateNeeded(action)) return;

        final DownloadSharedPreferenceEntry entry = getDownloadEntryFromIntent(intent);
        if (entry == null) return;

        switch (action) {
            case ACTION_DOWNLOAD_PAUSE:
                mDownloadNotificationService.notifyDownloadPaused(entry.id, entry.fileName, true,
                        false, entry.isOffTheRecord, entry.isTransient, null, null, false, true,
                        false, PendingState.NOT_PENDING);
                break;

            case ACTION_DOWNLOAD_CANCEL:
                mDownloadNotificationService.notifyDownloadCanceled(entry.id, true);
                break;

            case ACTION_DOWNLOAD_RESUME:
                // If user manually resumes a download, update the network type if it
                // is not metered previously.
                boolean canDownloadWhileMetered = entry.canDownloadWhileMetered
                        || DownloadManagerService.isActiveNetworkMetered(
                                   ContextUtils.getApplicationContext());
                // Update the SharedPreference entry.
                mDownloadSharedPreferenceHelper.addOrReplaceSharedPreferenceEntry(
                        new DownloadSharedPreferenceEntry(entry.id, entry.notificationId,
                                entry.isOffTheRecord, canDownloadWhileMetered, entry.fileName, true,
                                entry.isTransient));

                mDownloadNotificationService.notifyDownloadPending(entry.id, entry.fileName,
                        entry.isOffTheRecord, entry.canDownloadWhileMetered, entry.isTransient,
                        null, null, false, true, PendingState.PENDING_NETWORK);
                break;

            default:
                // No-op.
                break;
        }
    }

    boolean immediateNotificationUpdateNeeded(String action) {
        return ACTION_DOWNLOAD_PAUSE.equals(action) || ACTION_DOWNLOAD_CANCEL.equals(action)
                || ACTION_DOWNLOAD_RESUME.equals(action);
    }

    /**
     * Helper function that loads the native and runs given runnable.
     * @param intent that is propagated when the native is loaded.
     */
    @VisibleForTesting
    void loadNativeAndPropagateInteraction(final Intent intent) {
        final boolean browserStarted =
                BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
                        .isStartupSuccessfullyCompleted();
        final ContentId id = getContentIdFromIntent(intent);
        final BrowserParts parts = new EmptyBrowserParts() {
            @Override
            public void finishNativeInitialization() {
                // Delay the stop of the service by WAIT_TIME_MS after native library is loaded.
                mHandler.postDelayed(mStopSelfRunnable, WAIT_TIME_MS);

                if (ACTION_DOWNLOAD_RESUME.equals(intent.getAction())
                        && LegacyHelpers.isLegacyDownload(id)) {
                    DownloadNotificationUmaHelper.recordDownloadResumptionHistogram(browserStarted
                                    ? UmaDownloadResumption.BROWSER_RUNNING
                                    : UmaDownloadResumption.BROWSER_NOT_RUNNING);
                    if (!browserStarted) {
                        DownloadManagerService.getDownloadManagerService()
                                .onBackgroundDownloadStarted(id.id);
                    }
                }
                propagateInteraction(intent);
            }

            @Override
            public boolean startServiceManagerOnly() {
                if (!LegacyHelpers.isLegacyDownload(id)) return false;
                return DownloadUtils.shouldStartServiceManagerOnly()
                        && !ACTION_DOWNLOAD_OPEN.equals(intent.getAction());
            }
        };

        try {
            ChromeBrowserInitializer.getInstance().handlePreNativeStartup(parts);
            ChromeBrowserInitializer.getInstance().handlePostNativeStartup(true, parts);
        } catch (ProcessInitException e) {
            Log.e(TAG, "Unable to load native library.", e);
            ChromeApplication.reportStartupErrorAndExit(e);
        }
    }

    @VisibleForTesting
    void propagateInteraction(Intent intent) {
        String action = intent.getAction();
        DownloadNotificationUmaHelper.recordNotificationInteractionHistogram(action);
        final ContentId id = getContentIdFromIntent(intent);

        // Handle actions that do not require a specific entry or service delegate.
        switch (action) {
            case ACTION_NOTIFICATION_CLICKED:
                openDownload(ContextUtils.getApplicationContext(), intent, id);
                return;

            case ACTION_DOWNLOAD_OPEN:
                if (id != null) {
                    OfflineContentAggregatorNotificationBridgeUiFactory.instance().openItem(id);
                }
                return;
        }

        final DownloadSharedPreferenceEntry entry = getDownloadEntryFromIntent(intent);
        boolean isOffTheRecord = entry == null
                ? IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_OFF_THE_RECORD, false)
                : entry.isOffTheRecord;
        DownloadServiceDelegate downloadServiceDelegate = getServiceDelegate(id);

        Preconditions.checkNotNull(downloadServiceDelegate);
        Preconditions.checkNotNull(id);

        // Handle all remaining actions.
        switch (action) {
            case ACTION_DOWNLOAD_CANCEL:
                DownloadNotificationUmaHelper.recordStateAtCancelHistogram(
                        LegacyHelpers.isLegacyDownload(id),
                        intent.getIntExtra(EXTRA_DOWNLOAD_STATE_AT_CANCEL, -1));
                downloadServiceDelegate.cancelDownload(id, isOffTheRecord);
                break;

            case ACTION_DOWNLOAD_PAUSE:
                downloadServiceDelegate.pauseDownload(id, isOffTheRecord);
                break;

            case ACTION_DOWNLOAD_RESUME:
                DownloadItem item = (entry != null)
                        ? entry.buildDownloadItem()
                        : new DownloadItem(false,
                                  new DownloadInfo.Builder()
                                          .setDownloadGuid(id.id)
                                          .setIsOffTheRecord(isOffTheRecord)
                                          .build());
                downloadServiceDelegate.resumeDownload(id, item, true /* hasUserGesture */);
                break;

            default:
                // No-op.
                break;
        }

        downloadServiceDelegate.destroyServiceDelegate();
    }

    static boolean isActionHandled(Intent intent) {
        if (intent == null) return false;
        String action = intent.getAction();
        return ACTION_DOWNLOAD_CANCEL.equals(action) || ACTION_DOWNLOAD_PAUSE.equals(action)
                || ACTION_DOWNLOAD_RESUME.equals(action) || ACTION_DOWNLOAD_OPEN.equals(action)
                || ACTION_NOTIFICATION_CLICKED.equals(action);
    }

    /**
     * Retrieves DownloadSharedPreferenceEntry from a download action intent.
     * TODO(crbug.com/691805):  Instead of getting entire entry, pass only id/isOffTheRecord, after
     *                          consolidating all downloads-related objects.
     * @param intent Intent that contains the download action.
     */
    private DownloadSharedPreferenceEntry getDownloadEntryFromIntent(Intent intent) {
        return mDownloadSharedPreferenceHelper.getDownloadSharedPreferenceEntry(
                getContentIdFromIntent(intent));
    }

    /**
     * @param intent The {@link Intent} to pull from and build a {@link ContentId}.
     * @return A {@link ContentId} built by pulling extras from {@code intent}.  This will be
     *         {@code null} if {@code intent} is missing any required extras.
     */
    private static ContentId getContentIdFromIntent(Intent intent) {
        if (!intent.hasExtra(EXTRA_DOWNLOAD_CONTENTID_ID)
                || !intent.hasExtra(EXTRA_DOWNLOAD_CONTENTID_NAMESPACE)) {
            return null;
        }

        return new ContentId(
                IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_CONTENTID_NAMESPACE),
                IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_CONTENTID_ID));
    }

    /**
     * Gets appropriate download delegate that can handle interactions with download item referred
     * to by the entry.
     * @param id The {@link ContentId} to grab the delegate for.
     * @return delegate for interactions with the entry
     */
    static DownloadServiceDelegate getServiceDelegate(ContentId id) {
        if (LegacyHelpers.isLegacyDownload(id)) {
            return DownloadManagerService.getDownloadManagerService();
        }
        return OfflineContentAggregatorNotificationBridgeUiFactory.instance();
    }

    /**
     * Called to open a particular download item.  Falls back to opening Download Home.
     * @param context Context of the receiver.
     * @param intent Intent from the android DownloadManager.
     */
    private void openDownload(Context context, Intent intent, ContentId contentId) {
        long ids[] =
                intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
        if (ids == null || ids.length == 0) {
            DownloadManagerService.openDownloadsPage(context);
            return;
        }

        long id = ids[0];
        DownloadManagerBridge.queryDownloadResult(id, result -> {
            if (result.contentUri == null) {
                DownloadManagerService.openDownloadsPage(context);
                return;
            }

            String downloadFilename = IntentUtils.safeGetStringExtra(
                    intent, DownloadNotificationService.EXTRA_DOWNLOAD_FILE_PATH);
            boolean isSupportedMimeType = IntentUtils.safeGetBooleanExtra(
                    intent, DownloadNotificationService.EXTRA_IS_SUPPORTED_MIME_TYPE, false);
            boolean isOffTheRecord = IntentUtils.safeGetBooleanExtra(
                    intent, DownloadNotificationService.EXTRA_IS_OFF_THE_RECORD, false);
            String originalUrl =
                    IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_ORIGINATING_URI);
            String referrer = IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_REFERRER);
            DownloadManagerService.openDownloadedContent(context, downloadFilename,
                    isSupportedMimeType, isOffTheRecord, contentId.id, id, originalUrl, referrer,
                    DownloadMetrics.DownloadOpenSource.NOTIFICATION);
        });
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        // Since this service does not need to be bound, just return null.
        return null;
    }
}
