package mobos.leoss.si.qsystemmobileapp.Interceptors;


import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Button;

import java.io.IOException;
import java.text.MessageFormat;

import mobos.leoss.si.qsystemmobileapp.R;
import mobos.leoss.si.qsystemmobileapp.interfaces.InterceptorEventsInterface;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by janez on 30.5.2016.
 */

public class RequestInterceptor implements Interceptor {
    private static final String TAG = "WMS Interceptor";
    ProgressDialog mPdWaiting;
    ProgressDialog mPdConnectionLost;
    private boolean actionCanceled;
    InterceptorEventsInterface successNotifier;
    Boolean showErrorDetails = false;
    int tryCount = 0;
    Activity mActivity;

    public RequestInterceptor(Activity activityOfInterceptor) {
        mActivity = activityOfInterceptor;
        successNotifier = new InterceptorEventsInterface() {
            @Override
            public void onStart() {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
                                && (mActivity == null || mActivity.isDestroyed())) {
                            Log.i(TAG, "onStart: Activity is destroyed");
                            return;
                        }
                        if (mActivity != null) {
                            mPdWaiting = new ProgressDialog(mActivity, R.style.AppTheme);
                            mPdWaiting.setCancelable(false);
                            mPdWaiting.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
                            mPdWaiting.show();

                            mPdConnectionLost = new ProgressDialog(mActivity);
                            mPdConnectionLost.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                            mPdConnectionLost.setCancelable(true);
                            mPdConnectionLost.setCanceledOnTouchOutside(false);
                            mPdConnectionLost.setTitle("Kontaktiram strežnik...");
                            mPdConnectionLost.setIcon(android.R.drawable.ic_dialog_info);
                            //Definicija event za klik se naredi po klicu show-a, zato da positive button ne zapira progressdialoga
                            mPdConnectionLost.setButton(DialogInterface.BUTTON_POSITIVE, "Prikaži detajle", (DialogInterface.OnClickListener) null);
                            mPdConnectionLost.setButton(DialogInterface.BUTTON_NEGATIVE, "Prekliči", (dialogInterface, i) -> {
                                actionCanceled = true;
                            });
                        }
                    }
                });
            }

            @Override
            public void onFinish() {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
                                && (mActivity == null || mActivity.isDestroyed())) {
                            Log.i(TAG, "onFinish: Activity is destroyed");
                            return;
                        }
                        if (mPdWaiting != null && mPdWaiting.isShowing()) {
                            try {
                                mPdWaiting.dismiss();
                            } catch (IllegalArgumentException iae) {
                                //CommonFunctions.crashlyticsLog(iae, TAG);
                            }
                        }
                        if (mPdConnectionLost != null && mPdConnectionLost.isShowing()) {
                            try {
                                mPdConnectionLost.dismiss();
                            } catch (IllegalArgumentException iae) {
                                //CommonFunctions.crashlyticsLog(iae, TAG);
                            }
                        }
                    }
                });
            }

            @Override
            public void onFailure(String errorMessage) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
                                && (mActivity == null || mActivity.isDestroyed())) {
                            Log.i(TAG, "onFailure: Activity is destroyed");
                            return;
                        }
                        if (mPdConnectionLost != null) {
                            mPdConnectionLost.setMessage(generateConnectionProblemMessage(errorMessage));

                            if (!mPdConnectionLost.isShowing()) {
                                if (mPdWaiting != null && mPdWaiting.isShowing()) {
                                    mPdWaiting.dismiss();
                                }
                                mPdConnectionLost.show();
                                Button dialogDetails = mPdConnectionLost.getButton(DialogInterface.BUTTON_POSITIVE);
                                dialogDetails.setOnClickListener(view -> {
                                    showErrorDetails = !showErrorDetails;
                                    mPdConnectionLost.setMessage(generateConnectionProblemMessage(errorMessage));
                                    if (showErrorDetails)
                                        mPdConnectionLost.getButton(DialogInterface.BUTTON_POSITIVE).setText("Skrij podrobnosti");
                                    else
                                        mPdConnectionLost.getButton(DialogInterface.BUTTON_POSITIVE).setText("Prikaži podrobnosti");
                                });
                            }
                        }
                    }
                });
            }
        };
    }

    private String generateConnectionProblemMessage(String errorMessage) {
        String message = String.format("%s\n\n%s %s",
                "Trenutno ni mogoče komunicirati s strežnikom",
                "Poskušam ponovno:",
                tryCount);
        if (showErrorDetails) {
            message += MessageFormat.format("\r\n\r\n{0}:\r\n{1}","RAZLOG:", errorMessage);
        }
        return message;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        successNotifier.onStart();

        Request originalRequest = chain.request();
        Request request = originalRequest.newBuilder()
                .method(originalRequest.method(), originalRequest.body())
                .build();

        Response response = null;
        boolean responseOK = false;
        tryCount = 0;

        //request ponavljam dokler ni uspoešno izveden, ali pa ga uporabnik prekine oz. pride do napake na strežniku
        while ((!responseOK && !actionCanceled)) {
            try {
                response = chain.proceed(request);
                responseOK = response.isSuccessful();
            } catch (Exception ignored) {
            } finally {
                if ((!responseOK) && (response != null)) {
                    //region BUSINESS LOGIC EXCEPTIONS
                    if (response.code() == 500) { //500 = InternalServerError pomeni, da ne ponavljamo zahteve - to so BusinessLogicException-i, ki jih meče strežnik
                        successNotifier.onFinish();
                        return response;
                    }
                    //endregion BUSINESS LOGIC EXCEPTIONS

                    //region OSTALE NAPAKE STREŽNIKA
                    //Če strežnik ni dosegljiv, ali pa je naredil običajen Exception se request ponavlja dokler ne pritisnemo cancel
                    successNotifier.onFailure(response.code() + " " + response.message());
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    chain.request(); //po sleepu še enkrat poizkusim pognati request na strežnik
                    tryCount++;
                    //endregion OSTALE NAPAKE STREŽNIKA
                } else {
                    //V primeru, da je response null, to pomeni, da ni networka oz. se server ne odziva. Zato poizvedbo ukinem takoj
                    if (response == null) {
                        successNotifier.onFinish();
                        throw new IOException("Omrežje ni na voljo.");
                    }
                }
            }
        }

        //Poskrijem progress dialoge in vrnem rezultat, ki je lahko pozitiven odgovor strežnika,
        //lahko pa je tudi običajen Exception, ki ga nismo zajeli v BusinessLogic napake - poparsam jih kasneje
        successNotifier.onFinish();

        // otherwise just pass the original response on
        return response;
    }
}
