package it.integry.integrywmsnative.gest.login.viewmodel;

import android.app.ProgressDialog;
import android.content.Intent;
import androidx.appcompat.app.AlertDialog;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import it.integry.integrywmsnative.MainActivity;
import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.REST.consumers.ISimpleOperationCallback;
import it.integry.integrywmsnative.core.REST.consumers.SystemRESTConsumer;
import it.integry.integrywmsnative.core.REST.model.AvailableCodMdepsDTO;
import it.integry.integrywmsnative.core.di.BindableBoolean;
import it.integry.integrywmsnative.core.di.BindableString;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityProgress;
import it.integry.integrywmsnative.core.utility.UtilityServer;
import it.integry.integrywmsnative.gest.login.LoginActivity;
import it.integry.integrywmsnative.gest.login.core.LoginHelper;
import it.integry.integrywmsnative.gest.login.dto.LoginAziendaDTO;
import it.integry.integrywmsnative.gest.login.dto.LoginDTO;
import it.integry.integrywmsnative.view.dialogs.DialogSimpleMessageHelper;

public class LoginViewModel {
    private static final String TAG = LoginViewModel.class.getSimpleName();

    public BindableString username = new BindableString();
    public BindableString password = new BindableString();
    public BindableString codAzienda = new BindableString();

    public BindableBoolean customSettingsCheckboxEnabled = new BindableBoolean();
    public BindableBoolean customSettingsCheckboxChecked = new BindableBoolean();

    public BindableBoolean loginButtonEnabled = new BindableBoolean();


    public BindableString usernameError = new BindableString();
    public BindableString passwordError = new BindableString();
    public BindableString codAziendaError = new BindableString();



    private LoginActivity mActivity;

    private ProgressDialog mProgress;

    public LoginViewModel(LoginActivity activity) {
        this.mActivity = activity;

        loginButtonEnabled.set(true);

        codAzienda.set(SettingsManager.i().server.codAzienda);

        customSettingsCheckboxChecked.set(SettingsManager.i().server.host == null);
        customSettingsCheckboxEnabled.set(SettingsManager.i().server.host != null);
    }



    public boolean validate() {
        if (username.isEmpty() || username.get().length() < 3) {
            usernameError.set(mActivity.getText(R.string.username_error_not_valid).toString());
            return false;
        } else usernameError.set(null);

        if (codAzienda.isEmpty() || codAzienda.get().length() < 3) {
            codAziendaError.set(mActivity.getText(R.string.server_cod_azienda_not_valid).toString());
            return false;
        } else codAziendaError.set(null);

        return true;
    }



    public void login(boolean areValidData){
        if(areValidData){
            loginButtonEnabled.set(false);

            mProgress = ProgressDialog.show(mActivity, mActivity.getText(R.string.waiting),
                    mActivity.getText(R.string.loading) + " ...", true);

            final LoginHelper loginHelper = new LoginHelper(mActivity, codAzienda.get(), username.get(), password.get());

            loginHelper.retrieveServerData(new ISimpleOperationCallback<LoginAziendaDTO>() {

                @Override
                public void onSuccess(LoginAziendaDTO value) {

                    final String serverEndpoint = value.endpointRestApi;

                    URL u;
                    try {
                        u = new URL(serverEndpoint);
                    } catch (final MalformedURLException e) {
                        e.printStackTrace();
                        onLoginFailed(new SpannableString(e.toString()));
                        return;
                    }

                    final String host = u.getHost();
                    final int port = u.getPort();

                    UtilityServer.isHostReachable(host, port, value1 -> {

                        if(value1){ //Is online
                            loginHelper.doLogin(host, port, new ISimpleOperationCallback<LoginDTO>() {
                                @Override
                                public void onSuccess(final LoginDTO loginDTO) {

                                    SettingsManager.iDB().setAvailableProfiles(loginDTO.availableProfiles);
                                    SettingsManager.i().user.fullname = loginDTO.full_name;


                                    mActivity.runOnUiThread(() -> onLoginSuccess(
                                            "Benvenuto",
                                            Html.fromHtml("Ciao <b>" + loginDTO.full_name + "</b>, la Integry le augura di svolgere al meglio il suo lavoro"),
                                            host, port, loginDTO.availableProfiles));


                                }

                                @Override
                                public void onFailed(final Exception ex) {
                                    onLoginFailed(new SpannableString(ex.getMessage()));
                                }
                            });


                        } else { //Is not online
                            onLoginFailed(Html.fromHtml(String.format(mActivity.getText(R.string.server_not_reachable).toString(), host, port)));
                        }

                    });
                }

                @Override
                public void onFailed(Exception ex) {
                    onLoginFailed(Html.fromHtml(String.format(mActivity.getText(R.string.server_cod_azienda_not_valid).toString(), codAzienda.get())));
                }
            });

        }
    }


    private void loadDepo(String host, int port, Runnable onComplete) {

        SettingsManager.i().server.codAzienda = codAzienda.get();
        SettingsManager.i().server.host = host;
        SettingsManager.i().server.port = port;

        SettingsManager.i().user.username = username.get();
        SettingsManager.i().user.password = password.get();

        SystemRESTConsumer.getAvailableCodMdeps(new ISimpleOperationCallback<List<AvailableCodMdepsDTO>>() {
            @Override
            public void onSuccess(List<AvailableCodMdepsDTO> availableCodMdeps) {
                SettingsManager.iDB().setAvailableCodMdep(availableCodMdeps);

                if(availableCodMdeps == null || availableCodMdeps.size() == 0) {
                    onLoginFailed(Html.fromHtml(String.format(mActivity.getText(R.string.no_codmdep_available).toString())));
                    return;
                }

                SettingsManager.i().userSession.depo = availableCodMdeps.get(0);


                if(onComplete != null) onComplete.run();
            }

            @Override
            public void onFailed(Exception ex) {
                //BOH
                onLoginFailed(new SpannableString(ex.getMessage()));
            }
        });
    }


    private void onLoginFailed(final Spanned message){
        mProgress.dismiss();
        loginButtonEnabled.set(true);
        mActivity.runOnUiThread(() -> DialogSimpleMessageHelper.makeErrorDialog(
                mActivity,
                message,
                null,
                null).show());
    }


    private void onLoginSuccess(final String title, final Spanned message, final String host, final int port, final List<String> availableProfiles){
        mProgress.dismiss();
        mActivity.runOnUiThread(() -> DialogSimpleMessageHelper.makeSuccessDialog(
                mActivity,
                title,
                message,
                null,
                () -> showProfileDBSelectionDialog(host, port, availableProfiles)).show());
    }

    private void showProfileDBSelectionDialog(final String host, final int port, final List<String> availableProfiles){
        if(availableProfiles != null && availableProfiles.size() == 1 ) {
            SettingsManager.i().userSession.profileDB = availableProfiles.get(0);

            loadDepo(host, port, this::onLoginCompleted);
        } else {

            // setup the alert builder
            AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
            builder.setTitle(R.string.action_choose_profile_db);

            // add a list
            String[] profiles = new String[availableProfiles.size()];
            profiles = availableProfiles.toArray(profiles);
            builder.setItems(profiles, (dialog, which) -> {
                SettingsManager.i().userSession.profileDB = availableProfiles.get(which);

                loadDepo(host, port, this::onLoginCompleted);
            });

            // create and show the alert dialog
            AlertDialog dialog = builder.create();
            dialog.show();
        }
    }

    public void onLoginCompleted() {
        loginButtonEnabled.set(true);

        SettingsManager.update();

        ProgressDialog loadingProgress = UtilityProgress.createDefaultProgressDialog(mActivity);
        SettingsManager.reloadDBVariables(() -> {
            loadingProgress.dismiss();
                mActivity.finish();

                Intent myIntent = new Intent(mActivity, MainActivity.class);
                mActivity.startActivity(myIntent);

            },ex -> {
            loadingProgress.dismiss();
                DialogSimpleMessageHelper.makeErrorDialog(mActivity,
                    new SpannableString(ex.getMessage()), null, null).show();
            }
        );
    }


}
