// 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.signin;

import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.IntDef;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
import org.chromium.chrome.browser.widget.RadioButtonWithDescription;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;

/**
 * A dialog that is displayed when the user switches the account they are syncing to. It gives the
 * option to merge the data of the two accounts or to keep them separate.
 */
public class ConfirmImportSyncDataDialog extends DialogFragment
        implements DialogInterface.OnClickListener {

    /**
     * Callback for completion of the dialog. Only one of {@link Listener#onConfirm} or
     * {@link Listener#onCancel} will be called and it will only be called once.
     */
    public interface Listener {
        /**
         * The user has completed the dialog using the positive button.
         * @param wipeData Whether the user requested that existing data should be wiped.
         */
        void onConfirm(boolean wipeData);

        /**
         * The user dismisses the dialog through any means other than the positive button.
         */
        void onCancel();
    }

    /**
     * The situation ConfirmImportSyncDataDialog is created for - whether the user had previously
     * been signed into another account, had signed out then signed into a different one, or
     * if they directly switched accounts. This changes the strings displayed.
     */
    @IntDef({ImportSyncType.SWITCHING_SYNC_ACCOUNTS, ImportSyncType.PREVIOUS_DATA_FOUND})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ImportSyncType {
        int SWITCHING_SYNC_ACCOUNTS = 0;
        int PREVIOUS_DATA_FOUND = 1;
    }

    @VisibleForTesting
    public static final String CONFIRM_IMPORT_SYNC_DATA_DIALOG_TAG =
            "sync_account_switch_import_data_tag";

    private static final String KEY_OLD_ACCOUNT_NAME = "lastAccountName";
    private static final String KEY_NEW_ACCOUNT_NAME = "newAccountName";
    private static final String KEY_IMPORT_SYNC_TYPE = "importSyncType";

    private RadioButtonWithDescription mConfirmImportOption;
    private RadioButtonWithDescription mKeepSeparateOption;

    private Listener mListener;
    private boolean mListenerCalled;

    private static ConfirmImportSyncDataDialog newInstance(
            String oldAccountName, String newAccountName, @ImportSyncType int importSyncType) {
        ConfirmImportSyncDataDialog fragment = new ConfirmImportSyncDataDialog();
        Bundle args = new Bundle();
        args.putString(KEY_OLD_ACCOUNT_NAME, oldAccountName);
        args.putString(KEY_NEW_ACCOUNT_NAME, newAccountName);
        args.putInt(KEY_IMPORT_SYNC_TYPE, importSyncType);
        fragment.setArguments(args);
        return fragment;
    }

    /**
     * Creates and shows a new instance of ConfirmImportSyncDataFragment, a dialog that gives the
     * user the option to merge data between the account they are attempting to sign in to and the
     * account they were previously signed into, or to keep the data separate.
     * @param oldAccountName  The previous sync account name.
     * @param newAccountName  The potential next sync account name.
     * @param importSyncType  The situation the dialog is created in - either when directly changing
     *                        the sync account or signing in after being signed out (this changes
     *                        displayed strings).
     * @param fragmentManager FragmentManager to attach the dialog to.
     * @param callback        Callback to be called if the user completes the dialog (as opposed to
     *                        hitting cancel).
     */
    public static void showNewInstance(String oldAccountName, String newAccountName,
            @ImportSyncType int importSyncType, FragmentManager fragmentManager,
            Listener callback) {
        ConfirmImportSyncDataDialog confirmSync =
                newInstance(oldAccountName, newAccountName, importSyncType);

        confirmSync.setListener(callback);
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(confirmSync, CONFIRM_IMPORT_SYNC_DATA_DIALOG_TAG);
        transaction.commitAllowingStateLoss();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // If the dialog is being recreated it won't have the listener set and so won't be
        // functional. Therefore we dismiss, and the user will need to open the dialog again.
        if (savedInstanceState != null) {
            dismiss();
        }
        String oldAccountName = getArguments().getString(KEY_OLD_ACCOUNT_NAME);
        String newAccountName = getArguments().getString(KEY_NEW_ACCOUNT_NAME);
        @ImportSyncType
        int importSyncType = getArguments().getInt(KEY_IMPORT_SYNC_TYPE);

        LayoutInflater inflater = getActivity().getLayoutInflater();
        View v = inflater.inflate(R.layout.confirm_import_sync_data, null);

        TextView prompt = v.findViewById(R.id.sync_import_data_prompt);
        prompt.setText(getActivity().getString(R.string.sync_import_data_prompt, oldAccountName));

        mConfirmImportOption = v.findViewById(R.id.sync_confirm_import_choice);
        mKeepSeparateOption = v.findViewById(R.id.sync_keep_separate_choice);

        mConfirmImportOption.setDescriptionText(getActivity().getString(
                R.string.sync_import_existing_data_subtext, newAccountName));
        if (importSyncType == ImportSyncType.SWITCHING_SYNC_ACCOUNTS) {
            mKeepSeparateOption.setDescriptionText(getActivity().getString(
                    R.string.sync_keep_existing_data_separate_subtext_switching_accounts,
                    oldAccountName));
        } else {
            mKeepSeparateOption.setDescriptionText(getActivity().getString(
                    R.string.sync_keep_existing_data_separate_subtext_existing_data));
        }

        List<RadioButtonWithDescription> radioGroup =
                Arrays.asList(mConfirmImportOption, mKeepSeparateOption);
        mConfirmImportOption.setRadioButtonGroup(radioGroup);
        mKeepSeparateOption.setRadioButtonGroup(radioGroup);

        // If the account is managed, disallow merging information.
        if (SigninManager.get().getManagementDomain() != null) {
            mKeepSeparateOption.setChecked(true);
            mConfirmImportOption.setOnClickListener(
                    view -> ManagedPreferencesUtils.showManagedByAdministratorToast(getActivity()));
        } else {
            if (importSyncType == ImportSyncType.SWITCHING_SYNC_ACCOUNTS) {
                mKeepSeparateOption.setChecked(true);
            } else {
                mConfirmImportOption.setChecked(true);
            }
        }

        if (importSyncType == ImportSyncType.SWITCHING_SYNC_ACCOUNTS) {
            // Re-order the buttons so that Import Data is last and Don't Import (the default) is
            // at the top.
            LinearLayout layout = v.findViewById(R.id.sync_import_data_content);
            layout.removeView(mConfirmImportOption);
            layout.addView(mConfirmImportOption);
        }

        return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog)
                .setPositiveButton(R.string.continue_button, this)
                .setNegativeButton(R.string.cancel, this)
                .setView(v)
                .create();
    }

    private void setListener(Listener listener) {
        assert mListener == null;
        mListener = listener;
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (mListener == null) return;

        if (which == AlertDialog.BUTTON_POSITIVE) {
            assert mConfirmImportOption.isChecked() ^ mKeepSeparateOption.isChecked();

            RecordUserAction.record(mKeepSeparateOption.isChecked()
                    ? "Signin_ImportDataPrompt_DontImport"
                    : "Signin_ImportDataPrompt_ImportData");
            mListener.onConfirm(mKeepSeparateOption.isChecked());
        } else {
            assert which == AlertDialog.BUTTON_NEGATIVE;

            RecordUserAction.record("Signin_ImportDataPrompt_Cancel");
            mListener.onCancel();
        }
        mListenerCalled = true;
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (mListener != null && !mListenerCalled) {
            mListener.onCancel();
        }
    }
}

