package cordova.plugin.netcontroll.integration;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
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.app.Activity;
import android.graphics.Bitmap;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import android.net.Uri;
import android.content.Intent;
import android.provider.MediaStore;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;

import android.util.Base64;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;

import java.util.HashMap;
import java.util.Map;

import rede.smartrede.sdk.FlexTipoPagamento;
import rede.smartrede.sdk.Payment;
import rede.smartrede.sdk.PaymentStatus;
import rede.smartrede.sdk.Receipt;
import rede.smartrede.sdk.RedePaymentValidationError;
import rede.smartrede.sdk.RedePayments;

import android.graphics.Paint;
import android.graphics.Typeface;

import com.elgin.e1.Pagamento.Controller.TipoImpressao;
import com.elgin.e1.Pagamento.ElginPay;
import com.google.gson.annotations.SerializedName;
import com.google.zxing.WriterException;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.BarcodeFormat;

import com.journeyapps.barcodescanner.BarcodeEncoder;

import android.os.Build;

import br.com.gertec.gedi.GEDI;
import br.com.gertec.gedi.enums.GEDI_PRNTR_e_Alignment;
import br.com.gertec.gedi.enums.GEDI_PRNTR_e_BarCodeType;
import br.com.gertec.gedi.enums.GEDI_PRNTR_e_Status;
import br.com.gertec.gedi.exceptions.GediException;
import br.com.gertec.gedi.interfaces.ICL;
import br.com.gertec.gedi.interfaces.IGEDI;
import br.com.gertec.gedi.interfaces.IPRNTR;
import br.com.gertec.gedi.structs.GEDI_PRNTR_st_BarCodeConfig;
import br.com.gertec.gedi.structs.GEDI_PRNTR_st_PictureConfig;
import br.com.gertec.gedi.structs.GEDI_PRNTR_st_StringConfig;

//Json Serialize
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.List;
import com.google.zxing.EncodeHintType;
import android.os.AsyncTask;

import androidx.annotation.NonNull;

import java.lang.reflect.Type;
import java.util.ArrayList;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.EnumMap;
import com.izettle.html2bitmap.Html2Bitmap;
import com.izettle.html2bitmap.content.WebViewContent;
import java.io.ByteArrayOutputStream;

public class RedeGPos700 {
    //public class RedeGPos700 extends CordovaPlugin {
    //Cordova/Java Params
    private Activity mActivity;
    private Context mContext;
    private CordovaInterface mCordova;
    private CordovaWebView webView;

    //Rede
    // CordovaPlugin useRedeResultCordovaPlugin;

    //Intents CODES
    private static int PAYMENT_REQUEST_CODE = 890001;
    private static int REVERSAL_REQUEST_CODE = 890002;
    private static int REPRINT_REQUEST_CODE = 890003;

    public static final String G700 = "GPOS700";
    private static final String version = "v1.0.0";

    private RedePayments redePayments;
    private GertecPrinter gertecPrinter;
    private ConfigPrint configPrint = new ConfigPrint();
    public static String Model = Build.MODEL;

    //CallbacksOnActivityResult
    private CallbackContext selecionarImagemCallbackContext;

    //cutPaper boolean for resultActivity
    private boolean cutPaper = false;

    //    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        //        super.initialize(cordova, webView);

        //        this.webView = webView;
        mActivity = cordova.getActivity();
        mContext = cordova.getActivity().getApplicationContext();
        mCordova = cordova;
        redePayments = RedePayments.getInstance(mActivity);
    }

    public String Teste() {
        return "Result - RedeGPos700: ok";
    }

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if (action.equals("Testar")) {
            try {
                callbackContext.success("Testardo");
            } catch (Exception e) {
                callbackContext.error("Testar error: " + e.toString());
            }
            return true;
        } else if (action.equals("InicializaImpressao")) {
            try {
                gertecPrinter = new GertecPrinter(this.mContext);
                gertecPrinter.setConfigImpressao(configPrint);

                // Faz a impressão
                new Thread().sleep(1000);
                String sStatus = gertecPrinter.getStatusImpressora();
                if (gertecPrinter.isImpressoraOK()) {
                    callbackContext.success("InicializaImpressao ok");
                    return true;
                } else {
                    // ShowFalha(sStatus);
                    callbackContext.success("InicializaImpressao error: " + sStatus);
                    return false;
                }
            } catch (Exception e) {
                // callbackContext.error("InicializaImpressao error: " + e.toString());
            }
            return true;
        } else if (action.equals("ImpressaoBase64NetPrint")) {
                try{
                    JSONObject params = args.getJSONObject(0);
                    String base64String = params.getString("base64String");

                    Bitmap dadosImg = cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterBase64ToBitmap(base64String);
                    try {
                        gertecPrinter.imprimeImagemBmp(dadosImg, "CENTER", dadosImg.getHeight(), dadosImg.getWidth());
                        gertecPrinter.avancaLinha(150);
                    } catch (Exception x) {
                    }
                    finally {
                        try {
                            gertecPrinter.ImpressoraOutput();
                            callbackContext.success("ImpressaoBase64NetPrint - OK");
                        } catch (GediException e) {
                            callbackContext.error("ImpressaoBase64NetPrint error: " + e.toString());
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e){
                    callbackContext.error("PrintTesteBase64 error: " + e.toString());
                }
                return true;
        } 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){
                }
                try {
                    String html = cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterTextoImpressoToHtml(dados, negrito);
                    cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterHtmlToBitmap(html, mContext, bitmapResult -> {
                        Bitmap dadosImg = bitmapResult;
                        try {
                            gertecPrinter.imprimeImagemBmp(dadosImg, "CENTER", dadosImg.getHeight(), dadosImg.getWidth());
                            gertecPrinter.avancaLinha(150);
                        } catch (Exception x) {
                        }
                        finally {
                            try {
                                gertecPrinter.ImpressoraOutput();
                                callbackContext.success("ConverterHtmlToBitmap - OK");
                            } catch (GediException e) {
                                callbackContext.error("ConverterHtmlToBitmap error: " + e.toString());
                                e.printStackTrace();
                            }
                        }
                    });
                } catch (Exception y) {callbackContext.error("ImpressaoTextoNetPrintImg error: " + y);}
            } catch (Exception e) {
                callbackContext.error("ImpressaoTextoNetPrintImg error: " + e);
            }
            return true;
        } else if (action.equals("IniciarPagamento")) {
            try {
                JSONObject params = args.getJSONObject(0);

                String tipoTransacao = params.getString("tipoTransacao");
                FlexTipoPagamento tipoTransacaoObj = GetFlexTipoPagamentoEnumByName(tipoTransacao);

                int valor = params.getInt("valor");
                int numeroParcelas = params.getInt("numeroParcelas");

                Intent collectPaymentIntent = redePayments
                        .intentForPaymentBuilder(tipoTransacaoObj, valor)
                        .setInstallments(numeroParcelas).build();

                CordovaPlugin paymentResultCordovaPlugin = new CordovaPlugin() {
                    @Override
                    public void onActivityResult(int requestCode, int resultCode, Intent data) {
                        if (requestCode == PAYMENT_REQUEST_CODE) {
                            if (resultCode == RESULT_OK) {
                                if (data != null) {
                                    Payment payment = RedePayments.getPaymentFromIntent(data);
                                    Gson gson = new Gson();
                                    if (payment.getStatus() == PaymentStatus.AUTHORIZED) {
                                        //Receipt receipt =  payment.getReceipt();
                                        // String varResultStrJson = NetControllHelpers.parseObjToJsonSrtring(payment);
                                        // callbackContext.success(varResultStrJson);
                                        // callbackContext.success("PAGAMENTO OK");

                                        String paymentJsonString = gson.toJson(payment);

                                        callbackContext.success(paymentJsonString);
                                        //callbackContext.success(payment.toString());
                                    } else if (payment.getStatus() == PaymentStatus.FAILED) {
                                        callbackContext.success(gson.toJson(payment));
                                    } else if (payment.getStatus() == PaymentStatus.DECLINED) {
                                        callbackContext.success(gson.toJson(payment));
                                    }
                                }
                            } else if (resultCode == RESULT_CANCELED) {
                                callbackContext.error("Operação cancelada pelo usuário");
                            }
                        } else {
                            callbackContext.error("Pagamento result não encontrado");
                        }
                    }
                };
                mCordova.startActivityForResult(paymentResultCordovaPlugin, collectPaymentIntent, PAYMENT_REQUEST_CODE);
                return true;
            } catch (RedePaymentValidationError ex) {
                callbackContext.error("Pagamentos - Intent Pagamentos not found: " + ex.toString());
            } catch (Exception e) {
                callbackContext.error("IniciarPagamento error: " + e.toString());
            }
            return false;
        } else if (action.equals("EstornarPagamento")) {
            try {
                Intent reversal = redePayments.intentForReversal();
                CordovaPlugin reversalResultCordovaPlugin = new CordovaPlugin() {
                    @Override
                    public void onActivityResult(int requestCode, int resultCode, Intent data) {
                        if (requestCode == REVERSAL_REQUEST_CODE) {
                            if (resultCode == RESULT_OK) {
                                if (data != null) {
                                    Gson gson = new Gson();
                                    Payment payment = RedePayments.getPaymentFromIntent(data);
                                    if (payment.getStatus() == PaymentStatus.AUTHORIZED) {
                                        callbackContext.success(gson.toJson(payment));
                                    } else if (payment.getStatus() == PaymentStatus.FAILED) {
                                        callbackContext.success(gson.toJson(payment));
                                    } else if (payment.getStatus() == PaymentStatus.DECLINED) {
                                        callbackContext.success(gson.toJson(payment));
                                    }
                                }
                            } else if (resultCode == RESULT_CANCELED) {
                                callbackContext.error("Operação cancelada pelo usuário");
                            }
                        } else {
                            callbackContext.error("Estorno result não encontrado");
                        }
                    }
                };
                mCordova.startActivityForResult(reversalResultCordovaPlugin, reversal, REVERSAL_REQUEST_CODE);
                return true;
            } catch (RedePaymentValidationError ex) {
                callbackContext.error("Pagamentos - Intent Pagamentos not found: " + ex.toString());
            } catch (Exception e) {
                callbackContext.error("IniciarPagamento error: " + e.toString());
            }
            return false;
        } else if (action.equals("ReimprimirPagamento")) {
            try {
                Intent reprint = redePayments.intentForReprint();
                CordovaPlugin reprintResultCordovaPlugin = new CordovaPlugin() {
                    @Override
                    public void onActivityResult(int requestCode, int resultCode, Intent data) {
                        if (requestCode == REPRINT_REQUEST_CODE) {
                            if (resultCode == RESULT_OK) {
                                callbackContext.success("Reimpressão efetuada com sucesso");
                            } else if (resultCode == RESULT_CANCELED) {
                                callbackContext.error("Reimpressão cancelada pelo usuário");
                            }
                        } else {
                            callbackContext.error("Reimpressão result não encontrado");
                        }
                    }
                };
                mCordova.startActivityForResult(reprintResultCordovaPlugin, reprint, REPRINT_REQUEST_CODE);
                return true;
            } catch (RedePaymentValidationError ex) {
                callbackContext.error("Pagamentos - Intent Pagamentos not found: " + ex.toString());
            } catch (Exception e) {
                callbackContext.error("IniciarPagamento error: " + e.toString());
            }
            return false;
        }
        return false;
    }

    private FlexTipoPagamento GetFlexTipoPagamentoEnumByName(String receiptTypeName) {
        FlexTipoPagamento flexTipoPagamento = FlexTipoPagamento.CREDITO_A_VISTA;
        switch (receiptTypeName) {
            case "CREDITO_A_VISTA":
                flexTipoPagamento = FlexTipoPagamento.CREDITO_A_VISTA;
                break;
            case "CREDITO_PARCELADO":
                flexTipoPagamento = FlexTipoPagamento.CREDITO_PARCELADO;
                break;
            case "CREDITO_PARCELADO_EMISSOR":
                flexTipoPagamento = FlexTipoPagamento.CREDITO_PARCELADO_EMISSOR;
                break;
            case "DEBITO":
                flexTipoPagamento = FlexTipoPagamento.DEBITO;
                break;
            case "VOUCHER":
                flexTipoPagamento = FlexTipoPagamento.VOUCHER;
                break;
            case "PIX":
                flexTipoPagamento = FlexTipoPagamento.PIX;
                break;
            default:
                flexTipoPagamento = FlexTipoPagamento.CREDITO_A_VISTA;
                break;
        }
        return flexTipoPagamento;
    }

    private String ConverterTextoImpressoToHtml(String linhasImpressos) {
        try {
            String htmlStr = this.ConverterImpressaoToHtmlInicio();

            List < String > linhas = ConverterImpressaoToHtmlLinhasHtml(linhasImpressos);

            for (String linha: linhas) {
                htmlStr += linha;
            }

            htmlStr += this.ConverterImpressaoToHtmlFinal();

            return htmlStr;
        } catch (Exception e) {
            throw e;
        }
    }

    private boolean ConverterHtmlToBitmap(String htmlString, CallbackContext callbackContext) {
        try {
            AsyncTask < Void, Void, Bitmap > taskBitMap = new AsyncTask < Void, Void, Bitmap > () {
                @Override
                protected Bitmap doInBackground(Void...voids) {
                    Html2Bitmap build = new Html2Bitmap.Builder().setContext(mContext).setContent(WebViewContent.html(htmlString)).setBitmapWidth(380).setMeasureDelay(300).setScreenshotDelay(300).setStrictMode(true).setTimeout(15).setTextZoom(96).build();
                    Bitmap bitmapResult = build.getBitmap();
                    return bitmapResult;
                }

                @Override
                protected void onPostExecute(Bitmap bitmap) {
                    if (bitmap != null) {
                        try {
                            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                            bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
                            byte[] byteArray = byteArrayOutputStream.toByteArray();
                            String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
                            gertecPrinter.imprimeImagemBmp(bitmap, "CENTER", bitmap.getHeight(), bitmap.getWidth());
                            gertecPrinter.avancaLinha(150);
                        } catch (Exception errorPost) {
                            callbackContext.error("Result - ConverterHtmlToBitmap: " + "Error Detail: " + errorPost);
                        } finally {
                            try {
                                gertecPrinter.ImpressoraOutput();
                                callbackContext.success("ConverterHtmlToBitmap - OK");
                            } catch (GediException e) {
                                callbackContext.error("ConverterHtmlToBitmap error: " + e.toString());
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }.execute();
        } catch (Exception e) {
            throw e;
        }
        return true;
    }

    private String ConverterImpressaoToHtmlInicio() {
        String htmlResult = "<!DOCTYPE html>\n" +
                "<html lang='en'>\n" +
                "\n" +
                "<head>\n" +
                "    <!--  <meta charset='UTF-8'>\n" +
                "    <meta http-equiv='X-UA-Compatible' content='IE=edge'>\n" +
                "    <meta name='viewport' content='width=380, initial-scale=1.0'>\n" +
                "    <title>Document</title> -->\n" +
                "\n" +
                "    <style>\n" +
                "        /* @media print {\n" +
                "            .printer-ticket {\n" +
                "                border: none !important;\n" +
                "            }\n" +
                "        } */\n" +
                "\n" +
                "        body {\n" +
                "            margin: 0px;\n" +
                "            width: 380px;\n" +
                "            /*border: 1px solid black;*/\n" +
                "        }\n" +
                "\n" +
                "\n" +
                "\n" +
                "        .printer-ticket {\n" +
                "            /* background-color: #ffffcc; */\n" +
                "            background-color: white;\n" +
                "            font-size: 16px;\n" +

                "            /* padding: 10px; */\n" +
                "            max-width: 380px;\n" +
                "            /* border: solid 1px black; */\n" +
                "            /* text-align: center; */\n" +
                "            /*padding-left: 10px;*/\n" +
                "            /*padding-right: 10px;*/\n" +
                "        }\n" +
                "\n" +
                "        /* @media (max-width: 979px) {\n" +
                "            .section-printer--ticket {\n" +
                "                position: initial;\n" +
                "                top: 0;\n" +
                "            }\n" +
                "        } */\n" +
                "\n" +
                "        .printer-ticket table {\n" +
                "            margin: auto;\n" +
                "\n" +
                "        }\n" +
                "\n" +
                "        .printer-ticket * {\n" +
                "            font-family: monospace;\n" +
                "            /* font-family: Consolas, Regular;*/\n" +
                "            /* font-size: 100%; */\n" +
                "            color: black;\n" +
                "            /* line-height: 80%; */\n" +
                "            max-width: 380px;\n" +
                "            /* line-height: normal; */\n" +
                "            /* padding-left: 15px; */\n" +
                "        }\n" +
                "\n" +
                "        [data-normal='true'] {\n" +
                "            /* letter-spacing: 1px;\n" +
                "            font-size: 30px;\n" +
                "            text-align: left; */\n" +
                "            /* padding-left: 15px; */\n" +
                "        }\n" +
                "\n" +
                "\n" +
                "        [data-expandido='true'] {\n" +
                "            letter-spacing: 1px;\n" +
                "            font-size: 30px !important;\n" +
                "            /* text-align: left !important; */\n" +
                "            /* padding-left: 15px; */\n" +
                "        }\n" +
                "\n" +
                "        [data-condensado='true'] {\n" +
                "            letter-spacing: -2px;\n" +
                "            font-size: 15px !important;\n" +
                "            /* text-align: left !important; */\n" +
                "            /* padding-left: 10px; */\n" +
                "        }\n" +
                "\n" +
                "        [data-negrito='true'] {\n" +
                "            font-weight: bold;\n" +
                "        }\n" +
                "\n" +
                "        [data-reverse='true'] {\n" +
                "            background-color: black !important;\n" +
                "            color: white;\n" +
                "            -webkit-print-color-adjust: exact;\n" +
                "        }\n" +
                "\n" +
                "        [data-qrcode='true'] {\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "\n" +
                "        [data-barcode128='true'] {\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "\n" +
                "\n" +
                "        [data-alinhamento='1'] {\n" +
                "            text-align: left;\n" +
                "        }\n" +
                "\n" +
                "        [data-alinhamento='2'] {\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "\n" +
                "        [data-alinhamento='3'] {\n" +
                "            text-align: right;\n" +
                "        }\n" +
                "    </style>\n" +
                "</head>\n" +
                "\n" +
                "<body>\n" +
                "\n" +
                "\n" +
                "    <div class='printer-ticket'>\n" +
                "        <div class='row'>\n";

        return htmlResult;
    }

    private String ConverterImpressaoToHtmlInicioTentativa1() {
        String htmlResult = "<!DOCTYPE html>\n" +
                "<html lang='en'>\n" +
                "\n" +
                "<head>\n" +
                "    <meta charset='UTF-8'>\n" +
                "    <meta http-equiv='X-UA-Compatible' content='IE=edge'>\n" +
                "    <meta name='viewport' content='width=380, initial-scale=1.0'>\n" +
                "    <title>Document</title>\n" +
                "\n" +
                "    <style>\n" +
                "        /* @media print {\n" +
                "            .printer-ticket {\n" +
                "                border: none !important;\n" +
                "            }\n" +
                "        } */\n" +
                "\n" +
                "        body {\n" +
                "            margin: 0px;\n" +
                "            width: 380px;\n" +
                "            border: 1px solid black;\n" +
                "        }\n" +
                "\n" +
                "\n" +
                "\n" +
                "        .printer-ticket {\n" +
                "            /* background-color: #ffffcc; */\n" +
                "            background-color: white;\n" +
                "            /* padding: 10px; */\n" +
                "            max-width: 380px;\n" +
                "            /* border: solid 1px black; */\n" +
                "            /* text-align: center; */\n" +
                "            padding-left: 10px;\n" +
                "            padding-right: 10px;\n" +
                "        }\n" +
                "\n" +
                "        /* @media (max-width: 979px) {\n" +
                "            .section-printer--ticket {\n" +
                "                position: initial;\n" +
                "                top: 0;\n" +
                "            }\n" +
                "        } */\n" +
                "\n" +
                "        .printer-ticket table {\n" +
                "            margin: auto;\n" +
                "\n" +
                "        }\n" +
                "\n" +
                "        .printer-ticket * {\n" +
                "            font-family: monospace;\n" +
                "            /* font-size: 100%; */\n" +
                "            color: black;\n" +
                "            /* line-height: 80%; */\n" +
                "            max-width: 380px;\n" +
                "            /* line-height: normal; */\n" +
                "            /* padding-left: 15px; */\n" +
                "        }\n" +
                "\n" +
                "        [data-normal='true'] {\n" +
                "            /* letter-spacing: 1px;\n" +
                "            font-size: 30px;\n" +
                "            text-align: left; */\n" +
                "            /* padding-left: 15px; */\n" +
                "        }\n" +
                "\n" +
                "\n" +
                "        [data-expandido='true'] {\n" +
                "            letter-spacing: 1px;\n" +
                "            font-size: 30px !important;\n" +
                "            /* text-align: left !important; */\n" +
                "            /* padding-left: 15px; */\n" +
                "        }\n" +
                "\n" +
                "        [data-condensado='true'] {\n" +
                "            letter-spacing: -2px;\n" +
                "            font-size: 15px !important;\n" +
                "            /* text-align: left !important; */\n" +
                "            /* padding-left: 10px; */\n" +
                "        }\n" +
                "\n" +
                "        [data-negrito='true'] {\n" +
                "            font-weight: bold;\n" +
                "        }\n" +
                "\n" +
                "        [data-reverse='true'] {\n" +
                "            background-color: black !important;\n" +
                "            color: white;\n" +
                "            -webkit-print-color-adjust: exact;\n" +
                "        }\n" +
                "\n" +
                "        [data-qrcode='true'] {\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "\n" +
                "        [data-barcode128='true'] {\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "\n" +
                "\n" +
                "        [data-alinhamento='1'] {\n" +
                "            text-align: left;\n" +
                "        }\n" +
                "\n" +
                "        [data-alinhamento='2'] {\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "\n" +
                "        [data-alinhamento='3'] {\n" +
                "            text-align: right;\n" +
                "        }\n" +
                "    </style>\n" +
                "</head>\n" +
                "\n" +
                "<body>\n" +
                "\n" +
                "\n" +
                "    <div class='printer-ticket'>\n" +
                "        <div class='row'>\n";

        return htmlResult;
    }

    private List < String > ConverterImpressaoToHtmlLinhasHtml(String textoImpresso) {
        List < String > result = new ArrayList < String > ();;
        try {
            String[] linhas = textoImpresso.split("\n");
            for (String item: linhas) {
                String linha = item.replace(".nomeponto", "");
                linha = linha.replace(".impressovia", "");
                String tipoCaracter = "feed";

                if (linha.contains("<n>") && linha.contains("</n>")) {
                    tipoCaracter = "normal";
                    linha = linha.replace("<n>", "").replace("</n>", "");
                    if (linha.contains("<b>") && linha.contains("</b>")) {
                        tipoCaracter += "-bold";
                        linha = linha.replace("<b>", "").replace("</b>", "");
                    }
                } else if (linha.contains("<g>") && linha.contains("</g>")) {
                    tipoCaracter = "drawer";
                } else if (linha.contains("<e>") && linha.contains("</e>")) {
                    tipoCaracter = "expanded";
                    linha = linha.replace("<e>", "").replace("</e>", "");
                    if (linha.contains("<n>") && linha.contains("</n>")) {
                        tipoCaracter += "-normal";
                        linha = linha.replace("<n>", "").replace("</n>", "");
                        if (linha.contains("<b>") && linha.contains("</b>")) {
                            tipoCaracter = "bold";
                            linha = linha.replace("<b>", "").replace("</b>", "");
                        }
                    }
                } else if (linha.contains("<b>") && linha.contains("</b>")) {
                    tipoCaracter = "bold";
                    linha = linha.replace("<b>", "").replace("</b>", "");
                    if (linha.contains("<c>") && linha.contains("</c>")) {
                        tipoCaracter += "-condensed";
                        linha = linha.replace("<c>", "").replace("</c>", "");
                    } else if (linha.contains("<n>") && linha.contains("</n>")) {
                        tipoCaracter += "-normal";
                        linha = linha.replace("<n>", "").replace("</n>", "");
                    }
                } else if (linha.contains("<c>") && linha.contains("</c>")) {
                    tipoCaracter = "condensed";
                    linha = linha.replace("<c>", "").replace("</c>", "");
                } else if (linha.contains("<f>") && linha.contains("</f>")) {
                    tipoCaracter = "reverse";
                    linha = linha.replace("<f>", "").replace("</f>", "");
                } else if (linha.contains("<ce>") && linha.contains("</ce>")) {
                    linha = linha.replace("<ce>", "").replace("</ce>", "");
                    if (linha.contains("<qrcode>") && linha.contains("</qrcode>")) {
                        tipoCaracter = "qrcode";
                        linha = linha.replace("<qrcode>", "").replace("</qrcode>", "");
                    } else if (linha.contains("<code128>") && linha.contains("</code128>")) {
                        tipoCaracter = "barcode128";
                        linha = linha.replace("<code128>", "").replace("</code128>", "");
                    }
                }
                if (linha.contains("<esc      pos>")) {
                    linha = linha.replace("<esc      pos>", "              ");
                }
                if (linha == "") {
                    tipoCaracter = "feed";
                }

                switch (tipoCaracter) {
                    case "normal":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, false, false, false, false, false));
                        break;
                    case "normal-bold":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, false, true, false, false, false));
                        break;
                    case "bold-normal":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, false, true, false, false, false));
                        break;
                    case "bold":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, false, true, false, false, false));
                        break;
                    case "expanded":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, true, false, false, false, false, false));
                        break;
                    case "condensed":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, true, false, false, false, false));
                        break;
                    case "bold-condensed":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, true, true, false, false, false));
                        break;
                    case "reverse":
                        // ImpressaoTextoNetPrintHelper_ImpressaoTexto(linha, 1, 8 + 4, 0);
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, true, false, true, true, false, false));
                        break;
                    case "drawer":
                        //ImpressaoTextoNetPrintHelper_AbreGavetaElgin();
                        break;
                    case "qrcode":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, false, false, false, false, true));
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow("<br/>", false, false, false, false, false, false));
                        //ImpressaoTextoNetPrintHelper_DefinirImpressao(1);
                        //ImpressaoTextoNetPrintHelper_PrintQrCode(linha, 5, 1);
                        //ImpressaoTextoNetPrintHelper_AvancaPapel(5);
                        break;
                    case "barcode128":
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(linha, false, false, false, false, true, false));
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow("<br/>", false, false, false, false, false, false));
                        //ImpressaoTextoNetPrintHelper_DefinirImpressao(1);
                        //ImpressaoTextoNetPrintHelper_PrintBarCode(8, "{C" + linha, 50, 2, 4);
                        //ImpressaoTextoNetPrintHelper_AvancaPapel(5);
                        break;

                    default:
                        result.add(ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow("<br/>", false, false, false, false, false, false));
                        //                        ImpressaoTextoNetPrintHelper_AvancaPapel(1);
                        break;
                }

            }
        } catch (Exception ex) {
            String errorStr = ex.toString();
            throw ex;
        }
        return result;
    }

    String ImpressaoTextoNetPrintHelper_ImpressaoTextoDivRow(String texto, boolean expandido, boolean condensado, boolean negrito, boolean reverse, boolean barCode, boolean qrCode) {
        String result = "";
        try {

            if (!qrCode && !barCode) {
                texto = texto.replace(" ", "&nbsp;").replace("\r", "");
            }

            String textoExpandido = "";
            if (expandido) {
                textoExpandido = " data-expandido='true'";
            }

            String textoCondensado = "";
            if (condensado) {
                textoCondensado = " data-condensado='true'";
            }

            String textoNegrito = "";
            if (negrito) {
                textoNegrito = " data-negrito='true'";
            }

            String textoReverse = "";
            if (reverse) {
                textoReverse = " data-reverse='true'";
            }

            String textoBarCode = "";
            if (barCode) {
                textoBarCode = " data-barcode128='true'";
                String base64Barcode128 = this.CreateBarCodeBase64(texto, BarcodeFormat.CODE_128, 150, 75);
                String textoBarcode128 = "<img src=\"data:image/png;base64," + base64Barcode128 + "\" >";
                texto = textoBarcode128;
            }

            String textoQrCode = "";
            if (qrCode) {
                textoQrCode = " data-qrcode='true'";

                String baseQrCodeBase64 = this.CreateBarCodeBase64(texto, BarcodeFormat.QR_CODE, 200, 200);
                String textoQrCodeResult = "<img src=\"data:image/png;base64," + baseQrCodeBase64 + "\" >";
                texto = textoQrCodeResult;

            }

            result = "<div class='row'>\n" +
                    "                    <div class='col-12' " + textoExpandido + textoCondensado + textoNegrito + textoReverse + textoBarCode + textoQrCode + " >" + texto + "</div>\n" +
                    "                </div>";
            return result;
        } catch (Exception ex) {
            throw ex;
        }
    }

    private String ConverterImpressaoToHtmlFinal() {
        String htmlResult = " </div> " +
                "</div>" +
                "</body>" +
                "</html>";

        return htmlResult;
    }

    private String CreateBarCodeBase64(String valor, BarcodeFormat barcodeFormat, int width, int height) {
        ErrorCorrectionLevel errCorLvl = ErrorCorrectionLevel.L;
        switch (48) {
            case 48:
                errCorLvl = ErrorCorrectionLevel.L;
                break;
            case 49:
                errCorLvl = ErrorCorrectionLevel.M;
                break;
            case 50:
                errCorLvl = ErrorCorrectionLevel.Q;
                break;
            case 51:
                errCorLvl = ErrorCorrectionLevel.H;
        }

        Map < EncodeHintType, Object > hints = new EnumMap(EncodeHintType.class);
        hints.put(EncodeHintType.ERROR_CORRECTION, errCorLvl);

        Bitmap bitmap = null;
        try {
            bitmap = CreateBarcode(valor, barcodeFormat, width, height, hints);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        String resultBase64 = ConverterBitmapToBase64(bitmap);
        return resultBase64;
    }

    private Bitmap CreateBarcode(String dados, BarcodeFormat tipo, int width, int height, Map < EncodeHintType, Object > hints) throws WriterException {
        int BLACK = -16777216;
        boolean WHITE = true;
        if (hints != null) {
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 0);
        }

        long dte = System.currentTimeMillis();

        BitMatrix matrix;
        try {
            matrix = (new MultiFormatWriter()).encode(dados, tipo, width, height, hints);
        } catch (IllegalArgumentException var29) {
            var29.printStackTrace();
            return null;
        }

        dte = System.currentTimeMillis() - dte;
        width = matrix.getWidth();
        height = matrix.getHeight();
        long dtm = System.currentTimeMillis();
        int[][] mPixels = new int[height][width];

        int minX;
        int maxX;
        for (minX = 0; minX < height; ++minX) {
            for (maxX = 0; maxX < width; ++maxX) {
                mPixels[minX][maxX] = matrix.get(maxX, minX) ? -16777216 : -1;
            }
        }

        dtm = System.currentTimeMillis() - dtm;
        minX = 2147483647;
        maxX = 0;
        int minY = 2147483647;
        int maxY = 0;
        long dtp = System.currentTimeMillis();

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                if (mPixels[y][x] != -1) {
                    if (x < minX) {
                        minX = x;
                    }

                    if (x > maxX) {
                        maxX = x;
                    }

                    if (y < minY) {
                        minY = y;
                    }

                    if (y > maxY) {
                        maxY = y;
                    }
                }
            }
        }

        dtp = System.currentTimeMillis() - dtp;
        width = maxX - minX + 1;
        height = maxY - minY + 1;
        long dtr = System.currentTimeMillis();
        int[][] mTrimmedPixels = new int[height][width];
        int y = minY;

        for (int i = 0; y < maxY + 1 && i < height; ++i) {
            System.arraycopy(mPixels[y], minX, mTrimmedPixels[i], 0, width);
            ++y;
        }

        dtr = System.currentTimeMillis() - dtr;
        long dtv = System.currentTimeMillis();
        int[] vPixels = new int[width * height];

        for (y = 0; y < height; ++y) {
            int offset = y * width;
            System.arraycopy(mTrimmedPixels[y], 0, vPixels, offset, width);
        }

        dtv = System.currentTimeMillis() - dtv;
        //        long dtb = System.currentTimeMillis();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(vPixels, 0, width, 0, 0, width, height);
        //        dtb = System.currentTimeMillis() - dtb;
        //        System.out.println("Tempo para codificar dados: " + dte + " ms");
        //        System.out.println("Tempo para gerar matriz: " + dtm + " ms");
        //        System.out.println("Tempo para varrer matriz: " + dtp + " ms");
        //        System.out.println("Tempo para remover margens: " + dtr + " ms");
        //        System.out.println("Tempo para gerar vetor: " + dtv + " ms");
        //        System.out.println("Tempo para gerar bitmap: " + dtb + " ms");
        //        System.out.println("Tempo total (createBarcode): " + (dte + dtm + dtp + dtr + dtv + dtb) + " ms");
        return bitmap;
    }

    private String ConverterBitmapToBase64(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
        byte[] byteArray = byteArrayOutputStream.toByteArray();
        String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
        return encoded;
    }

    public class ConfigPrint {

        private String fonte = "NORMAL";
        private String alinhamento;
        private int tamanho;
        private int offSet;
        private int iHeight;
        private int iWidth;
        private int lineSpace;
        private boolean negrito;
        private boolean italico;
        private boolean sublinhado;
        private int avancaLinhas;

        public ConfigPrint() {
            this.fonte = "NORMAL";
            this.alinhamento = "CENTER";
            this.tamanho = 20;
            this.offSet = 0;
            this.iHeight = 700;
            this.iWidth = 430;
            this.lineSpace = 0;
            this.negrito = true;
            this.italico = true;
            this.sublinhado = false;
            this.avancaLinhas = 0;
        }

        public ConfigPrint(String fonte,
                           String alinhamento,
                           int tamanho,
                           int offSet,
                           int lineSpace,
                           boolean negrito,
                           boolean italico,
                           boolean sublinhado) {
            this.fonte = fonte;
            this.alinhamento = alinhamento;
            this.tamanho = tamanho;
            this.offSet = offSet;
            this.lineSpace = lineSpace;
            this.negrito = negrito;
            this.italico = italico;
            this.sublinhado = sublinhado;
        }

        public ConfigPrint(String fonte,
                           String alinhamento,
                           int tamanho,
                           int offSet,
                           int iHeight,
                           int iWidth,
                           int lineSpace,
                           boolean negrito,
                           boolean italico,
                           boolean sublinhado) {
            this.fonte = fonte;
            this.alinhamento = alinhamento;
            this.tamanho = tamanho;
            this.offSet = offSet;
            this.iHeight = iHeight;
            this.iWidth = iWidth;
            this.lineSpace = lineSpace;
            this.negrito = negrito;
            this.italico = italico;
            this.sublinhado = sublinhado;
        }

        public String getFonte() {
            return fonte;
        }

        public void setFonte(String fonte) {
            this.fonte = fonte;
            switch (fonte) {
                case "NORMAL":
                    break;
                case "DEFAULT":
                    break;
                case "DEFAULT BOLD":
                    break;
                case "MONOSPACE":
                    break;
                case "SANS SERIF":
                    break;
                case "SERIF":
                    break;
                default:
                    setFont(fonte);
            }
        }

        public String getAlinhamento() {
            return alinhamento;
        }

        public void setAlinhamento(String alinhamento) {
            this.alinhamento = alinhamento;
        }

        public int getTamanho() {
            return tamanho;
        }

        public void setTamanho(int tamanho) {
            this.tamanho = tamanho;
        }

        public int getOffSet() {
            return offSet;
        }

        public void setOffSet(int offSet) {
            this.offSet = offSet;
        }

        public int getLineSpace() {
            return lineSpace;
        }

        public void setLineSpace(int lineSpace) {
            this.lineSpace = lineSpace;
        }

        private void setFont(String fonte) {
            this.fonte = "fonts/" + fonte;
        }

        public int getiHeight() {
            return iHeight;
        }

        public void setiHeight(int iHeight) {
            this.iHeight = iHeight;
        }

        public int getiWidth() {
            return iWidth;
        }

        public void setiWidth(int iWidth) {
            this.iWidth = iWidth;
        }

        public boolean isNegrito() {
            return negrito;
        }

        public void setNegrito(boolean negrito) {
            this.negrito = negrito;
        }

        public boolean isItalico() {
            return italico;
        }

        public void setItalico(boolean italico) {
            this.italico = italico;
        }

        public boolean isSublinhado() {
            return sublinhado;
        }

        public void setSublinhado(boolean sublinhado) {
            this.sublinhado = sublinhado;
        }

        public int getAvancaLinhas() {
            return avancaLinhas;
        }

        public void setAvancaLinhas(int avancaLinhas) {
            this.avancaLinhas = avancaLinhas;
        }
    }

    public class GertecPrinter {

        // Definições
        private final String IMPRESSORA_ERRO = "Impressora com erro.";

        // Statics
        private boolean isPrintInit = false;

        // Vaviáveis iniciais
        private Activity activity;
        private Context context;

        // Classe de impressão
        private IGEDI iGedi = null;
        private IPRNTR iPrint = null;
        private ICL icl = null;
        private GEDI_PRNTR_st_StringConfig stringConfig;
        private GEDI_PRNTR_st_PictureConfig pictureConfig;
        private GEDI_PRNTR_e_Status status;

        // Classe de configuração da impressão
        private ConfigPrint configPrint;
        private Typeface typeface;

        /**
         * Método construtor da classe usando o GPOS 700
         * @param c = Context  atual que esta sendo inicializada a class
         **/
        public GertecPrinter(Context c) {
            this.context = c;
            startIGEDI();
        }

        /**
         * Método construtor da classe TSG 800
         * @param a = Activity  atual que esta sendo inicializada a class
         *
        public GertecPrinter(Activity a) {
        this.activity = a;
        startIGEDI(a);
        }
         */

        /**
         * Método que instância a classe GEDI da lib deve ser usado apenas para o GPOS 700
         *
         * @apiNote = Este mátodo faz a instância da classe GEDI através de uma Thread.
         *            Será sempre chamado na construção da classe.
         *            Não alterar...
         **/
        private void startIGEDI() {
            new Thread(() -> {
                GEDI.init(this.context);
                this.iGedi = GEDI.getInstance(this.context);
                this.iPrint = this.iGedi.getPRNTR();
                try {
                    new Thread().sleep(250);
                    icl = GEDI.getInstance().getCL();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        /**
         * Método que instância a classe GEDI da lib deve ser usado sempre o TSG 800
         *
         * @apiNote = Este mátodo faz a instância da classe GEDI através de uma Thread.
         *            Será sempre chamado na construção da classe.
         *            Não alterar...
         *
        private void startIGEDI(Activity a) {
        new Thread(() -> {
        iGedi = new Gedi(a);
        this.iGedi = GEDI.getInstance(a);
        this.iPrint = this.iGedi.getPRNTR();
        try {
        new Thread().sleep(250);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        }).start();
        }
         */

        /**
         * Método que recebe a configuração para ser usada na impressão
         * @param config  = Classe {@link ConfigPrint} que contém toda a configuração
         *                  para a impressão
         * */
        public void setConfigImpressao(ConfigPrint config) {

            this.configPrint = config;

            this.stringConfig = new GEDI_PRNTR_st_StringConfig(new Paint());
            this.stringConfig.paint.setTextSize(configPrint.getTamanho());
            this.stringConfig.paint.setTextAlign(Paint.Align.valueOf(configPrint.getAlinhamento()));
            this.stringConfig.offset = configPrint.getOffSet();
            this.stringConfig.lineSpace = configPrint.getLineSpace();

            switch (configPrint.getFonte()) {
                case "NORMAL":
                    this.typeface = Typeface.create(configPrint.getFonte(), Typeface.NORMAL);
                    break;
                case "DEFAULT":
                    this.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
                    break;
                case "DEFAULT BOLD":
                    this.typeface = Typeface.create(Typeface.DEFAULT_BOLD, Typeface.NORMAL);
                    break;
                case "MONOSPACE":
                    this.typeface = Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL);
                    break;
                case "SANS SERIF":
                    this.typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
                    break;
                case "SERIF":
                    this.typeface = Typeface.create(Typeface.SERIF, Typeface.NORMAL);
                    break;
                default:
                    this.typeface = Typeface.createFromAsset(this.context.getAssets(), configPrint.getFonte());
            }

            if (this.configPrint.isNegrito() && this.configPrint.isItalico()) {
                typeface = Typeface.create(typeface, Typeface.BOLD_ITALIC);
            } else if (this.configPrint.isNegrito()) {
                typeface = Typeface.create(typeface, Typeface.BOLD);
            } else if (this.configPrint.isItalico()) {
                typeface = Typeface.create(typeface, Typeface.ITALIC);
            }

            if (this.configPrint.isSublinhado()) {
                this.stringConfig.paint.setFlags(Paint.UNDERLINE_TEXT_FLAG);
            }

            this.stringConfig.paint.setTypeface(this.typeface);
        }

        /**
         * Método que retorna o atual estado da impressora
         *
         * @throws GediException = vai retorno o código do erro.
         *
         * @return String = traduzStatusImpressora()
         *
         * */
        public String getStatusImpressora() throws GediException {
            try {
                ImpressoraInit();
                this.status = this.iPrint.Status();
            } catch (GediException e) {
                throw new GediException(e.getErrorCode());
            }

            return traduzStatusImpressora(this.status);
        }

        /**
         * Método que recebe o atual texto a ser impresso
         * @param texto  = Texto que será impresso.
         *
         * @throws Exception = caso a impressora esteja com erro.
         *
         * */
        public void imprimeTexto(String texto) throws Exception {

            //this.getStatusImpressora();
            try {
                if (!isImpressoraOK()) {
                    throw new Exception(IMPRESSORA_ERRO);
                }
                sPrintLine(texto);
            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }

        /**
         * Método que recebe o atual texto e o tamanho da fonte que deve ser usado na impressão.
         *
         * @param texto  = Texto que será impresso.
         * @param tamanho = Tamanho da fonte que será usada
         *
         * @throws Exception = caso a impressora esteja com erro.
         *
         * @apiNote = Esse mátodo só altera o tamanho do texto na impressão que for chamado
         * a classe {@link ConfigPrint} não será alterada para continuar sendo usado na impressão da
         * proxíma linha
         *
         * */
        public void imprimeTexto(String texto, int tamanho) throws Exception {

            int tamanhoOld;

            //this.getStatusImpressora();

            try {
                if (!isImpressoraOK()) {
                    throw new Exception(IMPRESSORA_ERRO);
                }
                tamanhoOld = this.configPrint.getTamanho();
                this.configPrint.setTamanho(tamanho);
                this.setConfigImpressao(this.configPrint);
                sPrintLine(texto);
                this.configPrint.setTamanho(tamanhoOld);
                this.setConfigImpressao(this.configPrint);
            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }

        /**
         * Método que recebe o atual texto e ser o mesmo será impresso em negrito.
         *
         * @param texto  = Texto que será impresso.
         * @param negrito = Caso o texto deva ser impresso em negrito
         *
         * @throws Exception = caso a impressora esteja com erro.
         *
         * @apiNote = Esse mátodo só altera o tamanho do texto na impressão que for chamado
         *      * a classe {@link ConfigPrint} não será alterada para continuar sendo usado na impressão da
         *      * proxíma linha
         *
         * */
        public void imprimeTexto(String texto, boolean negrito) throws Exception {

            boolean negritoOld = false;

            //this.getStatusImpressora();

            try {
                if (!isImpressoraOK()) {
                    throw new Exception(IMPRESSORA_ERRO);
                }
                negritoOld = this.configPrint.isNegrito();
                this.configPrint.setNegrito(negrito);
                this.setConfigImpressao(this.configPrint);
                sPrintLine(texto);

                this.configPrint.setNegrito(negritoOld);
                this.setConfigImpressao(this.configPrint);

            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }

        /**
         * Método que recebe o atual texto e ser o mesmo será impresso em negrito e/ou itálico.
         *
         * @param texto  = Texto que será impresso.
         * @param negrito = Caso o texto deva ser impresso em negrito
         * @param italico  = Caso o texto deva ser impresso em itálico
         *
         * @throws Exception = caso a impressora esteja com erro.
         *
         * @apiNote = Esse mátodo só altera o tamanho do texto na impressão que for chamado
         *      * a classe {@link ConfigPrint} não será alterada para continuar sendo usado na impressão da
         *      * proxíma linha
         *
         * */
        public void imprimeTexto(String texto, boolean negrito, boolean italico) throws Exception {

            boolean negritoOld = false;
            boolean italicoOld = false;

            //this.getStatusImpressora();

            try {
                if (!isImpressoraOK()) {
                    throw new Exception(IMPRESSORA_ERRO);
                }
                negritoOld = this.configPrint.isNegrito();
                italicoOld = this.configPrint.isItalico();
                this.configPrint.setNegrito(negrito);
                this.configPrint.setItalico(italico);
                this.setConfigImpressao(this.configPrint);
                sPrintLine(texto);

                this.configPrint.setNegrito(negritoOld);
                this.configPrint.setItalico(italicoOld);
                this.setConfigImpressao(this.configPrint);

            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }
        /**
         * Método que recebe o atual texto e ser o mesmo será impresso em negrito, itálico e/ou  sublinhado.
         *
         * @param texto  = Texto que será impresso.
         * @param negrito = Caso o texto deva ser impresso em negrito
         * @param italico  = Caso o texto deva ser impresso em itálico
         * @param sublinhado   = Caso o texto deva ser impresso em itálico.
         *
         * @throws Exception = caso a impressora esteja com erro.
         *
         * @apiNote = Esse mátodo só altera o tamanho do texto na impressão que for chamado
         *      * a classe {@link ConfigPrint} não será alterada para continuar sendo usado na impressão da
         *      * proxíma linha
         *
         * */
        public void imprimeTexto(String texto, boolean negrito, boolean italico, boolean sublinhado) throws Exception {

            boolean negritoOld = false;
            boolean italicoOld = false;
            boolean sublinhadoOld = false;

            //this.getStatusImpressora();

            try {
                if (!isImpressoraOK()) {
                    throw new Exception(IMPRESSORA_ERRO);
                }
                negritoOld = this.configPrint.isNegrito();
                italicoOld = this.configPrint.isItalico();
                sublinhadoOld = this.configPrint.isSublinhado();

                this.configPrint.setNegrito(negrito);
                this.configPrint.setItalico(italico);
                this.configPrint.setSublinhado(sublinhado);
                this.setConfigImpressao(this.configPrint);
                sPrintLine(texto);

                this.configPrint.setNegrito(negritoOld);
                this.configPrint.setItalico(italicoOld);
                this.configPrint.setSublinhado(sublinhadoOld);
                this.setConfigImpressao(this.configPrint);

            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }

        /**
         * Método privado que faz a impressão do texto.
         *
         * @param texto = Texto que será impresso
         *
         * @throws GediException = retorna o código do erro
         *
         * */
        private boolean sPrintLine(String texto) throws Exception {
            //Print Data
            try {
                ImpressoraInit();
                this.iPrint.DrawStringExt(this.stringConfig, texto);
                this.avancaLinha(configPrint.getAvancaLinhas());
                //            ImpressoraOutput();
                return true;
            } catch (GediException e) {
                throw new GediException(e.getErrorCode());
            }
        }

        /**
         * Método que faz a impressão de imagens
         *
         * @param imagem = Nome da imagem que deve estar na pasta drawable
         *
         * @throws IllegalArgumentException = Argumento passado ilegal
         * @throws GediException = retorna o código do erro.
         *
         * */
        public boolean imprimeImagem(String imagem) throws GediException {

            int id = 0;
            Bitmap bmp;
            try {

                pictureConfig = new GEDI_PRNTR_st_PictureConfig();

                //Align
                pictureConfig.alignment = GEDI_PRNTR_e_Alignment.valueOf(configPrint.getAlinhamento());

                //Height
                pictureConfig.height = this.configPrint.getiHeight();
                //Width
                pictureConfig.width = this.configPrint.getiWidth();

                if (RedeGPos700.Model.equals(RedeGPos700.G700)) {
                    id = context.getResources().getIdentifier(imagem, "drawable",
                            context.getPackageName());
                    bmp = BitmapFactory.decodeResource(context.getResources(), id);
                } else {
                    id = this.activity.getApplicationContext().getResources().getIdentifier(
                            imagem, "drawable",
                            this.activity.getApplicationContext().getPackageName());
                    bmp = BitmapFactory.decodeResource(this.activity.getApplicationContext().getResources(), id);
                }

                ImpressoraInit();
                this.iPrint.DrawPictureExt(pictureConfig, bmp);
                this.avancaLinha(configPrint.getAvancaLinhas());

                return true;
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(e);
            } catch (GediException e) {
                throw new GediException(e.getErrorCode());
            }

        }

        public boolean imprimeImagemBmp(Bitmap bmp, String alinhamento, int height, int width) throws GediException {

            int id = 0;
            // Bitmap bmp;
            try {

                pictureConfig = new GEDI_PRNTR_st_PictureConfig();

                //Align
                pictureConfig.alignment = GEDI_PRNTR_e_Alignment.valueOf(alinhamento);

                //Height
                pictureConfig.height = height;
                //Width
                pictureConfig.width = width;

                // if (RedeGPos700.Model.equals(RedeGPos700.G700)) {
                //     id = context.getResources().getIdentifier(imagem, "drawable",
                //         context.getPackageName());
                //     bmp = BitmapFactory.decodeResource(context.getResources(), id);
                // } else {
                //     id = this.activity.getApplicationContext().getResources().getIdentifier(
                //         imagem, "drawable",
                //         this.activity.getApplicationContext().getPackageName());
                //     bmp = BitmapFactory.decodeResource(this.activity.getApplicationContext().getResources(), id);
                // }

                ImpressoraInit();
                this.iPrint.DrawPictureExt(pictureConfig, bmp);
                // this.avancaLinha(configPrint.getAvancaLinhas());

                return true;
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(e);
            } catch (GediException e) {
                throw new GediException(e.getErrorCode());
            }

        }

        /**
         * Método que faz a impressão de código de barras
         *
         * @param texto = Texto que será usado para a impressão do código de barras
         * @param height  = Tamanho
         * @param width  = Tamanho
         * @param barCodeType  = Tipo do código que será impresso
         *
         * @throws IllegalArgumentException = Argumento passado ilegal
         * @throws GediException = retorna o código do erro.
         *
         * */
        public boolean imprimeBarCode(String texto, int height, int width, String barCodeType) throws GediException {

            try {

                GEDI_PRNTR_st_BarCodeConfig barCodeConfig = new GEDI_PRNTR_st_BarCodeConfig();
                //Bar Code Type
                barCodeConfig.barCodeType = GEDI_PRNTR_e_BarCodeType.valueOf(barCodeType);

                //Height
                barCodeConfig.height = height;
                //Width
                barCodeConfig.width = width;

                ImpressoraInit();
                this.iPrint.DrawBarCode(barCodeConfig, texto);
                this.avancaLinha(configPrint.getAvancaLinhas());

                return true;
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(e);
            } catch (GediException e) {
                throw new GediException(e.getErrorCode());
            }

        }

        /**
         * Método que faz a impressão de código de barras
         *
         * @param texto = Texto que será usado para a impressão do código de barras
         * @param height  = Tamanho
         * @param width  = Tamanho
         * @param barCodeType  = Tipo do código que será impresso
         *
         * @throws IllegalArgumentException = Argumento passado ilegal
         * @throws GediException = retorna o código do erro.
         *
         * */
        public boolean imprimeBarCodeIMG(String texto, int height, int width, String barCodeType) throws GediException, WriterException {

            try {

                MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
                BitMatrix bitMatrix = multiFormatWriter.encode(texto, BarcodeFormat.valueOf(barCodeType), height, width);
                BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
                Bitmap bitmap = barcodeEncoder.createBitmap(bitMatrix);

                pictureConfig = new GEDI_PRNTR_st_PictureConfig();
                pictureConfig.alignment = GEDI_PRNTR_e_Alignment.valueOf(configPrint.getAlinhamento());

                pictureConfig.height = bitmap.getHeight();
                pictureConfig.width = bitmap.getWidth();

                ImpressoraInit();
                this.iPrint.DrawPictureExt(pictureConfig, bitmap);

                return true;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                throw new IllegalArgumentException(e);
            } catch (GediException e) {
                e.printStackTrace();
                throw new GediException(e.getErrorCode());
            } catch (WriterException e) {
                e.printStackTrace();
                throw new WriterException(e);
            }

        }

        /**
         * Método que faz o avanço de linhas após uma impressão.
         *
         * @param linhas = Número de linhas que dever ser pulado após a impressão.
         *
         * @throws GediException = retorna o código do erro.
         *
         * @apiNote = Esse método não deve ser chamado dentro de um FOR ou WHILE,
         * o número de linhas deve ser sempre passado no atributo do método.
         *
         * */
        public void avancaLinha(int linhas) throws GediException {
            try {
                if (linhas > 0) {
                    ImpressoraInit();
                    this.iPrint.DrawBlankLine(linhas);
                }
            } catch (GediException e) {
                throw new GediException(e.getErrorCode());
            }
        }

        /**
         * Método que retorno se a impressora está apta a fazer impressões
         *
         * @return true = quando estiver tudo ok.
         *
         * */
        public boolean isImpressoraOK() {

            if (status.getValue() == 0) {
                return true;
            }
            return false;
        }

        /**
         * Método que faz a inicialização da impressao
         *
         * @throws GediException = retorno o código do erro.
         *
         * */
        public void ImpressoraInit() throws GediException {
            try {
                if (this.iPrint != null && !isPrintInit) {
                    this.icl.PowerOff(); // Desliga o Módulo de NFC do equipamento.
                    this.iPrint.Init(); // Inicializa a Impressora do equipamento.
                    isPrintInit = true;
                }
            } catch (GediException e) {
                e.printStackTrace();
                throw new GediException(e.getErrorCode());
            }
        }
        /**
         * Método que faz a finalizacao do objeto iPrint
         *
         * @throws GediException = retorno o código do erro.
         *
         * */
        public void ImpressoraOutput() throws GediException {
            try {
                if (this.iPrint != null) {
                    this.iPrint.Output();
                    isPrintInit = false;
                }
            } catch (GediException e) {
                e.printStackTrace();
                throw new GediException(e.getErrorCode());
            }
        }

        /**
         * Método que faz a tradução do status atual da impressora.
         *
         * @param status = Recebe o {@link GEDI_PRNTR_e_Status} como atributo
         *
         * @return String = Retorno o atual status da impressora
         *
         * */
        private String traduzStatusImpressora(GEDI_PRNTR_e_Status status) {
            String retorno;
            switch (status) {
                case OK:
                    retorno = "IMPRESSORA OK";
                    break;

                case OUT_OF_PAPER:
                    retorno = "SEM PAPEL";
                    break;

                case OVERHEAT:
                    retorno = "SUPER AQUECIMENTO";
                    break;

                default:
                    retorno = "ERRO DESCONHECIDO";
                    break;
            }

            return retorno;
        }
    }
}