package ch.threema.app.dialogs;

import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.telephony.PhoneNumberFormattingTextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;

import org.slf4j.Logger;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Optional;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LifecycleOwner;

import ch.threema.android.LifecycleAwareAsyncTask;
import ch.threema.app.R;
import ch.threema.app.emojis.EmojiEditText;
import ch.threema.app.managers.ServiceManager;
import ch.threema.app.services.LocaleService;
import ch.threema.app.threemasafe.ThreemaSafeService;
import ch.threema.app.ui.SelectorDialogItem;
import ch.threema.app.ui.interop.TextButtonPrimaryXml;
import ch.threema.app.utils.DialogUtil;

import static ch.threema.base.utils.LoggingKt.getThreemaLogger;

import static ch.threema.app.utils.ActiveScreenLoggerKt.logScreenVisibility;

public class WizardSafeSearchPhoneDialog extends DialogFragment implements SelectorDialog.SelectorDialogClickListener {
    private static final Logger logger = getThreemaLogger("WizardSafeSearchPhoneDialog");

    private static final String DIALOG_TAG_PROGRESS = "pro";
    private static final String DIALOG_TAG_SELECT_ID = "se";

    private WizardSafeSearchPhoneDialogCallback callback;
    private Activity activity;
    private ThreemaSafeService threemaSafeService;
    private LocaleService localeService;

    private EditText emailEditText, phoneEditText;

    private ArrayList<SelectorDialogItem> matchingIDs;

    @NonNull
    public static WizardSafeSearchPhoneDialog newInstance() {
        return new WizardSafeSearchPhoneDialog();
    }

    public interface WizardSafeSearchPhoneDialogCallback {
        void onYes(String tag, String id);

        void onNo(String tag);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        logScreenVisibility(this, logger);

        try {
            callback = (WizardSafeSearchPhoneDialogCallback) getTargetFragment();
        } catch (ClassCastException e) {
            //
        }

        // called from an activity rather than a fragment
        if (callback == null) {
            if (!(activity instanceof WizardSafeSearchPhoneDialogCallback)) {
                throw new ClassCastException("Calling fragment must implement WizardSafeSearchPhoneDialogCallback interface");
            }
            callback = (WizardSafeSearchPhoneDialogCallback) activity;
        }
    }

    @Override
    public void onAttach(@NonNull Activity activity) {
        super.onAttach(activity);

        this.activity = activity;
    }

    @NonNull
    @Override
    public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
        final String tag = this.getTag();

        final View dialogView = activity.getLayoutInflater().inflate(R.layout.dialog_wizard_safe_search_phone, null);

        phoneEditText = dialogView.findViewById(R.id.safe_phone);
        emailEditText = dialogView.findViewById(R.id.safe_email);

        MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
        builder.setView(dialogView);

        try {
            var serviceManager = ServiceManager.require();
            threemaSafeService = serviceManager.getThreemaSafeService();
            localeService = serviceManager.getLocaleService();
        } catch (Exception e) {
            dismiss();
        }

        final @NonNull TextButtonPrimaryXml positiveButtonCompose = dialogView.findViewById(R.id.ok_compose);
        final @NonNull TextButtonPrimaryXml negativeButtonCompose = dialogView.findViewById(R.id.cancel_compose);

        final AlertDialog dialog = builder.create();

        positiveButtonCompose.setOnClickListener(v -> {
            String phone = null, email = null;
            if (phoneEditText.getText() != null) {
                phone = localeService.getNormalizedPhoneNumber(phoneEditText.getText().toString());
            }
            if (emailEditText.getText() != null) {
                email = emailEditText.getText().toString();
            }
            if (phone != null || email != null) {
                searchID(dialog, phone, email);
            } else {
                dismiss();
                callback.onYes(tag, null);
            }
        });

        negativeButtonCompose.setOnClickListener(v -> {
            dismiss();
            callback.onNo(tag);
        });

        phoneEditText.addTextChangedListener(new PhoneNumberFormattingTextWatcher(localeService.getCountryIsoCode()));

        setCancelable(false);

        return dialog;
    }

    private void searchID(LifecycleOwner lifecycleOwner, String phone, String email) {
        new SearchIdTask(this).execute(lifecycleOwner, new String[]{phone, email});
    }

    @Override
    public void onCancel(@NonNull DialogInterface dialogInterface) {
        callback.onNo(this.getTag());
    }

    private static class SearchIdTask extends LifecycleAwareAsyncTask<String[], ArrayList<String>> {
        private final WeakReference<WizardSafeSearchPhoneDialog> dialogReference;

        SearchIdTask(WizardSafeSearchPhoneDialog dialog) {
            dialogReference = new WeakReference<>(dialog);
        }

        @Override
        protected void onPreExecute() {
            WizardSafeSearchPhoneDialog dialog = dialogReference.get();
            if (dialog == null || dialog.isRemoving() || dialog.isDetached()) return;

            GenericProgressDialog.newInstance(R.string.safe_id_lookup, R.string.please_wait).show(dialog.getFragmentManager(), DIALOG_TAG_PROGRESS);
        }

        @Override
        protected ArrayList<String> doInBackground(String[] params) {
            return dialogReference.get().threemaSafeService.searchID(params[0], params[1]);
        }

        @Override
        protected void onPostExecute(ArrayList<String> ids) {
            final WizardSafeSearchPhoneDialog dialog = dialogReference.get();
            if (dialog == null || dialog.isRemoving() || dialog.isDetached()) return;

            DialogUtil.dismissDialog(dialog.getFragmentManager(), DIALOG_TAG_PROGRESS, true);
            if (ids != null) {
                ArrayList<SelectorDialogItem> selectorItems = new ArrayList<>();
                for (String id : ids) {
                    selectorItems.add(new SelectorDialogItem(id, R.drawable.ic_person_outline));
                }

                dialog.matchingIDs = selectorItems;

                if (ids.size() == 1) {
                    dialog.callback.onYes(dialog.getTag(), ids.get(0));
                    dialog.dismiss();
                } else {
                    SelectorDialog selectorDialog = SelectorDialog.newInstance(
                        dialog.getString(R.string.safe_select_id),
                        selectorItems,
                        null,
                        (String) null
                    );
                    selectorDialog.setTargetFragment(dialog, 0);
                    selectorDialog.show(dialog.getFragmentManager(), DIALOG_TAG_SELECT_ID);
                }
            } else {
                Optional.ofNullable(dialog)
                    .map(Fragment::getActivity)
                    .ifPresent(activity -> Toast.makeText(activity, R.string.safe_no_id_found, Toast.LENGTH_LONG).show());
            }
        }
    }

    /*
     * Selector callbacks
     */

    @Override
    public void onClick(String tag, int which, Object data) {
        callback.onYes(getTag(), matchingIDs.get(which).getText());
        dismiss();
    }
}
