package com.nordenlogic.android.usbserial.printer;

import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.method.ScrollingMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.ArrayAdapter;
import android.content.DialogInterface;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;

import com.nordenlogic.android.usbserial.util.HexDump;
import com.nordenlogic.android.usbserial.util.NLESCPrint;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.Locale;

public class TerminalFragment extends Fragment implements SerialInputOutputManager.Listener {



    private enum UsbPermission { Unknown, Requested, Granted, Denied }

    private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
    private static final int WRITE_WAIT_MILLIS = 2000;
    private static final int READ_WAIT_MILLIS = 2000;

    private int deviceId, portNum, baudRate;
    private boolean withIoManager;

    private final BroadcastReceiver broadcastReceiver;
    private final Handler mainLooper;
    private TextView receiveText;
    private ControlLines controlLines;

    private SerialInputOutputManager usbIoManager;
    private UsbSerialPort usbSerialPort;
    private UsbPermission usbPermission = UsbPermission.Unknown;
    private boolean connected = false;
    private int checkedItem = 0;

    public TerminalFragment() {
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if(INTENT_ACTION_GRANT_USB.equals(intent.getAction())) {
                    usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                            ? UsbPermission.Granted : UsbPermission.Denied;
                    connect();
                }
            }
        };
        mainLooper = new Handler(Looper.getMainLooper());
    }

    /*
     * Lifecycle
     */
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        setRetainInstance(true);
        deviceId = getArguments().getInt("device");
        portNum = getArguments().getInt("port");
        baudRate = getArguments().getInt("baud");
        withIoManager = getArguments().getBoolean("withIoManager");
    }

    @Override
    public void onResume() {
        super.onResume();
        getActivity().registerReceiver(broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB));

        if(usbPermission == UsbPermission.Unknown || usbPermission == UsbPermission.Granted)
            mainLooper.post(this::connect);
    }

    @Override
    public void onPause() {
        if(connected) {
            status("disconnected");
            disconnect();
        }
        getActivity().unregisterReceiver(broadcastReceiver);
        super.onPause();
    }

    /*

    Norden Logic Printer Test functions showing API calls

    */
    public void quickTest(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char)4));
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.norden_company_logo_200_75);
        send(nlPrinter.printBitmapToBytes(bitmap));
        send(nlPrinter.printLF());
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.company_128_128);
        send(nlPrinter.printBitmapToBytes(bitmap));
        send(nlPrinter.printLF());
        String printString = "======== Android ========";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());
        printString = "100% Native Android Java code.";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Android Java Drivers and Lib.";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Norden Logic Oy (c)2024";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());
        printString = "Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Bold 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_BOLD));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Double Width";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_DOUBLE_WIDTH));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Double Height";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_DOUBLE_HEIGHT));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Reverse 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_REVERSE));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Underlined 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_UNDERLINE));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Italic 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_ITALIC));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Italic Underlined 0123456 AB ab";
        int font = NLESCPrint.FONT_TYPE_ITALIC + NLESCPrint.FONT_TYPE_UNDERLINE;
        send(nlPrinter.fontTypeSet((char)font));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap_mode_192_12);
        send(nlPrinter.printBitmapToBytes(bitmap));
        send(nlPrinter.printLF());
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap_mode_36_10);
        send(nlPrinter.printBitmapToBytes(bitmap));
        send(nlPrinter.printLF());
        send(nlPrinter.setLeftMargin((char)4));
        send(nlPrinter.barcodeWidthSet((char)3));
        send(nlPrinter.barcodeHeightSet((char)64));
        byte [] bar = new byte[]{'0','1','2','3','4','5','6','7','8','9','0'};
        send(nlPrinter.barcodePrint(NLESCPrint.BARCODE_SYS_UPCA,bar,(char)11));
        send(nlPrinter.setLeftMargin((char)0));
        send(nlPrinter.printLF());

    }




    public void attributes(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char)4));
        String printString = "======== Attributes ========";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Bold 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_BOLD));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Double Width";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_DOUBLE_WIDTH));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Double Height";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_DOUBLE_HEIGHT));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Reverse 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_REVERSE));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Underlined 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_UNDERLINE));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Italic 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_ITALIC));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Italic Underlined 0123456 AB ab";
        int font = NLESCPrint.FONT_TYPE_ITALIC + NLESCPrint.FONT_TYPE_UNDERLINE;
        send(nlPrinter.fontTypeSet((char)font));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

    }




    public void languges(){

        /*
        Note for euro, usd etc:
        EURO 0x80
        USD  0x24
        @    0x40
        UK Pound 0xA3
        YEN 0xA5
        Copyright 0xA9
        Registered 0xAE
        */


        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char)4));
        String printString = "======== Language ========";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());


        printString = "Small Font";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontMode(NLESCPrint.FONT_SIZE_S_SMALL));
        printString = "ABCDabcd1234%&/!)(.-_;";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.setFontMode(NLESCPrint.FONT_SIZE_S_LARGE));
        printString = "Normal Font";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "ABCDabcd1234%&/!)(.-_;";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());

        printString = "DoubleByte";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setDbMode());
        byte[] printArray = new byte[]{(byte)0xB7,(byte)0xC9,(byte)0xC1,(byte)0xF7,(byte)0xD6,(byte)0xB1,(byte)0xCF,(byte)0xC2,
                (byte)0xC8,(byte)0xFD,(byte)0xC7,(byte)0xA7,(byte)0xB3,(byte)0xDF,(byte)0xA3,(byte)0xAC,(byte)0xD2,(byte)0xC9,
                     (byte)0xCA,(byte)0xC7,(byte)0xD2,(byte)0xF8,(byte)0xBA,(byte)0xD3,(byte)0xC2,(byte)0xE4,(byte)0xBE,(byte)0xC5,(byte)0xCC,(byte)0xEC};
        send(printArray);
        send(nlPrinter.cancelDbMode());
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());
        printString = "Check API doc for languages.\nMany supported and custom flash.";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());

    }




    public void density(){
        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char)4));
        String printString = "======== Density ========";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.setFontGrayScale((char)0));
        printString = "0: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)1));
        printString = "1: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)2));
        printString = "2: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)3));
        printString = "3: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)4));
        printString = "4: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)5));
        printString = "5: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)6));
        printString = "6: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)7));
        printString = "7: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)8));
        printString = "8: Normal 0123456 ABCD abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setFontGrayScale((char)4));

    }




    public void qrBitmap(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.setFontGrayScale((char)4));
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qr_128_128);
        send(nlPrinter.printBitmapToBytes(bitmap));
        send(nlPrinter.printLF());
    }




    public void formatting() {
        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        String printString = "======== Formatting ========";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());


        printString = "Default Line Space 33:\n abcdefghijklmnopqrstuvwxyz";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());


        printString = "Line Space 66:\n abcdefghijklmnopqrstuvwxyz";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.lineSpacingSet((char)66));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.lineSpacingDefaults());
        printString = "Default Line Space 33:\n abcdefghijklmnopqrstuvwxyz";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        printString = "Feeding 20 dots after printing:\nabcdefghijklmnopqrstuvwxyz";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printAndFeedNDotLine((char)20));

        printString = "Feeding 3 lines after printing:\nabcdefghijklmnopqrstuvwxyz";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printAndFeedNFontLine((char)3));
        send(nlPrinter.printCR());

        send(nlPrinter.setLeftMargin((char)8));
        printString = "Left Margin 8:\nabcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setLeftMargin((char)0));

        send(nlPrinter.setRightMargin((char)38));
        printString = "Right Margin 38:\nabcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.setLeftMargin((char)0));

    }


    public void alignment() {
        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        String printString = "======== Alignment ========";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        byte [] myTabs = new byte[]{0x8,0x18,0x26};
        send(nlPrinter.horizontalTabSet(myTabs,(char)3));

        printString = "No Tab: abcd";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.horizontalTab());
        printString = "Tab1";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.horizontalTab());
        printString = "Tab2";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.horizontalTab());
        printString = "Tab3";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printAndFeedNFontLine((char)2));

        send(nlPrinter.absolutePrintPos((char)50,(char)0));
        printString = "Abs: 1234";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());

        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_CENTER));
        printString = "Center: abcd";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_RIGHT));
        printString = "Right: abcd";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        printString = "Left: abcd";
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.printLF());

    }



    public void receipt() {
        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_company);
        send(nlPrinter.printBitmapToBytes(bitmap));


        String printString = "Date: DD/MM/YY HH:MM";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "PID: 034/344/00288394";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printAndFeedNFontLine((char)2));

        printString = "  Qty      Item      Price";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        printString = "2x  1L 1.5% Milk     $3.98";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "6x  1L 3.5% Milk     $16.75";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "10x 100g Yogurt Cup  $8.50";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Total:              $29.23";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());
        printString = "Incl. 19% VAT $5.55 (Net $23.68)";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Credit Card         $29.23";
        int font = NLESCPrint.FONT_TYPE_ITALIC + NLESCPrint.FONT_TYPE_UNDERLINE;
        send(nlPrinter.fontTypeSet((char)font));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.printAndFeedNFontLine((char)2));
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_CENTER));
        printString = "THANK YOU FOR YOUR VISIT";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

    }


    public void barcode_sample(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        send(nlPrinter.setLeftMargin((char)4));
        send(nlPrinter.barcodeWidthSet((char)3));
        send(nlPrinter.barcodeHeightSet((char)64));
        byte [] bar = new byte[]{'0','1','2','3','4','5','6','7','8','9','0'};
        send(nlPrinter.barcodePrint(NLESCPrint.BARCODE_SYS_UPCA,bar,(char)11));
        send(nlPrinter.setLeftMargin((char)0));
        send(nlPrinter.printLF());
    }


    public void barcode_with_text(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        send(nlPrinter.setLeftMargin((char)4));
        send(nlPrinter.barcodeWidthSet((char)3));
        send(nlPrinter.barcodeHeightSet((char)64));
        send(nlPrinter.barcodeTextYesNo((char)1));
        byte [] bar = new byte[]{'0','1','2','3','4','5','6','7','8','9','0'};
        send(nlPrinter.barcodePrint(NLESCPrint.BARCODE_SYS_UPCA,bar,(char)11));
        send(nlPrinter.setLeftMargin((char)0));
        send(nlPrinter.printLF());
    }

    public void barcode_no_text(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        send(nlPrinter.setLeftMargin((char)4));
        send(nlPrinter.barcodeWidthSet((char)3));
        send(nlPrinter.barcodeHeightSet((char)64));
        send(nlPrinter.barcodeTextYesNo((char)0));
        byte [] bar = new byte[]{'0','1','2','3','4','5','6','7','8','9','0'};
        send(nlPrinter.barcodePrint(NLESCPrint.BARCODE_SYS_UPCA,bar,(char)11));
        send(nlPrinter.setLeftMargin((char)0));
        send(nlPrinter.barcodeTextYesNo((char)1));
        send(nlPrinter.printLF());
    }

    public void barcode_w_margin(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        send(nlPrinter.setLeftMargin((char)4));
        send(nlPrinter.barcodeWidthSet((char)3));
        send(nlPrinter.barcodeHeightSet((char)64));
        send(nlPrinter.barcodeTextYesNo((char)1));
        byte [] bar = new byte[]{'0','1','2','3','4','5','6','7','8','9','0'};
        send(nlPrinter.barcodePrint(NLESCPrint.BARCODE_SYS_UPCA,bar,(char)11));
        send(nlPrinter.setLeftMargin((char)0));
        send(nlPrinter.printLF());
    }

    public void barcode_no_margin(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        send(nlPrinter.setLeftMargin((char)0));
        send(nlPrinter.barcodeWidthSet((char)3));
        send(nlPrinter.barcodeHeightSet((char)64));
        send(nlPrinter.barcodeTextYesNo((char)1));
        byte [] bar = new byte[]{'0','1','2','3','4','5','6','7','8','9','0'};
        send(nlPrinter.barcodePrint(NLESCPrint.BARCODE_SYS_UPCA,bar,(char)11));
        send(nlPrinter.printLF());
    }

    public void fullcut(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.fullCut());

    }


    public void partialcut(){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.partialCut());

    }


    public void receiptFullCut() {
        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_company);
        send(nlPrinter.printBitmapToBytes(bitmap));


        String printString = "Date: DD/MM/YY HH:MM";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "PID: 034/344/00288394";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printAndFeedNFontLine((char)2));

        printString = "  Qty      Item      Price";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        printString = "2x  1L 1.5% Milk     $3.98";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "6x  1L 3.5% Milk     $16.75";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "10x 100g Yogurt Cup  $8.50";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Total:              $29.23";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());
        printString = "Incl. 19% VAT $5.55 (Net $23.68)";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Credit Card         $29.23";
        int font = NLESCPrint.FONT_TYPE_ITALIC + NLESCPrint.FONT_TYPE_UNDERLINE;
        send(nlPrinter.fontTypeSet((char)font));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.printAndFeedNFontLine((char)2));
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_CENTER));
        printString = "THANK YOU FOR YOUR VISIT";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.fullCut());

    }


    public void receiptPartialCut() {
        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_LEFT));
        send(nlPrinter.setFontGrayScale((char) 4));
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_company);
        send(nlPrinter.printBitmapToBytes(bitmap));


        String printString = "Date: DD/MM/YY HH:MM";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "PID: 034/344/00288394";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printAndFeedNFontLine((char)2));

        printString = "  Qty      Item      Price";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        printString = "2x  1L 1.5% Milk     $3.98";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "6x  1L 3.5% Milk     $16.75";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "10x 100g Yogurt Cup  $8.50";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Total:              $29.23";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.printLF());
        printString = "Incl. 19% VAT $5.55 (Net $23.68)";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = ".................................";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        printString = "Credit Card         $29.23";
        int font = NLESCPrint.FONT_TYPE_ITALIC + NLESCPrint.FONT_TYPE_UNDERLINE;
        send(nlPrinter.fontTypeSet((char)font));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());

        send(nlPrinter.printAndFeedNFontLine((char)2));
        send(nlPrinter.horizontalAlign(NLESCPrint.ALIGN_CENTER));
        printString = "THANK YOU FOR YOUR VISIT";
        send(nlPrinter.fontTypeSet(NLESCPrint.FONT_TYPE_NORMAL));
        send(nlPrinter.printStr(printString));
        send(nlPrinter.printLF());
        send(nlPrinter.partialCut());

    }




    /*
Set connected Print Head. Option is saved into flash
n=0  MM58_FTP628MCL101   58mm 6 stb 7.2V compatible designs *default value
n=1   MM80_FTP638MCL101   80mm 5stb 7.2V compatible designs
n=2   MM58_LTP02_245_13   58mm 1stb line 7.2V designs
n=3   MM58_LTP02_245_C1   58mm 1stb line 4.0V designs
n=4   MM58_CUTTER_384     58mm NL024 chip 7.2V/24V designs
n=5   MM80_CUTTER_576     80mm NL024 chip 7.2V/24V designs
*/
    public void setPrintHead (char headType){

        NLESCPrint nlPrinter = new NLESCPrint();
        send(nlPrinter.printerSoftInit());
        send(nlPrinter.setPrinterHead(headType));

    }




    /*
     * UI
     */
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_terminal, container, false);
        receiveText = view.findViewById(R.id.receive_text);                          // TextView performance decreases with number of spans
        receiveText.setTextColor(getResources().getColor(R.color.colorRecieveText)); // set as default color to reduce number of spans
        receiveText.setMovementMethod(ScrollingMovementMethod.getInstance());
        TextView sendText = view.findViewById(R.id.send_text);
        View sendBtn = view.findViewById(R.id.send_btn);
        sendBtn.setOnClickListener(v -> send(sendText.getText().toString()));
        View receiveBtn = view.findViewById(R.id.receive_btn);
        controlLines = new ControlLines(view);
        if(withIoManager) {
            receiveBtn.setVisibility(View.GONE);
        } else {
            receiveBtn.setOnClickListener(v -> read());
        }
        return view;
    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_terminal, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.clear) {
            receiveText.setText("");
            return true;
        } else if( id == R.id.clr_buff) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    SpannableStringBuilder spn = new SpannableStringBuilder();
                    spn.append("send Clear buffer and line feed\n");
                    spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    receiveText.append(spn);
                    NLESCPrint nlPrinter = new NLESCPrint();
                    send(nlPrinter.clearPrintBuffer());
                    send(nlPrinter.printLF());
                } catch(UnsupportedOperationException ignored) {
                    Toast.makeText(getActivity(), "not supported", Toast.LENGTH_SHORT).show();
                } catch(Exception e) {
                    Toast.makeText(getActivity(), "Clear Buffer failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
            return true;
        }else if( id == R.id.status) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    SpannableStringBuilder spn = new SpannableStringBuilder();
                    spn.append("send Status\n");
                    spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    receiveText.append(spn);
                    NLESCPrint nlPrinter = new NLESCPrint();
                    send(nlPrinter.printerState());
                } catch(UnsupportedOperationException ignored) {
                    Toast.makeText(getActivity(), "Status not supported", Toast.LENGTH_SHORT).show();
                } catch(Exception e) {
                    Toast.makeText(getActivity(), "Status failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
            return true;
        }else if( id == R.id.callback) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    SpannableStringBuilder spn = new SpannableStringBuilder();
                    spn.append("send Set Status Callback\n");
                    spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    receiveText.append(spn);
                    int callbackBits = NLESCPrint.PRINTER_STATE_OVERHEAT+NLESCPrint.PRINTER_STATE_PAPEROUT;
                    NLESCPrint nlPrinter = new NLESCPrint();
                    send(nlPrinter.setPrinterCallBack((char)callbackBits));
                } catch(UnsupportedOperationException ignored) {
                    Toast.makeText(getActivity(), "Set Callback not supported", Toast.LENGTH_SHORT).show();
                } catch(Exception e) {
                    Toast.makeText(getActivity(), "Set Callback failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
            return true;


        }else if( id == R.id.version) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    SpannableStringBuilder spn = new SpannableStringBuilder();
                    spn.append("send Version\n");
                    spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    receiveText.append(spn);
                    NLESCPrint nlPrinter = new NLESCPrint();
                    send(nlPrinter.getFirmwareInfo());
                } catch(UnsupportedOperationException ignored) {
                    Toast.makeText(getActivity(), "Version not supported", Toast.LENGTH_SHORT).show();
                } catch(Exception e) {
                    Toast.makeText(getActivity(), "Version failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
            return true;
        }else if( id == R.id.reset) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                try {
                    SpannableStringBuilder spn = new SpannableStringBuilder();
                    spn.append("send Reset\n");
                    spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    receiveText.append(spn);
                    NLESCPrint nlPrinter = new NLESCPrint();
                    send(nlPrinter.printerSoftInit());
                } catch(UnsupportedOperationException ignored) {
                    Toast.makeText(getActivity(), "Reset not supported", Toast.LENGTH_SHORT).show();
                } catch(Exception e) {
                    Toast.makeText(getActivity(), "Reset failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
            return true;
        }else if( id == R.id.general) {
            if (!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                final String[] listStr = getResources().getStringArray(R.array.general_print);

                //int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(baudRate));
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("General");
                builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                final ArrayAdapter arrayAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_single_choice, listStr);
                builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String strName = (String) arrayAdapter.getItem(which);
                        int selectionIdx = which;
                        AlertDialog.Builder builderInner = new AlertDialog.Builder(getActivity());
                        builderInner.setMessage(strName);
                        builderInner.setTitle("You want to print:");
                        builderInner.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });
                        builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {


                                switch (selectionIdx) {
                                    case 0:
                                        //Quick Test
                                        quickTest();
                                        break;
                                    case 1:
                                        //attributes
                                        attributes();
                                        break;
                                    case 2:
                                        //languages
                                        languges();
                                        break;
                                    case 3:
                                        //density
                                        density();
                                        break;
                                    case 4:
                                        //QR Bitmap
                                        qrBitmap();
                                        break;
                                    case 5:
                                        //formatting
                                        formatting();
                                        break;
                                    case 6:
                                        //alignment
                                        alignment();
                                        break;
                                    case 7:
                                        //receipt
                                        receipt();
                                        break;
                                }
                                dialog.dismiss();
                            }
                        });
                        builderInner.show();
                    }
                });
                builder.create().show();
                //return true;
            }
            return true;
        }else if( id == R.id.bar_codes) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                final String[] listStr = getResources().getStringArray(R.array.barcode_print);

                //int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(baudRate));
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("Bar Code");
                builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                final ArrayAdapter arrayAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_single_choice,listStr);
                builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String strName = (String)arrayAdapter.getItem(which);
                        int selectionIdx = which;
                        AlertDialog.Builder builderInner = new AlertDialog.Builder(getActivity());
                        builderInner.setMessage(strName);
                        builderInner.setTitle("You want to print:");
                         builderInner.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                                     @Override
                                     public void onClick(DialogInterface dialog, int which) {
                                         dialog.dismiss();
                                     }
                                 });
                        builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int which) {


                                switch (selectionIdx)
                                {
                                    case 0:
                                        //Sample
                                        barcode_sample();
                                        break;
                                    case 1:
                                        //Code with Text
                                        barcode_with_text();
                                        break;
                                    case 2:
                                        //Code without Text
                                        barcode_no_text();
                                        break;
                                    case 3:
                                        //code with left margin
                                        barcode_w_margin();
                                        break;
                                    case 4:
                                        //code no left margin
                                        barcode_no_margin();
                                        break;
                                }
                                dialog.dismiss();
                            }
                        });
                        builderInner.show();
                    }
                });
                builder.create().show();
                //return true;
            }
            return true;
        }else if( id == R.id.cutter) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                final String[] listStr = getResources().getStringArray(R.array.cutter_print);

                //int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(baudRate));
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("Cutter");
                builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                final ArrayAdapter arrayAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_single_choice,listStr);
                builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String strName = (String)arrayAdapter.getItem(which);
                        int selectionIdx = which;
                        AlertDialog.Builder builderInner = new AlertDialog.Builder(getActivity());
                        builderInner.setMessage(strName);
                        builderInner.setTitle("You want to print:");
                        builderInner.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });
                        builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int which) {


                                switch (selectionIdx)
                                {
                                    case 0:
                                        //Full cut
                                        fullcut();
                                        break;
                                    case 1:
                                        //Partial cut
                                        partialcut();
                                        break;
                                    case 2:
                                        //Receipt with full cut
                                        receiptFullCut();
                                        break;
                                    case 3:
                                        //receipt with partial cut
                                        receiptPartialCut();
                                        break;
                                }
                                dialog.dismiss();
                            }
                        });
                        builderInner.show();
                    }
                });
                builder.create().show();
                //return true;
            }
            return true;
        }else if( id == R.id.head_type) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                final String[] listStr = getResources().getStringArray(R.array.print_head);

                //int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(baudRate));
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("Print Head Type");
                builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                final ArrayAdapter arrayAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_single_choice,listStr);
                builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String strName = (String)arrayAdapter.getItem(which);
                        int selectionIdx = which;
                        AlertDialog.Builder builderInner = new AlertDialog.Builder(getActivity());
                        builderInner.setMessage(strName);
                        builderInner.setTitle("You want to print:");
                        builderInner.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });
                        builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int which) {


                                switch (selectionIdx)
                                {
                                    case 0:
                                        //
                                        setPrintHead((char)0);
                                        break;
                                    case 1:
                                        //
                                        setPrintHead((char)1);
                                        break;
                                    case 2:
                                        //
                                        setPrintHead((char)2);
                                        break;
                                    case 3:
                                        //
                                        setPrintHead((char)3);
                                        break;
                                    case 4:
                                        //
                                        setPrintHead((char)4);
                                        break;
                                    case 5:
                                        //
                                        setPrintHead((char)5);
                                        break;
                                }
                                dialog.dismiss();
                            }
                        });
                        builderInner.show();
                    }
                });
                builder.create().show();
                //return true;
            }
            return true;
        }else if( id == R.id.settings) {
            if(!connected) {
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            } else {
                final String[] listStr = getResources().getStringArray(R.array.uart_baud_rates);

                //int pos = java.util.Arrays.asList(values).indexOf(String.valueOf(baudRate));
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("Controller UART");

                //first cancel button
                builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });


                final ArrayAdapter arrayAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_single_choice,listStr);

                builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //String strName = (String)arrayAdapter.getItem(which);

                        int selectionIdx = which;//first list selection


                        //inner dialog box
                        AlertDialog.Builder builderInner = new AlertDialog.Builder(getActivity());
                        //builderInner.setMessage(strName);
                        builderInner.setTitle("Selected");


                        builderInner.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });//end cancel button


                        builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,int which) {


                                switch (selectionIdx)
                                {
                                    case 0:
                                        //

                                        break;
                                    case 1:
                                        //

                                        break;
                                    case 2:
                                        //

                                        break;
                                    case 3:
                                        //

                                        break;
                                    case 4:
                                        //

                                        break;
                                    case 5:
                                        //

                                        break;
                                }
                                dialog.dismiss();
                            }
                        });//end OK button
                        builderInner.show();
                    }
                });//first arrayAdapter ending here
                builder.create().show();

            }
            return true;



        } else {
            return super.onOptionsItemSelected(item);
        }
    }





    /*
     * Serial
     */
    @Override
    public void onNewData(byte[] data) {
        mainLooper.post(() -> {
            receive(data);
        });
    }

    @Override
    public void onRunError(Exception e) {
        mainLooper.post(() -> {
            status("connection lost: " + e.getMessage());
            disconnect();
        });
    }

    /*
     * Serial + UI
     */
    private void connect() {
        UsbDevice device = null;
        UsbManager usbManager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE);
        for(UsbDevice v : usbManager.getDeviceList().values())
            if(v.getDeviceId() == deviceId)
                device = v;
        if(device == null) {
            status("connection failed: device not found");
            return;
        }
        UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
        if(driver == null) {
            driver = CustomProber.getCustomProber().probeDevice(device);
        }
        if(driver == null) {
            status("connection failed: no driver for device");
            return;
        }
        if(driver.getPorts().size() < portNum) {
            status("connection failed: not enough ports at device");
            return;
        }
        usbSerialPort = driver.getPorts().get(portNum);
        UsbDeviceConnection usbConnection = usbManager.openDevice(driver.getDevice());
        if(usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) {
            usbPermission = UsbPermission.Requested;
            PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(getActivity(), 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
            usbManager.requestPermission(driver.getDevice(), usbPermissionIntent);
            return;
        }
        if(usbConnection == null) {
            if (!usbManager.hasPermission(driver.getDevice()))
                status("connection failed: permission denied");
            else
                status("connection failed: open failed");
            return;
        }

        try {
            usbSerialPort.open(usbConnection);
            usbSerialPort.setParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
            if(withIoManager) {
                usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
                usbIoManager.start();
            }
            status("connected");
            connected = true;
            controlLines.start();
        } catch (Exception e) {
            status("connection failed: " + e.getMessage());
            disconnect();
        }
    }

    private void disconnect() {
        connected = false;
        controlLines.stop();
        if(usbIoManager != null) {
            usbIoManager.setListener(null);
            usbIoManager.stop();
        }
        usbIoManager = null;
        try {
            usbSerialPort.close();
        } catch (IOException ignored) {}
        usbSerialPort = null;
    }

    private void send(String str) {
        if(!connected) {
            Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
        byte[] data = (str + '\n').getBytes();
            SpannableStringBuilder spn = new SpannableStringBuilder();
            spn.append("send " + data.length + " bytes\n");
            spn.append(HexDump.dumpHexString(data)).append("\n");
            spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            receiveText.append(spn);
            usbSerialPort.write(data, WRITE_WAIT_MILLIS);
        } catch (Exception e) {
            onRunError(e);
        }
    }


    private void send(byte[] data) {
        if(!connected) {
            Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            SpannableStringBuilder spn = new SpannableStringBuilder();
            spn.append("send " + data.length + " bytes\n");
            spn.append(HexDump.dumpHexString(data)).append("\n");
            spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorSendText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            receiveText.append(spn);
            usbSerialPort.write(data, WRITE_WAIT_MILLIS);
        } catch (Exception e) {
            onRunError(e);
        }
    }

    private void read() {
        if(!connected) {
            Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            byte[] buffer = new byte[8192];
            int len = usbSerialPort.read(buffer, READ_WAIT_MILLIS);
            receive(Arrays.copyOf(buffer, len));
        } catch (IOException e) {
            // when using read with timeout, USB bulkTransfer returns -1 on timeout _and_ errors
            // like connection loss, so there is typically no exception thrown here on error
            status("connection lost: " + e.getMessage());
            disconnect();
        }
    }

    private void receive(byte[] data) {
        SpannableStringBuilder spn = new SpannableStringBuilder();
        spn.append("received " + data.length + " bytes\n");
        if(data.length > 1)
            spn.append(HexDump.dumpHexString(data)).append("\n");
        if(data.length > 1)
          receiveText.append(spn);
    }

    void status(String str) {
        SpannableStringBuilder spn = new SpannableStringBuilder(str+'\n');
        spn.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorStatusText)), 0, spn.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        receiveText.append(spn);
    }

    class ControlLines {
        private static final int refreshInterval = 200; // msec

        private final Runnable runnable;
        private final ToggleButton rtsBtn, ctsBtn, dtrBtn, dsrBtn, cdBtn, riBtn;

        ControlLines(View view) {
            runnable = this::run; // w/o explicit Runnable, a new lambda would be created on each postDelayed, which would not be found again by removeCallbacks

            rtsBtn = view.findViewById(R.id.controlLineRts);
            ctsBtn = view.findViewById(R.id.controlLineCts);
            dtrBtn = view.findViewById(R.id.controlLineDtr);
            dsrBtn = view.findViewById(R.id.controlLineDsr);
            cdBtn = view.findViewById(R.id.controlLineCd);
            riBtn = view.findViewById(R.id.controlLineRi);
            rtsBtn.setOnClickListener(this::toggle);
            dtrBtn.setOnClickListener(this::toggle);
        }

        private void toggle(View v) {
            ToggleButton btn = (ToggleButton) v;
            if (!connected) {
                btn.setChecked(!btn.isChecked());
                Toast.makeText(getActivity(), "not connected", Toast.LENGTH_SHORT).show();
                return;
            }
            String ctrl = "";
            try {
                if (btn.equals(rtsBtn)) { ctrl = "RTS"; usbSerialPort.setRTS(btn.isChecked()); }
                if (btn.equals(dtrBtn)) { ctrl = "DTR"; usbSerialPort.setDTR(btn.isChecked()); }
            } catch (IOException e) {
                status("set" + ctrl + "() failed: " + e.getMessage());
            }
        }

        private void run() {
            if (!connected)
                return;
            try {
                EnumSet<UsbSerialPort.ControlLine> controlLines = usbSerialPort.getControlLines();
                rtsBtn.setChecked(controlLines.contains(UsbSerialPort.ControlLine.RTS));
                ctsBtn.setChecked(controlLines.contains(UsbSerialPort.ControlLine.CTS));
                dtrBtn.setChecked(controlLines.contains(UsbSerialPort.ControlLine.DTR));
                dsrBtn.setChecked(controlLines.contains(UsbSerialPort.ControlLine.DSR));
                cdBtn.setChecked(controlLines.contains(UsbSerialPort.ControlLine.CD));
                riBtn.setChecked(controlLines.contains(UsbSerialPort.ControlLine.RI));
                mainLooper.postDelayed(runnable, refreshInterval);
            } catch (IOException e) {
                status("getControlLines() failed: " + e.getMessage() + " -> stopped control line refresh");
            }
        }

        void start() {
            if (!connected)
                return;
            try {
                EnumSet<UsbSerialPort.ControlLine> controlLines = usbSerialPort.getSupportedControlLines();
                if (!controlLines.contains(UsbSerialPort.ControlLine.RTS)) rtsBtn.setVisibility(View.INVISIBLE);
                if (!controlLines.contains(UsbSerialPort.ControlLine.CTS)) ctsBtn.setVisibility(View.INVISIBLE);
                if (!controlLines.contains(UsbSerialPort.ControlLine.DTR)) dtrBtn.setVisibility(View.INVISIBLE);
                if (!controlLines.contains(UsbSerialPort.ControlLine.DSR)) dsrBtn.setVisibility(View.INVISIBLE);
                if (!controlLines.contains(UsbSerialPort.ControlLine.CD))   cdBtn.setVisibility(View.INVISIBLE);
                if (!controlLines.contains(UsbSerialPort.ControlLine.RI))   riBtn.setVisibility(View.INVISIBLE);
                run();
            } catch (IOException e) {
                Toast.makeText(getActivity(), "getSupportedControlLines() failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }

        void stop() {
            mainLooper.removeCallbacks(runnable);
            rtsBtn.setChecked(false);
            ctsBtn.setChecked(false);
            dtrBtn.setChecked(false);
            dsrBtn.setChecked(false);
            cdBtn.setChecked(false);
            riBtn.setChecked(false);
        }
    }
}
