/////////////////////////////////////////////////////////////////////
//
// BaseJposService.java - Abstract base class for all JavaPOS services.
//
// Modification history
// ------------------------------------------------------------------
// 2007-07-24 JavaPOS Release 1.0                                  VK
//
/////////////////////////////////////////////////////////////////////

import jpos.*;
import jpos.FiscalPrinter;
import org.apache.log4j.*;
import java.io.FileReader;
import java.io.BufferedReader;

class PrinterTest implements FiscalPrinterConst {

    String encoding = "Cp866";
    private static Logger logger = Logger.getLogger(PrinterTest.class);
    ShtrihFiscalPrinter printer = new ShtrihFiscalPrinter(
            new FiscalPrinter(), encoding);

    public String centerLine(String data, int lineLength) {
        int len = Math.min(data.length(), lineLength);
        String s = data.substring(0, len);
        len = (lineLength - len) / 2;
        for (int i = 0; i < len; i++) {
            s = " " + s;
        }

        len = lineLength - s.length();
        for (int i = 0; i < len; i++) {
            s += " ";
        }
        return s;
    }

    public String getLine(String data)
            throws JposException {
        String result = centerLine(data, printer.getMessageLength() - 6);
        result = "***" + result + "***";
        return result;
    }

    private String getHeaderLine(int lineNumber)
            throws JposException {
        return getLine("Строка клише " + String.valueOf(lineNumber));
    }

    private String getTrailerLine(int lineNumber)
            throws JposException {
        return getLine("Строка подвала " + String.valueOf(lineNumber));
    }

    public void setHeaderLines(String fileName) {
        try {
            int numLines = printer.getNumHeaderLines();
            if (numLines == 0) {
                return;
            }

            for (int i = 1; i < numLines; i++) {
                printer.setHeaderLine(i, getHeaderLine(i), false);
            }
            // last header line
            String line = getImageCommand2(fileName) + getHeaderLine(numLines);
            printer.setHeaderLine(numLines, line, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setTrailerLines() {
        try {
            int numTrailerLines = printer.getNumTrailerLines();
            for (int i = 1; i <= numTrailerLines; i++) {
                printer.setTrailerLine(i, getTrailerLine(i), false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void printBarcodeDIO(int barcodeType, String label, String barcode)
            throws Exception {
        printer.printBarcode(barcode, label + barcode, barcodeType, 100,
                printer.PRINTTYPE_DRIVER, 2, printer.TEXTPOS_BELOW, 1, 3);
    }

    private void printBarcode(int barcodeType, String label, String barcode)
            throws Exception {
        try {
            printer.printNormal(FPTR_S_RECEIPT, label + barcode);
            printBarcodeDIO(barcodeType, label, barcode);
        } catch (JposException e) {
            printer.printNormal(FPTR_S_RECEIPT, "[ERROR] " + e.getMessage());
        }
    }

    public void printAllBarcodes() {
        try {
            printer.beginNonFiscal();
            /*
            printBarcode(printer.BARCODE_UPCA, "UPC-A: ", "01234567890");
            printBarcode(printer.BARCODE_UPCE, "UPC-E: ", "0123456");
            printBarcode(printer.BARCODE_EAN13, "EAN13: ", "012345678912");
            printBarcode(printer.BARCODE_EAN8, "EAN8: ", "0123456");
            printBarcode(printer.BARCODE_CODE39, "CODE39: ", "012345678912");
            printBarcode(printer.BARCODE_ITF, "ITF25 (14): ", "01234567890123");
            printBarcode(printer.BARCODE_ITF, "ITF25 (20): ", "01234567890123456789");
            printBarcode(printer.BARCODE_CODABAR, "CODABAR: ", "012345678912");
            printBarcode(printer.BARCODE_CODE93, "CODE93: ", "012345678912");
            printBarcode(printer.BARCODE_CODE128, "CODE128: ", "012345678912");
            printBarcode(printer.BARCODE_PDF417, "PDF417: ", "012345678912");
             * 
             */
            printBarcode(printer.BARCODE_CODE128, "CODE128: ", "0010001170912101000004");
            printBarcode(printer.BARCODE_CODE128, "CODE128: ", "C0010001170912101000004");

            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getImageCommand(String fileName) {
        byte[] ss = {0x1B, 0x62};
        byte[] es = {0x0A};

        String data = new String(ss) + fileName + new String(es);
        return data;
    }

    // %L:Logo.bmp%
    private String getImageCommand2(String fileName) {
        byte[] ss = {0x25, 0x4C, 0x3A};
        byte[] es = {0x25};

        String data = new String(ss) + fileName + new String(es);
        return data;
    }

    public String getBarcode(
            int barcodeType,
            String text)
            throws JposException {
        // barcodeHeight
        byte b[] = {0x1D, 0x6B, 0, 0};
        b[2] = (byte) barcodeType;
        b[3] = (byte) text.length();

        String result = new String(b);
        result += text;
        return result;
    }

    private void printNormalBarcode(String label, int code, String text)
            throws Exception {
        try {
            printer.printNormal(FPTR_S_RECEIPT, label + text);
            printer.printNormal(FPTR_S_RECEIPT, getBarcode(code, text));
        } catch (JposException e) {
            printer.printNormal(FPTR_S_RECEIPT, "[ERROR] " + e.getMessage());
        }
    }

    private void printRecMessageBarcode(String label, int code, String text)
            throws Exception {
        try {
            printer.printRecMessage(label + text);
            printer.printRecMessage(getBarcode(code, text));
        } catch (JposException e) {
            printer.printRecMessage("[ERROR] " + e.getMessage());
        }
    }

    public void printEscBarcodesNormal() {
        try {
            printer.beginNonFiscal();

            printNormalBarcode("UPC-A: ", 65, "01234567890");
            printNormalBarcode("UPC-E: ", 66, "0123456");
            printNormalBarcode("EAN13: ", 67, "012345678912");
            printNormalBarcode("EAN8: ", 68, "0123456");
            printNormalBarcode("CODE39: ", 69, "012345678912");
            printNormalBarcode("ITF25: ", 70, "012345678912");
            printNormalBarcode("CODABAR: ", 71, "012345678912");
            printNormalBarcode("CODE93: ", 72, "012345678912");
            printNormalBarcode("CODE128: ", 73, "012345678912");
            printNormalBarcode("PDF417: ", 74, "012345678912");


            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printEscBarcodesRecMessage() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printRecMessageBarcode("UPC-A: ", 65, "01234567890");
            printRecMessageBarcode("UPC-E: ", 66, "0123456");
            printRecMessageBarcode("EAN13: ", 67, "012345678912");
            printRecMessageBarcode("EAN8: ", 68, "0123456");
            printRecMessageBarcode("CODE39: ", 69, "012345678912");
            printRecMessageBarcode("ITF25: ", 70, "012345678912");
            printRecMessageBarcode("CODABAR: ", 71, "012345678912");
            printRecMessageBarcode("CODE93: ", 72, "012345678912");
            printRecMessageBarcode("CODE128: ", 73, "012345678912");
            printRecMessageBarcode("PDF417: ", 74, "012345678912");

            printer.printRecVoid("");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void printCode39(String label, String barcode, int dots, int ratio)
            throws Exception {
        try {
            printer.printBarcode(
                    barcode,
                    label + barcode,
                    printer.BARCODE_CODE39,
                    100,
                    printer.PRINTTYPE_DRIVER,
                    dots,
                    printer.TEXTPOS_BELOW,
                    1,
                    ratio);
        } catch (JposException e) {
            printer.printNormal(FPTR_S_RECEIPT, "[ERROR] " + e.getMessage());
        }
    }

    public void printCode39Barcodes() {
        try {
            printer.beginNonFiscal();

            String barcode = "001.0578.270210.0001";
            printer.printBarcode(
                    barcode, barcode,
                    printer.BARCODE_CODE39,
                    100,
                    printer.PRINTTYPE_DRIVER,
                    1,
                    printer.TEXTPOS_BOTH,
                    1,
                    2);

            printer.printBarcode(
                    barcode, barcode,
                    printer.BARCODE_CODE39,
                    100,
                    printer.PRINTTYPE_DRIVER,
                    1,
                    printer.TEXTPOS_BOTH,
                    1,
                    3);

            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printBarcodes() {
        printCode39Barcodes();
        //printAllBarcodes();
    }

    public void testDirectIO()
            throws Exception {
        System.out.println("FPTR_DIO_READTABLE");
        int table;
        int rowCount;
        int fieldCount;

        // FPTR_DIO_WRITETABLE
        // payment names
        table = 5;
        rowCount = 4;
        fieldCount = 1;
        for (int row = 2; row <= rowCount; row++) {
            for (int field = 1; field <= fieldCount; field++) {
                printer.writeTable(table, row, field, "PAYTYPE" + String.valueOf(row));
            }
        }

        table = 1;
        rowCount = 1;
        fieldCount = 20;
        for (int row = 1; row <= rowCount; row++) {
            for (int field = 1; field <= fieldCount; field++) {
                String fieldValue = printer.readTable(table, row, field);
                System.out.println(
                        "Table " + String.valueOf(table) + ", "
                        + "Row " + String.valueOf(row) + ", "
                        + "Field " + String.valueOf(field) + ": "
                        + fieldValue);
            }
        }
        // payment names
        table = 5;
        rowCount = 4;
        fieldCount = 1;
        for (int row = 1; row <= rowCount; row++) {
            for (int field = 1; field <= fieldCount; field++) {
                String fieldValue = printer.readTable(table, row, field);
                System.out.println(
                        "Table " + String.valueOf(table) + ", "
                        + "Row " + String.valueOf(row) + ", "
                        + "Field " + String.valueOf(field) + ": "
                        + fieldValue);
            }
        }
        // FPTR_DIO_WRITE_PAYMENT_NAME
        for (int i = 2; i <= 4; i++) {
            printer.writePaymentName(i, "Тип оплаты " + String.valueOf(i));
        }
        // FPTR_DIO_READ_PAYMENT_NAME
        for (int i = 1; i <= 4; i++) {
            String paymentName = printer.readPaymentName(i);
            System.out.println(
                    "Payment " + String.valueOf(i) + ": " + paymentName);
        }
        // FPTR_DIO_READ_DAY_END
        System.out.println("FPTR_DIO_READ_DAY_END");
        if (printer.readDayEnd()) {
            System.out.println("Day end required");
        } else {
            System.out.println("24 hours is not over");
        }
    }

    public void open(String DeviceName) {
        try {
            printer.open(DeviceName);
            printer.setPowerNotify(printer.JPOS_PN_ENABLED);
            printer.claim(1000);
            printer.setDeviceEnabled(true);
            printer.setCheckTotal(false);
            printer.setAdditionalHeader("Additional header");
            printer.setAdditionalTrailer("Additional trailer");

            //testDirectIO();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            printer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printEmptyFiscalReceipt() {
        try {
            printer.beginFiscalReceipt(true);
            printer.printRecMessage("Nonfiscal line 1");
            printer.printRecSubtotal(0);
            printer.printRecTotal(0, 0, "1");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt() {
        printFiscalReceipt3();
    }

    public void printFiscalReceipt1() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecMessage("Nonfiscal line 1");
            printer.printRecSubtotal(0);
            printer.setPreLine("PreLine text");
            printer.setPostLine("PostLine text");
            // Weight item
            printer.printRecItem("Weight item", 0, 12345, 0, 123, "kg.");
            // Single item
            printer.printRecItem("Single item", 878, 0, 0, 0, "");
            // discounts
            printer.printRecItemAdjustment(FPTR_AT_AMOUNT_DISCOUNT, "Amount discount", -123, 0);
            printer.printRecItemAdjustment(FPTR_AT_AMOUNT_SURCHARGE, "Amount charge", -123, 0);
            printer.printRecItemAdjustment(FPTR_AT_PERCENTAGE_DISCOUNT, "Percent discount", -1000, 0);
            printer.printRecItemAdjustment(FPTR_AT_PERCENTAGE_SURCHARGE, "Percent charge", -1000, 0);

            printer.printRecVoidItem("Item void", 123, 12345, FiscalPrinterConst.FPTR_AT_AMOUNT_DISCOUNT, 0, 0);
            printer.printRecItem("Item 1", 0, 12345, 0, 123, "Unit name");
            printer.printRecMessage("Nonfiscal info 2");
            printer.printRecMessage(getBarcode(67, "012345678912"));

            printer.printRecSubtotal(0);
            printer.printRecTotal(0, 1, "1");
            printer.printRecTotal(0, 1, "10");
            printer.printRecTotal(0, 1, "20");
            printer.printRecTotal(0, 1, "30");
            printer.printRecTotal(0, 10000, "1");

            printer.printRecMessage(
                    "PrintRecMessage in FPTR_PS_FISCAL_RECEIPT_ENDING");

            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt2() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecMessage("Nonfiscal line 1");
            printer.printRecSubtotal(0);
            printer.setPreLine("PreLine text");
            printer.setPostLine("PostLine text");
            printer.printRecItem("1. Weight item", 0, 12345, 0, 123, "kg.");
            printer.printRecItem("2. Single item", 878, 0, 0, 0, "");
            printer.printRecItem("3. Multiline item text\r\nLine2\r\nLine3", 878, 0, 0, 0, "");
            printer.printRecItem("4. Long item text\r\n"
                    + "012345678901234567890123456789012345678901234567890123456789"
                    + "012345678901234567890123456789012345678901234567890123456789", 878, 0, 0, 0, "");

            // discounts
            printer.printRecItemAdjustment(FPTR_AT_AMOUNT_DISCOUNT, "Amount discount", -123, 0);
            printer.printRecItemAdjustment(FPTR_AT_AMOUNT_SURCHARGE, "Amount charge", -123, 0);
            printer.printRecItemAdjustment(FPTR_AT_PERCENTAGE_DISCOUNT, "Percent discount", -1000, 0);
            printer.printRecItemAdjustment(FPTR_AT_PERCENTAGE_SURCHARGE, "Percent charge", -1000, 0);

            printer.printRecVoidItem("Item void", 123, 12345, FiscalPrinterConst.FPTR_AT_AMOUNT_DISCOUNT, 0, 0);
            printer.printRecItem("Item 1", 0, 12345, 0, 123, "Unit name");
            printer.printRecMessage("Nonfiscal info 2");
            printBarcodeDIO(printer.BARCODE_EAN13, "EAN13: ", "012345678912");


            printer.printRecSubtotal(0);
            printer.printRecTotal(0, 1, "1");
            printer.printRecTotal(0, 1, "10");
            printer.printRecTotal(0, 1, "20");
            printer.printRecTotal(0, 1, "30");
            printer.printRecTotal(0, 100000, "1");

            printer.printRecMessage("PrintRecMessage in FPTR_PS_FISCAL_RECEIPT_ENDING");

            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt3() {
        try {
            byte b[] = {0x1B, 0x62};
            String result = new String(b);

            printer.setHeaderLine(1, new String(b) + "Logo.bmp", false);
            printer.setHeaderLine(2, "  ООО \"ГИПЕРГЛОБУС\"                               ", true);
            printer.setHeaderLine(3, "      Рязанская обл. Рязанский р-н                ", false);
            printer.setHeaderLine(4, "  с. Дядьково   телефон:(4912)97-55-60            ", false);

            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.setPreLine("4603260010725 ");
            printer.printRecItem("МЯСО КРАБИКА ОХЛ200Г", 305900, 1000, 2, 305900, "");
            printer.setPreLine("4603260010725 ");
            printer.printRecItem("МЯСО КРАБИКА ОХЛ200Г", 305900, 1000, 2, 305900, "");
            printer.printRecItemAdjustment(1, "", -305900, 2);

            printer.printRecSubtotal(305900);
            printer.printRecTotal(305900, 900, "39");
            printer.printRecTotal(305900, 500000, "1");
            printer.printRecMessage(" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
            printer.printRecMessage("     П о з д р а в л я е м !");
            printer.printRecMessage(" Вы получили СПЕЦИАЛЬНЫЕ СКИДКИ у нас:");
            printBarcodeDIO(printer.BARCODE_EAN13, "EAN13: ", "012345678912");
            printer.printRecMessage(" Авто скидка   30,59");

            byte b1[] = {0x1D, 0x61, 0x01, 0x0A};
            printer.printRecMessage(new String(b1));

            byte b2[] = {0x1D, 0x48, 0x02, 0x0A};
            printer.printRecMessage(new String(b2));

            byte b3[] = {0x1D, 0x77, 0x02, 0x0A};
            printer.printRecMessage(new String(b3));

            byte b4[] = {0x1D, 0x68, 0x0A};
            printer.printRecMessage(new String(b4));

            byte b5[] = {0x1D, 0x6B, 0x43, 0x0C};

            printer.printRecMessage(new String(b5) + "102170110365");
            printer.printRecMessage(" *****     Спасибо за покупку!      *****");
            printer.printRecMessage(" \"Глобус\" г. Щелково приглашает на работу");
            printer.printRecMessage("      - продавцов (возможно без о/р)");
            printer.printRecMessage("      - кассиров (возможно без о/р)");
            printer.printRecMessage("        - повара (о/р от 1 года)");
            printer.printRecMessage("          тел. (495) 221-85-00");
            printer.printRecMessage("         Найди работу уже сегодня");
            printer.printRecMessage("*0365 1000/011/001          17.02.11 13:58 AC-00");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt4() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecItem("Item 1", 1350000, 1000, 1, 1350000, "");
            printer.printRecTotal(1350000, 10000, "11");
            printer.printRecTotal(1350000, 10000, "12");
            printer.printRecTotal(1350000, 10000, "21");
            printer.printRecTotal(1350000, 10000, "31");
            printer.printRecTotal(1350000, 10000, "32");
            printer.printRecTotal(1350000, 1500000, "1");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt5() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecItem("8032711221681", 75000000, 1, 0, 0, "");
            printer.printRecMessage("DDP CALZ. BABY  SKISKOLAER + BIKE B  ARGENTO  26");
            printer.printRecTotal(75000000, 50000000, "2");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt6() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecItem("Товар номер 1", 7565, 1000, 1, 0, "Unit1");
            printer.printRecItemAdjustment(FPTR_AT_AMOUNT_DISCOUNT,
                    "Скидка на товар 1", -123, 1);
            printer.printRecItem("Товар номер 2", 1234, 1234, 2, 0, "Unit2");
            printer.printRecItemAdjustment(FPTR_AT_AMOUNT_DISCOUNT,
                    "Скидка на товар 2", -234, 2);

            printer.printRecTotal(75000000, 50000000, "2");
            printer.printRecMessage("Подвал чека, строка 1");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFiscalReceipt7() {
        printSalesReceipt7();
        printRefundReceipt7();
    }

    public void printSalesReceipt7() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecItem("Weight item", 18900, 1000, 0, 18900, "kg.");
            printer.printRecTotal(18900, 18900, "0");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printRefundReceipt7() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecItemRefund("Weight item", 18900, 1000, 0, 18900, "kg.");
            printer.printRecTotal(18900, 18900, "0");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void zeroFiscalReceipt() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecItem("Zero receipt", 0, 0, 0, 0, "kg.");
            printer.printRecTotal(0, 0, "1");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printRefundReceipt() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_SALES);
            printer.beginFiscalReceipt(true);
            printer.printRecMessage("Nonfiscal info 1");
            printer.printRecSubtotal(0);
            printer.printRecRefund("Item refund", 123, 1);
            printer.printRecItem("Weight item", 0, 0, 1, 123, "kg.");
            printer.printRecItemRefund("printRecItemRefund",
                    456, 8767, 1, 456, "Unit name");
            printer.printRecItemRefundVoid("printRecItemRefundVoid",
                    456, 8767, 1, 456, "Unit name");

            printer.printRecItemRefund("Receipt item refund", 1345, 8767, 1,
                    456, "Receipt item refund unit name");

            printer.printRecSubtotal(0);
            printer.printRecTotal(0, 10000, "1");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printNonFiscal() {
        try {
            printer.beginNonFiscal();
            printer.printNormal(FPTR_S_RECEIPT, getLine(""));
            printer.printNormal(FPTR_S_RECEIPT, getLine("Nonfiscal receipt"));
            printer.printNormal(FPTR_S_RECEIPT, getLine(""));

            printer.printNormal(FPTR_S_RECEIPT, "Строка1\rСтрока2\nСтрока3\r\nСтрока4\r\rСтрока6");
            printer.printNormal(FPTR_S_RECEIPT, "Строка7");
            printer.printNormal(FPTR_S_RECEIPT, "Нефискальный чек");

            printer.endNonFiscal();
        } catch (JposException e) {
            System.out.println("JposException");
            System.out.println("ErrorCode: " + String.valueOf(e.getErrorCode()));
            System.out.println("ErrorCodeExtended: " + String.valueOf(e.getErrorCodeExtended()));
            System.out.println("Text: " + e.getMessage());

            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printImage(String fileName) {
        try {
            printer.beginNonFiscal();
            printer.printNormal(FPTR_S_RECEIPT, getImageCommand2(fileName));
            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printCashInReceipt() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_CASH_IN);
            printer.beginFiscalReceipt(true);
            printer.printRecCash(100);
            printer.printRecTotal(0, 100, "0");
            printer.printRecMessage("--------------------------------------");
            printer.printText("TOTAL: 100", 2);
            printer.printRecMessage("--------------------------------------");

            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printCancelledCashInReceipt()
            throws Exception {
        printer.setFiscalReceiptType(FPTR_RT_CASH_IN);
        printer.beginFiscalReceipt(true);
        printer.printRecVoid("Receipt cancelled");
        printer.endFiscalReceipt(true);
    }

    public void printCancelledCashInReceipt2()
            throws Exception {
        printer.setFiscalReceiptType(FPTR_RT_CASH_IN);
        printer.beginFiscalReceipt(true);
        printer.printRecCash(100);
        printer.printRecVoid("Receipt cancelled");
        printer.endFiscalReceipt(true);
    }

    public void printCancelledCashInReceipt3()
            throws Exception {
        printer.setFiscalReceiptType(FPTR_RT_CASH_IN);
        printer.beginFiscalReceipt(true);
        printer.printRecCash(100);
        printer.printRecTotal(0, 100, "0");
        printer.printRecVoid("Receipt cancelled");
        printer.endFiscalReceipt(true);
    }

    public void printCashOutReceipt() {
        try {
            printer.setFiscalReceiptType(FPTR_RT_CASH_OUT);
            printer.beginFiscalReceipt(true);
            printer.printRecCash(100);
            printer.printRecTotal(0, 100, "0");
            printer.printRecMessage("--------------------------------------");
            printer.printText("TOTAL: 100", 2);
            printer.printRecMessage("--------------------------------------");
            printer.endFiscalReceipt(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printCancelledCashOutReceipt()
            throws Exception {
        printer.setFiscalReceiptType(FPTR_RT_CASH_OUT);
        printer.beginFiscalReceipt(true);
        printer.printRecVoid("Receipt cancelled");
        printer.endFiscalReceipt(true);
    }

    public void fiscalReceipts() {
        try {
            printCashInReceipt();
            printCancelledCashInReceipt();
            printCashOutReceipt();
            printCancelledCashOutReceipt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printTextFile(String fileName) {
        try {
            printer.beginNonFiscal();

            String line = "";
            BufferedReader br = new BufferedReader(new FileReader(fileName));
            while (br.ready()) {
                line = br.readLine();
                printer.printNormal(FPTR_S_RECEIPT, line);
            }
            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printZReport() {
        try {
            printer.printZReport();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void VatTest() {
        try {
            if (printer.getCapHasVatTable()) {
                int numVatRates = printer.getNumVatRates();
                System.out.println("NumVatRates: " + String.valueOf(numVatRates));
                // set vat rates
                for (int i = 1; i <= numVatRates; i++) {
                    printer.setVatValue(i, String.valueOf(1234 * i));
                }
                printer.setVatTable();
                // get vat rates
                for (int i = 1; i <= numVatRates; i++) {
                    int[] vatRate = new int[1];
                    printer.getVatEntry(i, 0, vatRate);
                    System.out.println("VatRate " + String.valueOf(i)
                            + "  : " + String.valueOf(vatRate[0]));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void clearImages() {
        try {
            printer.clearImages();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void loadImages() {
        try {
            printer.beginNonFiscal();
            printer.printNormal(FPTR_S_RECEIPT, "Load image receipt");

            // delete all images
            printer.printNormal(FPTR_S_RECEIPT, "Delete all images...");
            try {
                printer.clearImages();
                printer.printNormal(FPTR_S_RECEIPT, "OK");
            } catch (JposException e) {
                printer.printNormal(FPTR_S_RECEIPT, e.getMessage());
            }


            // load images from files
            for (int i = 0; i < 10; i++) {
                long startTime = System.currentTimeMillis();
                String fileName = "Logo" + String.valueOf(i) + ".bmp";
                printer.printNormal(FPTR_S_RECEIPT,
                        "Loading IMAGE" + String.valueOf(i) + " from file "
                        + fileName + " ...");
                try {
                    printer.loadImage(fileName);
                    printer.printNormal(FPTR_S_RECEIPT, "OK, "
                            + String.valueOf(System.currentTimeMillis() - startTime)
                            + " ms.");
                } catch (JposException e) {
                    printer.printNormal(FPTR_S_RECEIPT, e.getMessage());
                }
            }
            printer.endNonFiscal();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printImages() {
        try {
            printer.beginNonFiscal();
            printer.printNormal(FPTR_S_RECEIPT, "Print image receipt");
            for (int i = 0; i < 10; i++) {
                printer.printNormal(FPTR_S_RECEIPT, "IMAGE "
                        + String.valueOf(i) + ":");
                try {
                    printer.printImage(i);
                } catch (JposException e) {
                    printer.printNormal(FPTR_S_RECEIPT, e.getMessage());
                }
            }
            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printLines() {
        try {
            printer.beginNonFiscal();
            printer.printNormal(FPTR_S_RECEIPT, "Print black line receipt");
            for (int i = 0; i < 3; i++) {
                int lineHeight = 1 + i * 2;
                printer.printNormal(FPTR_S_RECEIPT, "Line height: "
                        + String.valueOf(lineHeight));
                try {
                    printer.printLine(lineHeight);
                    printer.printNormal(FPTR_S_RECEIPT, "OK");
                } catch (JposException e) {
                    printer.printNormal(FPTR_S_RECEIPT, e.getMessage());
                }
            }
            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void clearReceiptLogo() {
        try {
            // clear all receipt logo
            printer.clearLogo();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setReceiptLogo() {
        try {
            // clear all receipt logo
            printer.clearLogo();
            // set receipt logo0
            printer.addLogo(0, printer.LOGO_POS_AFTER_HEADER);
            // set receipt logo1
            printer.addLogo(1, printer.LOGO_POS_BEFORE_TRAILER);
            // set receipt logo2
            printer.addLogo(2, printer.LOGO_POS_AFTER_ADDTRAILER);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printFonts() {
        try {
            printer.beginNonFiscal();
            printer.printNormal(FPTR_S_RECEIPT, "Print lines with fonts");
            for (int i = 1; i < 8; i++) {
                String line = "Text line, font " + String.valueOf(i);
                printer.printText(line, i);
            }
            printer.endNonFiscal();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void openCashDrawer() {
        try {
            printer.openCashDrawer(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean isDrawerOpened() {
        try {
            return printer.readDrawerState();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public String readStatus() {
        String result = "";
        try {
            result = "";

            result = result
                    + "Receipt number: " + String.valueOf(printer.getReceiptNumber()) + "\n";

            result = result
                    + "Printer serial: " + printer.readSerial() + "\n";

            result = result
                    + "Electronic journal serial: " + printer.readEJSerial() + "\n";

            PrinterStatus status = printer.readPrinterStatus();
            result = result
                    + "Printer mode: " + String.valueOf(status.getMode())
                    + ", " + status.getPrinterMode().getText() + "\n";

            result = result
                    + "Printer submode: " + String.valueOf(status.getSubMode())
                    + ", " + PrinterSubMode.getText(status.getSubMode()) + "\n";

            result = result
                    + "Printer flags: " + String.valueOf(status.getFlags()) + "\n";

            PrinterFlags flags = status.getPrinterFlags();

            result = result
                    + "Journal paper is near end: "
                    + String.valueOf(flags.getJrnNearEnd()) + "\n";

            result = result
                    + "Receipt paper is near end: "
                    + String.valueOf(flags.getRecNearEnd()) + "\n";

            result = result
                    + "Paper on top slip station sensor: "
                    + String.valueOf(flags.getSlpEmpty()) + "\n";

            result = result
                    + "Paper on bottom slip station sensor: "
                    + String.valueOf(flags.getSlpNearEnd()) + "\n";

            result = result
                    + "Amount point position: "
                    + String.valueOf(flags.getAmountPointPosition()) + "\n";

            result = result
                    + "Electronic journal is present: "
                    + String.valueOf(flags.getEJPresent()) + "\n";

            result = result
                    + "Journal paper is empty: "
                    + String.valueOf(flags.getJrnEmpty()) + "\n";

            result = result
                    + "Receipt paper is empty: "
                    + String.valueOf(flags.getRecEmpty()) + "\n";

            result = result
                    + "Journal lever is up: "
                    + String.valueOf(flags.getJrnLeverUp()) + "\n";

            result = result
                    + "Receipt lever is up: "
                    + String.valueOf(flags.getRecLeverUp()) + "\n";

            result = result
                    + "Cover is opened: "
                    + String.valueOf(flags.getCoverOpened()) + "\n";

            result = result
                    + "Cash drawer is opened: "
                    + String.valueOf(flags.getDrawerOpened()) + "\n";

            result = result
                    + "Left printer sensor failure: "
                    + String.valueOf(flags.getLSensorFailure()) + "\n";

            result = result
                    + "Right printer sensor failure: "
                    + String.valueOf(flags.getRSensorFailure()) + "\n";

            result = result
                    + "Electronic journal is near end: "
                    + String.valueOf(flags.getJrnNearEnd()) + "\n";

            result = result
                    + "Extended quantity: "
                    + String.valueOf(flags.getExtQuantity()) + "\n";

            result = result
                    + "Operator number: "
                    + String.valueOf(status.getOperator()) + "\n";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public String readCashRegisters() {
        String result = "";
        try {
            result = "";
            for (int i = 0; i < 253; i++) {
                ShtrihFiscalPrinter.CashRegister reg = printer.readCashRegister(i);
                result = result + result.format("%-3d. %d, %s\n",
                        i,
                        reg.getValue(),
                        reg.getText());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public String readOperRegisters() {
        String result = "";
        try {
            result = "";
            for (int i = 0; i < 253; i++) {
                ShtrihFiscalPrinter.OperRegister reg = printer.readOperRegister(i);
                result = result + result.format("%-3d. %d, %s\n",
                        i,
                        reg.getValue(),
                        reg.getText());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void saveXmlZReport() {
        try {
            printer.saveXmlZReport("ZReport.xml");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void saveCsvZReport() {
        try {
            printer.saveCsvZReport("ZReport.csv");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void readStatus1() {
        try {
            printer.readStatus1();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void readStatus2() {
        try {
            printer.readStatus2();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void testSynchronization(String fptrDeviceName,
            String cashDeviceName) {
        try {
            logger.debug("testSynchronization");
            int i = 0;
            Thread thread = null;
            int maxThreadCount = 1;
            Thread[] threads = new Thread[maxThreadCount * 2];
            for (i = 0; i < maxThreadCount; i++) {
                FiscalPrinterTest test1 = new FiscalPrinterTest(fptrDeviceName, encoding);
                thread = new Thread(test1);
                thread.start();
                threads[i] = thread;
            }

            for (i = 0; i < maxThreadCount; i++) {
                CashDrawerTest test2 = new CashDrawerTest(cashDeviceName, encoding);
                thread = new Thread(test2);
                thread.start();
                threads[maxThreadCount + i] = thread;
            }

            for (i = 0; i < threads.length; i++) {
                threads[i].join();
            }

            logger.debug("testSynchronization: OK");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("testSynchronization", e);
        }
    }

    public class FiscalPrinterTest implements Runnable
    {
        private String resultText = "";
        private final String deviceName;
        private final String encoding;
        private Logger logger = Logger.getLogger(FiscalPrinterTest.class);

        public FiscalPrinterTest(String deviceName, String encoding) {
            this.deviceName = deviceName;
            this.encoding = encoding;
        }

        public String getResultText() {
            return resultText;
        }

        public void run() {
            try {
                logger.debug("run");
                ShtrihFiscalPrinter printer = new ShtrihFiscalPrinter(
                        new FiscalPrinter(), encoding);
                printer.open(deviceName);
                printer.setPowerNotify(printer.JPOS_PN_ENABLED);
                printer.claim(0);
                printer.setDeviceEnabled(true);
                //printer.close();

                logger.debug("OK");
            } catch (Exception e) {
                logger.error("Failed", e);
                resultText = "Failed: " + e.getMessage();
            }
        }
    }

    public class CashDrawerTest implements Runnable {

        private String resultText = "";
        private final String deviceName;
        private final String encoding;
        private Logger logger = Logger.getLogger(CashDrawerTest.class);

        public CashDrawerTest(String deviceName, String encoding) {
            this.deviceName = deviceName;
            this.encoding = encoding;
        }

        public String getResultText() {
            return resultText;
        }

        public void run() {
            try {
                logger.debug("run");
                CashDrawer drawer = new CashDrawer();
                drawer.open(deviceName);
                drawer.claim(0);
                drawer.setDeviceEnabled(true);
                //drawer.close();

                logger.debug("OK");
            } catch (Exception e) {
                logger.error("Failed", e);
                resultText = "Failed: " + e.getMessage();
            }
        }
    }
}
