/*
 * Copyright 2019 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 androidx.browser.trusted;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.browser.customtabs.CustomTabColorSchemeParams;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.browser.customtabs.CustomTabsSession;
import androidx.browser.customtabs.TrustedWebUtils;
import androidx.browser.trusted.sharing.ShareData;
import androidx.browser.trusted.sharing.ShareTarget;
import androidx.browser.trusted.splashscreens.SplashScreenParamKey;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Constructs instances of {@link TrustedWebActivityIntent} that can be used to start Trusted Web
 * Activities (see {@link TrustedWebUtils} for more details).
 */
public class TrustedWebActivityIntentBuilder {
    /**
     * Extra for the Trusted Web Activity launch Intent to specify a {@link Bundle} of parameters
     * for the browser to use in constructing a splash screen.
     *
     * It is recommended to use {@link TrustedWebActivityIntentBuilder} instead of manually piecing
     * the Intent together.
     */
    @SuppressLint("ActionValue")
    public static final String EXTRA_SPLASH_SCREEN_PARAMS =
            "androidx.browser.trusted.EXTRA_SPLASH_SCREEN_PARAMS";

    /**
     * Extra for the Trusted Web Activity launch Intent to specify a list of origins for the
     * browser to treat as trusted, in addition to the origin of the launching URL.
     *
     * It is recommended to use {@link TrustedWebActivityIntentBuilder} instead of manually piecing
     * the Intent together.
     */
    @SuppressLint("ActionValue")
    public static final String EXTRA_ADDITIONAL_TRUSTED_ORIGINS =
            "android.support.customtabs.extra.ADDITIONAL_TRUSTED_ORIGINS";

    /** Extra for the share target, see {@link #setShareParams}. */
    public static final String EXTRA_SHARE_TARGET = "androidx.browser.trusted.extra.SHARE_TARGET";

    /** Extra for the share data, see {@link #setShareParams}. */
    public static final String EXTRA_SHARE_DATA = "androidx.browser.trusted.extra.SHARE_DATA";

    /** Extra for the {@link TrustedWebActivityDisplayMode}, see {@link #setDisplayMode}. */
    public static final String EXTRA_DISPLAY_MODE = "androidx.browser.trusted.extra.DISPLAY_MODE";

    /** Extra for the screenOrientation, see {@link #setScreenOrientation}. */
    public static final String EXTRA_SCREEN_ORIENTATION =
            "androidx.browser.trusted.extra.SCREEN_ORIENTATION";

    @NonNull
    private final Uri mUri;
    @NonNull
    private final CustomTabsIntent.Builder mIntentBuilder = new CustomTabsIntent.Builder();

    @Nullable
    private List<String> mAdditionalTrustedOrigins;
    @Nullable
    private Bundle mSplashScreenParams;

    @Nullable
    private ShareData mShareData;
    @Nullable
    private ShareTarget mShareTarget;

    @NonNull
    private TrustedWebActivityDisplayMode mDisplayMode =
            new TrustedWebActivityDisplayMode.DefaultMode();

    @ScreenOrientation.LockType
    private int mScreenOrientation = ScreenOrientation.DEFAULT;

    /**
     * Creates a Builder given the required parameters.
     *
     * @param uri The web page to launch as Trusted Web Activity.
     */
    public TrustedWebActivityIntentBuilder(@NonNull Uri uri) {
        mUri = uri;
    }

    /**
     * Sets the color applied to the toolbar and the status bar, see
     * {@link CustomTabsIntent.Builder#setToolbarColor}.
     *
     * When a Trusted Web Activity is on the verified origin, the toolbar is hidden, so the color
     * applies only to the status bar. When it's on an unverified origin, the toolbar is shown, and
     * the color applies to both toolbar and status bar.
     *
     * @deprecated Use {@link #setDefaultColorSchemeParams} instead.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setToolbarColor(@ColorInt int color) {
        mIntentBuilder.setToolbarColor(color);
        return this;
    }

    /**
     * Sets the navigation bar color, see {@link CustomTabsIntent.Builder#setNavigationBarColor}.
     *
     * @deprecated Use {@link #setDefaultColorSchemeParams} instead.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setNavigationBarColor(@ColorInt int color) {
        mIntentBuilder.setNavigationBarColor(color);
        return this;
    }

    /**
     * Sets the navigation bar divider color, see
     * {@link CustomTabsIntent.Builder#setNavigationBarDividerColor}.
     *
     * @deprecated Use {@link #setDefaultColorSchemeParams} instead.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setNavigationBarDividerColor(@ColorInt int color) {
        mIntentBuilder.setNavigationBarDividerColor(color);
        return this;
    }

    /**
     * Sets the color scheme, see {@link CustomTabsIntent.Builder#setColorScheme}.
     * In Trusted Web Activities color scheme may affect such UI elements as info bars and context
     * menus.
     *
     * @param colorScheme Must be one of {@link CustomTabsIntent#COLOR_SCHEME_SYSTEM},
     *                    {@link CustomTabsIntent#COLOR_SCHEME_LIGHT}, and
     *                    {@link CustomTabsIntent#COLOR_SCHEME_DARK}.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setColorScheme(
            @CustomTabsIntent.ColorScheme int colorScheme) {
        mIntentBuilder.setColorScheme(colorScheme);
        return this;
    }

    /**
     * Sets {@link CustomTabColorSchemeParams} for the given color scheme.
     * This allows, for example, to set two navigation bar colors - for light and dark scheme.
     * Trusted Web Activity will automatically apply the correct color according to current system
     * settings. For more details see {@link CustomTabsIntent.Builder#setColorSchemeParams}.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setColorSchemeParams(
            @CustomTabsIntent.ColorScheme int colorScheme,
            @NonNull CustomTabColorSchemeParams params) {
        mIntentBuilder.setColorSchemeParams(colorScheme, params);
        return this;
    }

    /**
     * Sets the default {@link CustomTabColorSchemeParams}.
     *
     * This will set a default color scheme that applies when no CustomTabColorSchemeParams
     * specified for current color scheme via {@link #setColorSchemeParams}.
     *
     * @param params An instance of {@link CustomTabColorSchemeParams}.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setDefaultColorSchemeParams(
            @NonNull CustomTabColorSchemeParams params) {
        mIntentBuilder.setDefaultColorSchemeParams(params);
        return this;
    }

    /**
     * Sets a list of additional trusted origins that the user may navigate or be redirected to
     * from the starting uri.
     *
     * For example, if the user starts at https://www.example.com/page1 and is redirected to
     * https://m.example.com/page2, and both origins are associated with the calling application
     * via the Digital Asset Links, then pass "https://www.example.com/page1" as uri and
     * Arrays.asList("https://m.example.com") as additionalTrustedOrigins.
     *
     * Alternatively, use {@link CustomTabsSession#validateRelationship} to validate additional
     * origins asynchronously, but that would delay launching the Trusted Web Activity.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setAdditionalTrustedOrigins(
            @NonNull List<String> origins) {
        mAdditionalTrustedOrigins = origins;
        return this;
    }

    /**
     * Sets the parameters of a splash screen shown while the web page is loading, such as
     * background color. See {@link SplashScreenParamKey} for a list of supported parameters.
     *
     * To provide the image for the splash screen, use {@link TrustedWebUtils#transferSplashImage},
     * prior to launching the intent.
     *
     * It is recommended to also show the same splash screen in the app as soon as possible,
     * prior to establishing a CustomTabConnection. The Trusted Web Activity provider should
     * ensure seamless transition of the splash screen from the app onto the top of webpage
     * being loaded.
     *
     * The splash screen will be removed on the first paint of the page, or when the page load
     * fails.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setSplashScreenParams(
            @NonNull Bundle splashScreenParams) {
        mSplashScreenParams = splashScreenParams;
        return this;
    }

    /**
     * Sets the parameters for delivering data to a Web Share Target via a Trusted Web Activity.
     *
     * @param shareTarget A {@link ShareTarget} object describing the Web Share Target.
     * @param shareData   A {@link ShareData} object containing the data to be sent to the Web Share
     *                    Target.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setShareParams(@NonNull ShareTarget shareTarget,
            @NonNull ShareData shareData) {
        mShareTarget = shareTarget;
        mShareData = shareData;
        return this;
    }

    /**
     * Sets a {@link TrustedWebActivityDisplayMode}. This can be used e.g. to enable immersive mode
     * (see {@link TrustedWebActivityDisplayMode.ImmersiveMode}. Not setting it means
     * {@link TrustedWebActivityDisplayMode.DefaultMode} will be used.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setDisplayMode(
            @NonNull TrustedWebActivityDisplayMode displayMode) {
        mDisplayMode = displayMode;
        return this;
    }

    /**
     * Sets a screenOrientation. This can be used e.g. to enable the locking of an orientation
     * lock type {@link ScreenOrientation}.
     *
     * @param orientation A {@link ScreenOrientation} lock type for a Trusted Web Activity.
     *                    Not setting it means {@link ScreenOrientation#DEFAULT} will be used.
     */
    @NonNull
    public TrustedWebActivityIntentBuilder setScreenOrientation(
            @ScreenOrientation.LockType int orientation) {
        mScreenOrientation = orientation;
        return this;
    }

    /**
     * Builds an instance of {@link TrustedWebActivityIntent].
     *
     * @param session The {@link CustomTabsSession} to use for launching a Trusted Web Activity.
     */
    @NonNull
    public TrustedWebActivityIntent build(@NonNull CustomTabsSession session) {
        if (session == null) {
            throw new NullPointerException("CustomTabsSession is required for launching a TWA");
        }

        mIntentBuilder.setSession(session);
        Intent intent = mIntentBuilder.build().intent;
        intent.setData(mUri);
        intent.putExtra(TrustedWebUtils.EXTRA_LAUNCH_AS_TRUSTED_WEB_ACTIVITY, true);
        if (mAdditionalTrustedOrigins != null) {
            intent.putExtra(EXTRA_ADDITIONAL_TRUSTED_ORIGINS,
                    new ArrayList<>(mAdditionalTrustedOrigins));
        }

        if (mSplashScreenParams != null) {
            intent.putExtra(EXTRA_SPLASH_SCREEN_PARAMS, mSplashScreenParams);
        }
        List<Uri> sharedUris = Collections.emptyList();
        if (mShareTarget != null && mShareData != null) {
            intent.putExtra(EXTRA_SHARE_TARGET, mShareTarget.toBundle());
            intent.putExtra(EXTRA_SHARE_DATA, mShareData.toBundle());
            if (mShareData.uris != null) {
                sharedUris = mShareData.uris;
            }
        }
        intent.putExtra(EXTRA_DISPLAY_MODE, mDisplayMode.toBundle());
        intent.putExtra(EXTRA_SCREEN_ORIENTATION, mScreenOrientation);
        return new TrustedWebActivityIntent(intent, sharedUris);
    }

    /**
     * Builds a {@link CustomTabsIntent} based on provided parameters.
     * Can be useful for falling back to Custom Tabs when Trusted Web Activity providers are
     * unavailable.
     */
    @NonNull
    public CustomTabsIntent buildCustomTabsIntent() {
        return mIntentBuilder.build();
    }

    /**
     * Returns the {@link Uri} to be launched with this Builder.
     */
    @NonNull
    public Uri getUri() {
        return mUri;
    }

    /**
     * Returns {@link TrustedWebActivityDisplayMode} set on this Builder.
     */
    @NonNull
    public TrustedWebActivityDisplayMode getDisplayMode() {
        return mDisplayMode;
    }
}
