// Copyright 2016 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.customtabs;

import android.content.Intent;
import android.os.SystemClock;

import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
import org.chromium.chrome.browser.IntentHandler.TabOpenType;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.webapps.ActivityAssigner;

/**
 * Manages the state of separate task Custom Tabs for Android versions prior to L.
 *
 * L provides the ability to force tasks to be in separate stacks via the NEW_DOCUMENT flag, but
 * no corresponding flag is available in KitKat and before.  To work around this, we predefine an
 * limited number of activities that we will cycle through.
 */
public class SeparateTaskManagedCustomTabActivity extends SeparateTaskCustomTabActivity {
    private static final String FORCE_FINISH = "CCT.ForceFinish";

    // Time at which an intent was received and handled.
    private long mIntentHandlingTimeMs;

    @Override
    public void onStartWithNative() {
        super.onStartWithNative();

        if (!isFinishing()) {
            ActivityAssigner.instance(ActivityAssigner.SEPARATE_TASK_CCT_NAMESPACE)
                    .markActivityUsed(getActivityIndex(), getIntent().getData().getAuthority());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        mIntentHandlingTimeMs = SystemClock.uptimeMillis();
        if (intent != null && intent.getBooleanExtra(FORCE_FINISH, false)) {
            finish();
            return;
        }
        super.onNewIntent(intent);
    }

    @Override
    public ChromeTabCreator getTabCreator(boolean incognito) {
        TabCreator tabCreator = super.getTabCreator(incognito);
        assert tabCreator instanceof ChromeTabCreator;
        return (ChromeTabCreator) tabCreator;
    }

    @Override
    protected IntentHandlerDelegate createIntentHandlerDelegate() {
        return new IntentHandlerDelegate() {
            @Override
            public void processWebSearchIntent(String query) {
            }

            @Override
            public void processUrlViewIntent(String url, String referer, String headers,
                    TabOpenType tabOpenType, String externalAppId, int tabIdToBringToFront,
                    boolean hasUserGesture, Intent intent) {
                Tab currentTab = getTabCreator(false).launchUrlFromExternalApp(
                        url, referer, headers, externalAppId, true, intent, mIntentHandlingTimeMs);

                // Close all existing tabs from the previous session.
                TabModel tabModel = getTabModelSelector().getModel(false);
                for (int i = tabModel.getCount() - 1; i >= 0; i--) {
                    if (tabModel.getTabAt(i).equals(currentTab)) continue;
                    tabModel.closeTab(tabModel.getTabAt(i), false, false, false);
                }
            }
        };
    }

    private int getActivityIndex() {
        // Cull out the activity index from the class name.
        String baseClassName = SeparateTaskCustomTabActivity.class.getSimpleName();
        String className = this.getClass().getSimpleName();
        assert className.matches("^" + baseClassName + "[0-9]+$");
        String indexString = className.substring(baseClassName.length());
        return Integer.parseInt(indexString);
    }

    @Override
    protected void handleFinishAndClose() {
        Intent intent = new Intent(getIntent());
        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        intent.putExtra(FORCE_FINISH, true);
        startActivity(intent);
    }
}