package cordova.plugin.netcontroll.integration.stone;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


import android.graphics.Bitmap;
import android.os.AsyncTask;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.izettle.html2bitmap.Html2Bitmap;
import com.izettle.html2bitmap.content.WebViewContent;


// import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import android.app.Activity;
import android.graphics.Bitmap;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import android.net.Uri;
import android.content.Intent;
import android.provider.MediaStore;
import android.os.Build;

import static android.app.Activity.RESULT_OK;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;

import java.util.List;

//Json Serialize
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;


//Bitmap
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;

import android.util.Base64;
import java.io.ByteArrayOutputStream;
import java.util.Objects;
import java.util.stream.Collectors;

//Stone 


import br.com.stone.posandroid.providers.PosMifareProvider;
import stone.providers.ActiveApplicationProvider;
import stone.providers.BaseTransactionProvider;
import stone.providers.CaptureTransactionProvider;
import stone.providers.TransactionProvider;
import stone.providers.CancellationProvider;
import stone.providers.ReversalProvider;

import stone.application.StoneStart;

import stone.application.interfaces.StoneCallbackInterface;
import stone.application.interfaces.StoneActionCallback;

import stone.application.enums.ErrorsEnum;
import stone.application.enums.InstalmentTransactionEnum;
import stone.application.enums.TypeOfTransactionEnum;
import stone.application.enums.Action;
import stone.application.enums.ReceiptType;
import stone.application.enums.TransactionStatusEnum;

import br.com.stone.posandroid.providers.PosPrintProvider;
import br.com.stone.posandroid.providers.PosTransactionProvider;
import br.com.stone.posandroid.providers.PosPrintReceiptProvider;

import stone.database.transaction.TransactionObject;
import stone.database.transaction.TransactionDAO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.common.BitMatrix;


import stone.user.UserModel;
import stone.utils.Stone;
import stone.utils.keys.StoneKeyType;

public class StoneSumni {
    private PosTransactionProvider transactionProvider;

    //Cordova/Java Params
    private Activity mActivity;
    private Context mContext;
    private CordovaWebView webView;


    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        this.webView = webView;
        mActivity = cordova.getActivity();
        mContext = this.webView.getContext();
    }

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("InitializeSdk")) {
            JSONObject params = args.getJSONObject(0);
            try {
                Map<StoneKeyType, String> stoneKeys = new HashMap<StoneKeyType, String>() {{
                    //CREDENCIAIS DE HOMOLOGACAO
                    //put(StoneKeyType.QRCODE_AUTHORIZATION, "0615879c-6c6b-4220-b2de-fbe069f179be");
                    //put(StoneKeyType.QRCODE_PROVIDERID, "413b7c3e-ad75-45b8-a5ba-e5d37a948442");

                    //CREDENCIAIS DE PRODUCAO
                    put(StoneKeyType.QRCODE_AUTHORIZATION, "8894810f-8dec-4190-9656-5806a23d33d6");
                    put(StoneKeyType.QRCODE_PROVIDERID, "d34c4c91-881a-4402-8fdd-a5e76430bbf5");
                }};

                List<UserModel> user = StoneStart.init(this.mContext, stoneKeys);
                Stone.setAppName(params.getString("appName"));

                callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(user));
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - InitializeSdk: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("AtivarStoneCode")) {
            JSONObject params = args.getJSONObject(0);
            try {
                final ActiveApplicationProvider activeApplicationProvider = new ActiveApplicationProvider(this.mContext);
                activeApplicationProvider.setConnectionCallback(new StoneCallbackInterface() {
                    @Override
                    public void onSuccess() {
                        // stoneCodeListView.setAdapter(populateStoneCodeListView());
                        // ((ArrayAdapter) stoneCodeListView.getAdapter()).notifyDataSetChanged();
                        // Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_LONG).show();
                        // callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(order));
                        callbackContext.success("Stone - Sumni - AtivarStoneCode - onSuccess");
                    }

                    @Override
                    public void onError() {
                        // Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG).show();
                        // Log.e("ManageStoneCodeActivity", "onError: " + activeApplicationProvider.getListOfErrors());
                        List<ErrorsEnum>  errors =  activeApplicationProvider.getListOfErrors();
                        callbackContext.error("onError :" + errors.toString());
                    }
                });
                activeApplicationProvider.activate(params.getString("stoneCode"));
                // callbackContext.success("AtivarStoneCode");
                // callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(user));
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - AtivarStoneCode: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("DesativarStoneCode")) {
            JSONObject params = args.getJSONObject(0);
            try {
                final ActiveApplicationProvider activeApplicationProvider = new ActiveApplicationProvider(this.mContext);
                activeApplicationProvider.setConnectionCallback(new StoneCallbackInterface() {
                    @Override
                    public void onSuccess() {
                        callbackContext.success("Stone - Sumni - DesativarStoneCode - onSuccess");
                    }

                    @Override
                    public void onError() {
                        List<ErrorsEnum>  errors =  activeApplicationProvider.getListOfErrors();
                        callbackContext.error("onError :" + errors.toString());
                    }
                });
                activeApplicationProvider.deactivate(params.getString("stoneCode"));
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - DesativarStoneCode: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("IniciarTransacao")) {
            JSONObject params = args.getJSONObject(0);
            try {
                String parcelas = params.getString("parcelas");
                String tipoTransacao = params.getString("tipoTransacao");
                String valor = params.getString("valor");
                String statusChangeCallBack = params.getString("statusChangeCallBack");

                final TransactionObject transactionObject = new TransactionObject();

                if (parcelas != "") {
                    transactionObject.setInstalmentTransaction(GetInstalmentTransactionEnumByName(parcelas));
                }
                //transactionObject.setCapture(false);
                //"ServiceRefererName": "623b21c77dbc9c0019c5f906"
                transactionObject.setInitiatorTransactionKey(null);
                transactionObject.setTypeOfTransaction(GetTransactionTypeEnumByName(tipoTransacao));

                transactionObject.setAmount(valor);

                transactionProvider = new PosTransactionProvider(this.mContext, transactionObject, GetSelectedUserModel(0));
                transactionProvider.useDefaultUI(true);
                transactionProvider.setDialogTitle("Aguarde"); // Título do Dialog
                transactionProvider.setDialogMessage("Enviando..."); // Mensagem do Dialog
                transactionProvider.setConnectionCallback(new StoneActionCallback() {
                    @Override
                    public void onSuccess() {
                        mActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                String transactionStatus = transactionObject.getTransactionStatus().toString();
                                executeGlobalJavascript(statusChangeCallBack + "('" + transactionStatus + "')");
                            }
                        });


                        if ((transactionProvider.getTransactionStatus().toString() == "UNKNOWN")
                                || (transactionProvider.getTransactionStatus().toString() == "DECLINED")
                                || (transactionProvider.getTransactionStatus().toString() == "DECLINED_BY_CARD")
                                || (transactionProvider.getTransactionStatus().toString() == "TECHNICAL_ERROR")
                                || (transactionProvider.getTransactionStatus().toString() == "REJECTED")
                                || (transactionProvider.getTransactionStatus().toString() == "WITH_ERROR")
                                || (transactionProvider.getTransactionStatus().toString() == "REVERSED")
                                || (transactionProvider.getTransactionStatus().toString() == "PENDING_REVERSAL")) {
                            String msg = "Erro na transação";
                            if (transactionProvider.getMessageFromAuthorize() != null) {
                                msg += ": " + transactionProvider.getMessageFromAuthorize();
                            } else {
                                msg += "!";
                            }
                            callbackContext.error(msg);
                            return;
                        }

                        if(transactionObject.getTypeOfTransaction().toString() == "PIX"){
                            Gson gson = new Gson();
                            String transactionObjectJSON = gson.toJson(transactionObject);
                            JsonObject transactionObjectCopy = gson.fromJson(transactionObjectJSON, JsonObject.class);
                            transactionObjectCopy.remove("qrcode");
                            callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(transactionObjectCopy));
                        } else {
                            callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(transactionObject));
                        }
                        // if (transactionObject.getTransactionStatus() == TransactionStatusEnum.APPROVED) {
                        //     callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(transactionObject));
                        // } else {
                        //     String msg = "Erro na transação";
                        //     if (transactionProvider.getMessageFromAuthorize() != null) {
                        //         msg += ":" + transactionProvider.getMessageFromAuthorize();
                        //     } else {
                        //         msg += "!";
                        //     }
                        //     callbackContext.error(msg);
                        // }
                    }

                    @Override
                    public void onError() {
                        // Erro na transação
                        callbackContext.error(transactionProvider.getListOfErrors().toString());
                    }

                    @Override
                    public void onStatusChanged(Action action) {
                        Object teste3 = action;
                        mActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                switch (action.name()){
                                    case "TRANSACTION_TYPE_SELECTION":
                                        List<String> options = transactionProvider.getTransactionTypeOptions();
                                        StringBuilder result = new StringBuilder();

                                        for (int i = 0; i < options.size(); i++) {
                                            result.append(options.get(i).trim());
                                            if (i < options.size() - 1) {
                                                result.append("|");
                                            }
                                        }
                                        String finalResult = result.toString();
                                        executeGlobalJavascript(statusChangeCallBack + "('" + action.name() + "|" + finalResult + "')");
                                        break;

                                    case "TRANSACTION_WAITING_QRCODE_SCAN":
                                        //PosPrintProvider customPosPrintProvider = new PosPrintProvider(mContext);
                                        Bitmap QRCode = Bitmap.createScaledBitmap(transactionObject.getQRCode(), 400, 400, true);
                                        //customPosPrintProvider.addBitmap(QRCode);
                                        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                                        QRCode.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
                                        byte[] byteArray = byteArrayOutputStream.toByteArray();
                                        String QrEncoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
                                        //customPosPrintProvider.execute();
                                        executeGlobalJavascript(statusChangeCallBack + "('" + action.name() + "|" + QrEncoded + "')");
                                        break;

                                    default:
                                        executeGlobalJavascript(statusChangeCallBack + "('" + action.name() + "')");
                                        break;
                                }


                                /* if (action.name() == "TRANSACTION_TYPE_SELECTION") {
                                    List<String> options = transactionProvider.getTransactionTypeOptions();
                                    StringBuilder result = new StringBuilder();

                                    for (int i = 0; i < options.size(); i++) {
                                        result.append(options.get(i).trim());
                                        if (i < options.size() - 1) {
                                            result.append("|");
                                        }
                                    }
                                    String finalResult = result.toString();
                                    executeGlobalJavascript(statusChangeCallBack + "('" + action.name() + "|" + finalResult + "')");
                                } else{
                                    executeGlobalJavascript(statusChangeCallBack + "('" + action.name() + "')");
                                }
                                 */
                            }
                        });
                    }
                });
                new Thread(() -> {
                    transactionProvider.execute();
                }).start();
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - IniciarTransacao: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("DefinirTipoMultibeneficios")) {
            JSONObject params = args.getJSONObject(0);
            try {
                Integer tipo = params.getInt("tipo");
                transactionProvider.setTransactionTypeSelected(tipo);
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - DefinirTipoMultibeneficios: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("CapturarTransacao")) {
            JSONObject params = args.getJSONObject(0);
            try {
                String transactionObjectStr = params.getString("transactionObject");
                TransactionObject transactionObject = cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseJsonStringToObj(transactionObjectStr,TransactionObject.class);
                if (transactionObject.isCapture()) {
                    callbackContext.error("Esta transação já foi capturada");
                    return false;
                }
                final CaptureTransactionProvider captureProvider = new CaptureTransactionProvider(this.mContext, transactionObject);
                captureProvider.setDialogMessage("Efetuando Captura...");
                captureProvider.setConnectionCallback(new StoneCallbackInterface() {
                    @Override
                    public void onSuccess() {
                        switch (captureProvider.getResponseCodeEnum()) {
                            case Approved:
                                callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(captureProvider.getTransactionObject()));
                                break;
//                            case Declined:
//                                callbackContext.error(captureProvider.getMessageFromAuthorize());
//                                break;
//                            case TechnicalError:
//                                callbackContext.error(captureProvider.getMessageFromAuthorize());
//                                break;
                            case Default:
                                callbackContext.error(captureProvider.getListOfErrors().toString());
                                break;
                        }
                    }
                    @Override
                    public void onError() {
                        callbackContext.error(captureProvider.getListOfErrors().toString());
                    }
                });
                captureProvider.execute();
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - CancelarTransacao: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("AbortarTransacao")) {
            try {
                new Thread(() -> {
                    try {
                        transactionProvider.abortPayment();
                        callbackContext.success("Stone - Sumni - AbortarTransacao - onSuccess");
                    } catch (Exception e) {
                        callbackContext.error("Result - Stone - Sumni - AbortarTransacao: " + "Error Detail: " + e.toString());
                    }
                }).start();
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - AbortarTransacao: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("ReverterTransacaoComErro")) {
            try {

                ReversalProvider reversalProvider = new ReversalProvider(this.mContext);
                reversalProvider.setDialogMessage("Cancelando transação com erro");
                reversalProvider.isDefaultUI();
                reversalProvider.setConnectionCallback(new StoneCallbackInterface() {
                    @Override
                    public void onSuccess() {
                        callbackContext.success("Result - Stone - Sumni - ReverterTransacaoComErro: OK");
                    }

                    @Override
                    public void onError() {
                        callbackContext.success("Result - Stone - Sumni - ReverterTransacaoComErro: Error");
                    }
                });
                new Thread(() -> {
                    reversalProvider.execute();
                }).start();
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - ReverterTransacaoComErro: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("ImprimirComprovanteTransacao")) {
            JSONObject params = args.getJSONObject(0);
            try {
                String transactionObjectStr = params.getString("transactionObject");
                TransactionObject transactionObject = cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseJsonStringToObj(transactionObjectStr,TransactionObject.class);

                String receiptTypeString = params.getString("tipoRecibo");
                ReceiptType receiptType = GetReceiptTypeEnumByName(receiptTypeString);

                PosPrintReceiptProvider posPrintReceiptProvider = new PosPrintReceiptProvider(mContext, transactionObject, receiptType);
                posPrintReceiptProvider.setConnectionCallback(new StoneCallbackInterface() {
                    @Override
                    public void onSuccess() {
                        callbackContext.success("ImpressoOk");
                    }

                    @Override
                    public void onError() {
                        callbackContext.error("Erro ao imprimir: " + posPrintReceiptProvider.getListOfErrors());
                    }
                });
                posPrintReceiptProvider.execute();

                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - ImprimirComprovanteTransacao: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("ImpressaoTextoNetPrint")) {
            JSONObject params = args.getJSONObject(0);
            try {
                String dados = params.getString("dados");
                Boolean negrito = false;
                try {
                    negrito = params.getBoolean("negrito");
                }catch (Exception ex){
                }

                String html = cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterTextoImpressoToHtml(dados, negrito);

                cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterHtmlToBitmap(html, mContext, bitmap -> {
                    if (bitmap != null) {
                        try {
                            PosPrintProvider customPosPrintProvider = new PosPrintProvider(mContext);
                            // PosPrintProvider posPrintReceiptProvider = new PosPrintProvider(mContext, transactionObject, receiptType);
                            customPosPrintProvider.addBitmap(bitmap);
                            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                            bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
                            byte[] byteArray = byteArrayOutputStream.toByteArray();
                            String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
                            customPosPrintProvider.setConnectionCallback(new StoneCallbackInterface() {
                                @Override
                                public void onSuccess() {
                                    callbackContext.success("ImpressoOk");
                                }

                                @Override
                                public void onError() {
                                    callbackContext.error("Erro ao imprimir: " + customPosPrintProvider.getListOfErrors());
                                }
                            });
                            customPosPrintProvider.execute();
                        } catch (Exception errorPost) {
                            callbackContext.error("Result - ConverterHtmlToBitmap: " + "Error Detail: " + errorPost);
                        }
                    }
                });
//                callbackContext.success(html);
            } catch (Exception e) {
                callbackContext.error("ImpressaoTextoNetPrint error: " + e.toString());
            }
            return true;
        }

        else if (action.equals("ImpressaoBase64NetPrint")) {
            try{
                final PosPrintProvider customPosPrintProvider = new PosPrintProvider(this.mContext);
                JSONObject params = args.getJSONObject(0);
                String base64String = params.getString("base64String");
                Bitmap dadosImg = cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterBase64ToBitmap(base64String);
                customPosPrintProvider.addBitmap(dadosImg);
                // result = Termica.ImprimeBitmap(decodedByte);
                // if (result == 1) {
                // }
                // callbackContext.success(result);
                customPosPrintProvider.execute();
                callbackContext.success("PrintTesteBase64");
            } catch (Exception e){
                callbackContext.error("PrintTesteBase64 error: " + e.toString());
            }
            return true;
        }

        else if (action.equals("ConverterTextoImpressoToHtml")) {
            JSONObject params = args.getJSONObject(0);
            try{
                String dados = params.getString("dados");

            } catch (Exception e){
                callbackContext.error("ConverterHtmlToBitmap error: " + e.toString());
            }
            return true;
        }

        else if (action.equals("ConverterHtmlToBitmap")) {
            JSONObject params = args.getJSONObject(0);
            try{
                String htmlString = params.getString("htmlStr");
                cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterHtmlToBitmap( htmlString, mContext, bitmap -> {
                    callbackContext.success("Convertido");
                });
            } catch (Exception e){
                callbackContext.error("ConverterHtmlToBitmap error: " + e.toString());
            }
            return true;
        }


        else if (action.equals("ListarTransacoes")) {
            JSONObject params = args.getJSONObject(0);
            try {
                TransactionDAO transactionDAO = new TransactionDAO(this.mContext);
                List<TransactionObject> transactionObjects = transactionDAO.getAllTransactionsOrderByIdDesc();
                callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(transactionObjects));
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - ListarTransacoes: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("CancelarTransacao")) {
            JSONObject params = args.getJSONObject(0);
            try {
                String transactionObjectStr = params.getString("transactionObject");
                TransactionObject transactionObject = cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseJsonStringToObj(transactionObjectStr,TransactionObject.class);

                final CancellationProvider cancellationProvider = new CancellationProvider(this.mContext, transactionObject);
                cancellationProvider.useDefaultUI(false); // para dar feedback ao usuario ou nao.
                cancellationProvider.setDialogMessage("Cancelando...");
                cancellationProvider.setConnectionCallback(new StoneCallbackInterface() { // chamada de retorno.
                    public void onSuccess() {
                        switch (cancellationProvider.getResponseCodeEnum()) {
                            case Approved:
                                callbackContext.success(cancellationProvider.getMessageFromAuthorize());
                                break;
                            case Declined:
                                callbackContext.error(cancellationProvider.getMessageFromAuthorize());
                                break;
                            case TechnicalError:
                                callbackContext.error(cancellationProvider.getMessageFromAuthorize());
                                break;
                            case Default:
                                callbackContext.error(cancellationProvider.getMessageFromAuthorize());
                                break;
                        }

                    }

                    public void onError() {
                        callbackContext.error(cancellationProvider.getListOfErrors().toString());
                    }
                });
                cancellationProvider.execute();
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - CancelarTransacao: " + "Error Detail: " + error1);
            }
            return false;
        }

        else if (action.equals("CancelarTransacaoCompleto")) {
            JSONObject params = args.getJSONObject(0);
            try {
                String transactionObjectStr = params.getString("transactionObject");
                TransactionObject transactionObject = cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseJsonStringToObj(transactionObjectStr,TransactionObject.class);

                final CancellationProvider cancellationProvider = new CancellationProvider(this.mContext, transactionObject);
                cancellationProvider.useDefaultUI(false); // para dar feedback ao usuario ou nao.
                cancellationProvider.setDialogMessage("Cancelando...");
                cancellationProvider.setConnectionCallback(new StoneCallbackInterface() { // chamada de retorno.
                    public void onSuccess() {

                        TransactionDAO transactionDAO = new TransactionDAO(mContext);
                        List<TransactionObject> transactionObjects = transactionDAO.getAllTransactionsOrderByIdDesc();



                        switch (cancellationProvider.getResponseCodeEnum()) {
                            case Approved:
                                for (TransactionObject item : transactionObjects) {
                                    if (transactionObject.getTransactionReference().equals((item.getTransactionReference()))) {
                                        callbackContext.success(cordova.plugin.netcontroll.integration.util.NetControllHelpers.parseObjToJsonSrtring(item));
                                        return;
                                    }
                                }
                                break;

                            case Declined:
                                callbackContext.error(cancellationProvider.getMessageFromAuthorize());
                                break;
                            case TechnicalError:
                                callbackContext.error(cancellationProvider.getMessageFromAuthorize());
                                break;
                            case Default:
                                callbackContext.error(cancellationProvider.getMessageFromAuthorize());
                                break;
                        }
                    }

                    public void onError() {
                        callbackContext.error(cancellationProvider.getListOfErrors().toString());
                    }
                });
                cancellationProvider.execute();
                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - CancelarTransacao: " + "Error Detail: " + error1);
            }
            return false;
        } else if (action.equals("RetornaUUIDMifare")) {
            try {
                JSONObject params = args.getJSONObject(0);
                String statusChangeCallBack = params.getString("statusChangeCallBack");

                PosMifareProvider mifareProvider = new PosMifareProvider(this.mContext);
                mifareProvider.setConnectionCallback( new StoneCallbackInterface() {
                    public void onSuccess() {
                        byte[] byteUUID = mifareProvider.getCardUUID();
                        StringBuilder strUUID = new StringBuilder();
                        for (byte b : byteUUID) {
                            strUUID.append(String.format("%02X", b));
                        }
                        mifareProvider.powerOff();
                        callbackContext.success(strUUID.toString().toUpperCase());
                    }

                    public void onError() {
                        mifareProvider.cancelDetection();
                        mifareProvider.powerOff();
                        callbackContext.error("Erro na leitura do cartão!");
                    }
                });
                mifareProvider.execute();
                String Status = "Aproxime o cartão NFC a leitora NFC!";
                executeGlobalJavascript(statusChangeCallBack + "('" + Status + "')");

                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - RetornaUUIDMifare: " + "Error Detail: " + error1);
            }
        } else if (action.equals("FechaComunicacaoMifare")) {
            try {
                PosMifareProvider mifareProvider = new PosMifareProvider(this.mContext);
                mifareProvider.setConnectionCallback( new StoneCallbackInterface() {
                    public void onSuccess() {
                        mifareProvider.cancelDetection();
                        mifareProvider.powerOff();
                        callbackContext.success("Erro na leitura do cartão!");
                    }

                    public void onError() {
                        mifareProvider.cancelDetection();
                        mifareProvider.powerOff();
                        callbackContext.error("Erro na leitura do cartão!");
                    }
                });
                mifareProvider.execute();
                Thread.sleep(500);
                mifareProvider.cancelDetection();
                mifareProvider.powerOff();

                return true;
            } catch (Exception error1) {
                callbackContext.error("Result - Stone - Sumni - CancelaComunicacaoMifare: " + "Error Detail: " + error1);
            }
        }
        return false;
    }


    // Helpers
    private UserModel GetSelectedUserModel(int position) {
        return Stone.getUserModel(position);
    }

    private InstalmentTransactionEnum GetInstalmentTransactionEnumByName(String instalmentTransactionName) {
        InstalmentTransactionEnum instalmentCode = InstalmentTransactionEnum.ONE_INSTALMENT;
        switch (instalmentTransactionName) {
            case "ONE_INSTALMENT":                                                  //1x (à vista)
                instalmentCode = InstalmentTransactionEnum.ONE_INSTALMENT;
                break;
            case "TWO_INSTALMENT_NO_INTEREST":                                      //2x sem juros
                instalmentCode = InstalmentTransactionEnum.TWO_INSTALMENT_NO_INTEREST;
                break;
            case "THREE_INSTALMENT_NO_INTEREST":                                    //3x sem juros
                instalmentCode = InstalmentTransactionEnum.THREE_INSTALMENT_NO_INTEREST;
                break;
            case "FOUR_INSTALMENT_NO_INTEREST":                                     //4x sem juros
                instalmentCode = InstalmentTransactionEnum.FOUR_INSTALMENT_NO_INTEREST;
                break;
            case "FIVE_INSTALMENT_NO_INTEREST":                                     //5x sem juros
                instalmentCode = InstalmentTransactionEnum.FIVE_INSTALMENT_NO_INTEREST;
                break;
            case "SIX_INSTALMENT_NO_INTEREST":                                      //6x sem juros
                instalmentCode = InstalmentTransactionEnum.SIX_INSTALMENT_NO_INTEREST;
                break;
            case "SEVEN_INSTALMENT_NO_INTEREST":                                    //7x sem juros
                instalmentCode = InstalmentTransactionEnum.SEVEN_INSTALMENT_NO_INTEREST;
                break;
            case "EIGHT_INSTALMENT_NO_INTEREST":                                    //8x sem juros
                instalmentCode = InstalmentTransactionEnum.EIGHT_INSTALMENT_NO_INTEREST;
                break;
            case "NINE_INSTALMENT_NO_INTEREST":                                     //9x sem juros
                instalmentCode = InstalmentTransactionEnum.NINE_INSTALMENT_NO_INTEREST;
                break;
            case "TEN_INSTALMENT_NO_INTEREST":                                      //10x sem juros
                instalmentCode = InstalmentTransactionEnum.TEN_INSTALMENT_NO_INTEREST;
                break;
            case "ELEVEN_INSTALMENT_NO_INTEREST":                                   //11x sem juros
                instalmentCode = InstalmentTransactionEnum.ELEVEN_INSTALMENT_NO_INTEREST;
                break;
            case "TWELVE_INSTALMENT_NO_INTEREST":                                   //12x sem juros
                instalmentCode = InstalmentTransactionEnum.TWELVE_INSTALMENT_NO_INTEREST;
                break;
            case "TWO_INSTALMENT_WITH_INTEREST":                                    //2x com juros
                instalmentCode = InstalmentTransactionEnum.TWO_INSTALMENT_WITH_INTEREST;
                break;
            case "THREE_INSTALMENT_WITH_INTEREST":                                  //3x com juros
                instalmentCode = InstalmentTransactionEnum.THREE_INSTALMENT_WITH_INTEREST;
                break;
            case "FOUR_INSTALMENT_WITH_INTEREST":                                   //4x com juros
                instalmentCode = InstalmentTransactionEnum.FOUR_INSTALMENT_WITH_INTEREST;
                break;
            case "FIVE_INSTALMENT_WITH_INTEREST":                                   //5x com juros
                instalmentCode = InstalmentTransactionEnum.FIVE_INSTALMENT_WITH_INTEREST;
                break;
            case "SIX_INSTALMENT_WITH_INTEREST":                                    //6x com juros
                instalmentCode = InstalmentTransactionEnum.SIX_INSTALMENT_WITH_INTEREST;
                break;
            case "SEVEN_INSTALMENT_WITH_INTEREST":                                  //7x com juros
                instalmentCode = InstalmentTransactionEnum.SEVEN_INSTALMENT_WITH_INTEREST;
                break;
            case "EIGHT_INSTALMENT_WITH_INTEREST":                                  //8x com juros
                instalmentCode = InstalmentTransactionEnum.EIGHT_INSTALMENT_WITH_INTEREST;
                break;
            case "NINE_INSTALMENT_WITH_INTEREST":                                   //9x com juros
                instalmentCode = InstalmentTransactionEnum.NINE_INSTALMENT_WITH_INTEREST;
                break;
            case "TEN_INSTALMENT_WITH_INTEREST":                                    //10x com juros
                instalmentCode = InstalmentTransactionEnum.TEN_INSTALMENT_WITH_INTEREST;
                break;
            case "ELEVEN_INSTALMENT_WITH_INTEREST":                                 //11x com juros
                instalmentCode = InstalmentTransactionEnum.ELEVEN_INSTALMENT_WITH_INTEREST;
                break;
            case "TWELVE_INSTALMENT_WITH_INTEREST":                                 //12x com juros
                instalmentCode = InstalmentTransactionEnum.TWELVE_INSTALMENT_WITH_INTEREST;
                break;
            default:
                instalmentCode = InstalmentTransactionEnum.ONE_INSTALMENT;
                break;
        }
        return instalmentCode;
    }

    private TypeOfTransactionEnum GetTransactionTypeEnumByName(String transactionTypeName) {
        TypeOfTransactionEnum transactionType = TypeOfTransactionEnum.CREDIT;
        switch (transactionTypeName) {
            case "CREDIT":
                transactionType = TypeOfTransactionEnum.CREDIT;
                break;
            case "DEBIT":
                transactionType = TypeOfTransactionEnum.DEBIT;
                break;
            case "VOUCHER":
                transactionType = TypeOfTransactionEnum.VOUCHER;
                break;
            case "PIX":
                transactionType = TypeOfTransactionEnum.PIX;
                break;
            default:
                transactionType = TypeOfTransactionEnum.CREDIT;
                break;
        }
        return transactionType;
    }

    private ReceiptType GetReceiptTypeEnumByName(String receiptTypeName) {
        ReceiptType receiptType = ReceiptType.MERCHANT;
        switch (receiptTypeName) {
            case "MERCHANT":
                receiptType = ReceiptType.MERCHANT;
                break;
            case "CLIENT":
                receiptType = ReceiptType.CLIENT;
                break;
            default:
                receiptType = ReceiptType.MERCHANT;
                break;
        }
        return receiptType;
    }

    private void executeGlobalJavascript(final String jsString){
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                webView.loadUrl("javascript:" + jsString);
            }
        });
    }

}