// Copyright 2022 The Chromium Authors
// 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.segmentation_platform;

import android.os.Handler;
import android.os.Looper;

import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
import org.chromium.chrome.browser.dom_distiller.ReaderModeManager;
import org.chromium.chrome.browser.dom_distiller.TabDistillabilityProvider;
import org.chromium.chrome.browser.dom_distiller.TabDistillabilityProvider.DistillabilityObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant;
import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;

/** Provides reader mode signal for showing contextual page action for a given tab. */
public class ReaderModeActionProvider implements ContextualPageActionController.ActionProvider {
    @Override
    public void getAction(Tab tab, SignalAccumulator signalAccumulator) {
        final TabDistillabilityProvider tabDistillabilityProvider =
                TabDistillabilityProvider.get(tab);
        if (tabDistillabilityProvider.isDistillabilityDetermined()) {
            notifyActionAvailable(tabDistillabilityProvider.isDistillable(),
                    tabDistillabilityProvider.isMobileOptimized(), tab, signalAccumulator);
            return;
        }

        // Distillability score isn't available yet. Start observing the provider.
        final TabDistillabilityProvider.DistillabilityObserver distillabilityObserver =
                new DistillabilityObserver() {
                    @Override
                    public void onIsPageDistillableResult(Tab tab, boolean isDistillable,
                            boolean isLast, boolean isMobileOptimized) {
                        notifyActionAvailable(
                                isDistillable, isMobileOptimized, tab, signalAccumulator);
                        tabDistillabilityProvider.removeObserver(this);
                    }
                };
        tabDistillabilityProvider.addObserver(distillabilityObserver);
    }

    @Override
    public void onActionShown(Tab tab, @AdaptiveToolbarButtonVariant int action) {
        if (tab == null) return;
        if (action != AdaptiveToolbarButtonVariant.READER_MODE) return;

        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            if (tab.isDestroyed()) return;

            tab.getUserDataHost()
                    .getUserData(ReaderModeManager.USER_DATA_KEY)
                    .setReaderModeUiShown();
        }, /* delayMillis= */ 500);
    }

    private void notifyActionAvailable(boolean isDistillable, boolean isMobileOptimized, Tab tab,
            SignalAccumulator signalAccumulator) {
        // TODO(shaktisahu): Can we merge these into a single method call?
        signalAccumulator.setHasReaderMode(isDistillable && !isFilteredOut(tab, isMobileOptimized));
        signalAccumulator.notifySignalAvailable();
    }

    private boolean isFilteredOut(Tab tab, boolean isMobileOptimized) {
        // Test if the user is requesting the desktop site. Ignore this if distiller is set to
        // ALWAYS_TRUE.
        boolean usingRequestDesktopSite = tab.getWebContents() != null
                && tab.getWebContents().getNavigationController().getUseDesktopUserAgent()
                && !DomDistillerTabUtils.isHeuristicAlwaysTrue();

        if (usingRequestDesktopSite) return true;

        if (AdaptiveToolbarFeatures.isReaderModeRateLimited()
                && tab.getUserDataHost()
                           .getUserData(ReaderModeManager.USER_DATA_KEY)
                           .isReaderModeUiRateLimited()) {
            return true;
        }

        if (isMobileOptimized && DomDistillerTabUtils.shouldExcludeMobileFriendly(tab)) {
            return true;
        }

        return false;
    }
}
