package ch.threema.app.dialogs;

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.view.View;
import android.widget.TextView;

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

import org.slf4j.Logger;

import java.text.NumberFormat;

import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentManager;
import ch.threema.app.R;
import static ch.threema.base.utils.LoggingKt.getThreemaLogger;

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

public class CancelableHorizontalProgressDialog extends ThreemaDialogFragment {
    private static final Logger logger = getThreemaLogger("CancelableHorizontalProgressDialog");
    private ProgressDialogClickListener callback;
    private Activity activity;
    private DialogInterface.OnClickListener listener;
    private NumberFormat mProgressPercentFormat;
    private TextView progressPercent;
    private LinearProgressIndicator progressBar;
    private int max;

    /**
     * Creates a DialogFragment with a horizontal progress bar and a percentage display below. Mimics deprecated system ProgressDialog behavior
     *
     * @param title  title of dialog
     * @param button label of cancel button
     * @param total  maximum allowed progress value.
     * @return the dialog
     */
    public static CancelableHorizontalProgressDialog newInstance(@StringRes int title, @StringRes int button, int total) {
        CancelableHorizontalProgressDialog dialog = new CancelableHorizontalProgressDialog();
        Bundle args = new Bundle();
        args.putInt("title", title);
        args.putInt("button", button);
        args.putInt("total", total);

        dialog.setArguments(args);
        return dialog;
    }

    /**
     * Creates a DialogFragment with a horizontal progress bar and a percentage display below.
     * Mimics deprecated system ProgressDialog behavior.
     * Note that when using this constructor, no cancel button is shown.
     *
     * @param title title of dialog
     * @param total maximum allowed progress value.
     * @return the dialog
     */
    public static CancelableHorizontalProgressDialog newInstance(@StringRes int title, int total) {
        CancelableHorizontalProgressDialog dialog = new CancelableHorizontalProgressDialog();
        Bundle args = new Bundle();
        args.putInt("title", title);
        args.putInt("total", total);

        dialog.setArguments(args);
        return dialog;
    }

    /**
     * Creates a DialogFragment with a horizontal progress bar and a percentage display below. Mimics deprecated system ProgressDialog behavior
     *
     * @param title  title of dialog
     * @param button label of cancel button
     * @param total  maximum allowed progress value.
     * @return the dialog
     */
    public static CancelableHorizontalProgressDialog newInstance(@NonNull String title, @NonNull String button, int total) {
        CancelableHorizontalProgressDialog dialog = new CancelableHorizontalProgressDialog();
        Bundle args = new Bundle();
        args.putString("title", title);
        args.putString("button", button);
        args.putInt("total", total);

        dialog.setArguments(args);
        return dialog;
    }

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

        this.mProgressPercentFormat = NumberFormat.getPercentInstance();
        this.mProgressPercentFormat.setMaximumFractionDigits(0);

        if (callback == null) {
            try {
                callback = (ProgressDialogClickListener) getTargetFragment();
            } catch (ClassCastException e) {
                //
            }
        }

        // called from an activity rather than a fragment
        if (callback == null) {
            if ((activity instanceof ProgressDialogClickListener)) {
                callback = (ProgressDialogClickListener) activity;
            }
        }
    }

    /**
     * Set a listener to be attached to the cancel button. Do not use, implement {@link ProgressDialogClickListener} listener on the calling activity/fragment instead!
     */
    @Deprecated
    public void setOnCancelListener(DialogInterface.OnClickListener onClickListener) {
        this.listener = onClickListener;
    }

    public interface ProgressDialogClickListener {
        default void onCancel(String tag, Object object) {

        }
    }

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

        this.activity = activity;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        int titleRes = getArguments().getInt("title");
        int button = getArguments().getInt("button");
        int total = getArguments().getInt("total", 0);
        String titleString = getArguments().getString("title");
        String buttonString = getArguments().getString("button");

        final String tag = this.getTag();

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

        progressBar = dialogView.findViewById(R.id.progress);
        progressPercent = dialogView.findViewById(R.id.progress_percent);

        MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getActivity(), getTheme()).setCancelable(false);
        builder.setView(dialogView);

        if (titleRes != 0) {
            builder.setTitle(titleRes);
        } else if (titleString != null) {
            builder.setTitle(titleString);
        }

        max = total;
        if (max == 0) {
            max = 100;
        }
        progressBar.setMax(max);
        setProgress(0);

        DialogInterface.OnClickListener onClickListener = (dialog, which) -> {
            if (listener != null) {
                listener.onClick(dialog, which);
            }
            if (callback != null) {
                callback.onCancel(tag, object);
            }
        };

        if (button != 0) {
            builder.setPositiveButton(getString(button), onClickListener);
        } else if (buttonString != null) {
            builder.setPositiveButton(buttonString, onClickListener);
        }

        AlertDialog progressDialog = builder.create();

        setCancelable(false);

        return progressDialog;
    }

    /**
     * Updates progress bar. Do not call this directly, use {@link ch.threema.app.utils.DialogUtil#updateProgress(FragmentManager, String, int)} instead!
     */
    @UiThread
    public void setProgress(int progress) {
        if (progressBar != null && progressPercent != null) {
            double percent = (double) progress / (double) max;
            SpannableString tmp = new SpannableString(mProgressPercentFormat.format(percent));
            tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
                0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            progressPercent.setText(tmp);
            progressBar.setProgress(progress);
        }
    }
}
