package it.integry.integrywmsnative.core.rest.consumers;

import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Singleton;

import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.EntityBase;
import it.integry.integrywmsnative.core.rest.RESTBuilder;
import it.integry.integrywmsnative.core.rest.model.EsitoType;
import it.integry.integrywmsnative.core.rest.model.ServiceRESTResponse;
import it.integry.integrywmsnative.core.utility.UtilityGson;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

@Singleton
public class EntityRESTConsumer extends _BaseRESTConsumer {


    public <T extends EntityBase> void processEntity(T entityToSave, final ISimpleOperationCallback<T> callback, Class<T> type) {

        RunnableArgs<Exception> tmpFailed = ex -> {
            if (callback != null) callback.onFailed(ex);
        };

        EntityRESTConsumerService service = RESTBuilder.getService(EntityRESTConsumerService.class);
        service
                .processEntity(entityToSave)
                .enqueue(new Callback<>() {
                    @Override
                    public void onResponse(Call<ServiceRESTResponse<JsonObject>> call, Response<ServiceRESTResponse<JsonObject>> response) {
                        if (response.isSuccessful()) {

                            if (response.body() != null) {
                                if (response.body().getEsito() == EsitoType.OK) {
                                    Gson gson = new Gson();
                                    T object = gson.fromJson(response.body().getEntity(), type);

                                    callback.onSuccess(object);
                                } else {
                                    Log.e("EntityRESTConsumer", response.body().getErrorMessage());
                                    tmpFailed.run(new Exception(response.body().getErrorMessage()));
                                }
                            } else {
                                Log.e("EntityRESTConsumer", response.message());
                                tmpFailed.run(new Exception(response.message()));
                            }
                        } else {
                            Log.e("EntityRESTConsumer", "Status " + response.code() + ": " + response.message());
                            tmpFailed.run(new Exception("Status " + response.code() + ": " + response.message()));
                        }
                    }

                    @Override
                    public void onFailure(Call<ServiceRESTResponse<JsonObject>> call, Throwable t) {
                        Log.e("EntityRESTConsumer", t.toString());
                        tmpFailed.run(new Exception(t));
                    }
                });

    }

    public <T extends EntityBase> void processEntityList(List<T> entitiesToSave, boolean singleTransaction, Class<T> type, final RunnableArgs<List<T>> onComplete, final RunnableArgs<Exception> onFailed) {

        RunnableArgs<Exception> tmpFailed = ex -> {
//            UtilityExceptions.defaultException(null, ex);
            if (onFailed != null) onFailed.run(ex);
        };

        EntityRESTConsumerService service = RESTBuilder.getService(EntityRESTConsumerService.class);
        Call<List<ServiceRESTResponse<JsonObject>>> request = service.processEntityList(singleTransaction, entitiesToSave);
        request.enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<List<ServiceRESTResponse<JsonObject>>> call, Response<List<ServiceRESTResponse<JsonObject>>> response) {
                if (response.isSuccessful()) {

                    if (response.body() != null) {

                        ArrayList<T> responseList = new ArrayList<>();
                        Gson gson = UtilityGson.createObject();
//                        Type typeOfObjectsList = new TypeToken<T>() {}.getType();

                        for (ServiceRESTResponse<JsonObject> jsonSingleObject : response.body()) {

                            if (jsonSingleObject.getEsito() == EsitoType.OK) {
                                String jsonText = gson.toJson(jsonSingleObject.getEntity());
                                responseList.add(gson.fromJson(jsonText, type));
                            } else {
                                Log.e("EntityRESTConsumer", jsonSingleObject.getErrorMessage());
                                tmpFailed.run(new Exception(jsonSingleObject.getErrorMessage()));

                                return;
                            }
                        }

                        onComplete.run(responseList);
                    } else {
                        Log.e("EntityRESTConsumer", response.message());
                        tmpFailed.run(new Exception(response.message()));
                    }
                } else {
                    Log.e("EntityRESTConsumer", "Status " + response.code() + ": " + response.message());
                    tmpFailed.run(new Exception("Status " + response.code() + ": " + response.message()));
                }
            }

            @Override
            public void onFailure(Call<List<ServiceRESTResponse<JsonObject>>> call, Throwable t) {
                Log.e("EntityRESTConsumer", t.toString());
                tmpFailed.run(new Exception(t));
            }
        });

    }


    @Deprecated
    public <T extends EntityBase> void selectEntity(T entityToSave, final ISimpleOperationCallback<List<T>> callback, Class type) {

        EntityRESTConsumerService service = RESTBuilder.getService(EntityRESTConsumerService.class);
        Call<ServiceRESTResponse<JsonObject>> request = service.processEntity(entityToSave);
        request.enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<JsonObject>> call, Response<ServiceRESTResponse<JsonObject>> response) {
                if (response.isSuccessful()) {

                    if (response.body() != null) {
                        if (response.body().getEsito() == EsitoType.OK) {
                            Gson gson = new Gson();
                            List<JsonObject> jsons = response.body().getEntityList();

                            List<T> newList = new ArrayList<T>();

                            if (jsons != null) {
                                for (int i = 0; i < jsons.size(); i++) {
                                    JsonObject jsonTmp = jsons.get(i);

                                    newList.add((T) gson.fromJson(jsonTmp, type));
                                }
                            }


                            callback.onSuccess(newList);
                        } else {
                            Log.e("EntityRESTConsumer", response.body().getErrorMessage());
                            callback.onFailed(new Exception(response.body().getErrorMessage()));
                        }
                    } else {
                        Log.e("EntityRESTConsumer", response.message());
                        callback.onFailed(new Exception(response.message()));
                    }
                } else {
                    Log.e("EntityRESTConsumer", "Status " + response.code() + ": " + response.message());
                    callback.onFailed(new Exception("Status " + response.code() + ": " + response.message()));
                }
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<JsonObject>> call, Throwable t) {
                Log.e("EntityRESTConsumer", t.toString());
                callback.onFailed(new Exception(t));
            }
        });

    }

}
