//
//  Sample.swift
//  SiiLibSample
//

import UIKit
import SwiftUI

class SampleFunctions {
    // Create a printerManager instance
    fileprivate static var _printerManager: SIIPrinterManagerWrapper!
    // Create a smart label instance
    fileprivate static var _labelManager: SIISmartLabelManagerWrapper!
    // Used for discoveries
    fileprivate static var _printerDiscoveryCompletion  = false
    // Used for showing results
    fileprivate static var _resultMessage = ""

    /// Initial settings when view is loaded
    static func InitialSetting() {
        self._printerManager = SIIPrinterManagerWrapper()
        self._labelManager = SIISmartLabelManagerWrapper()
        self._printerDiscoveryCompletion = false
        self._resultMessage = ""
    }
    
    /// Sample for connecting to printer
    static func connectSample(_ model: Int32, _ address: String, _ type: Int32) -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            try self._printerManager.connect(model, address: address, portType: type)
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }

    /// Sample for disconnect
    static func disconnectSample() -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            // Get printer response before disconnect is recommended
            _ = response_request()
            try self._printerManager.disconnect()
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }
    
    /// Sample for printing a stand mode sample receipt
    static func standardModeSample() -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            // Store internationalCharacter and codePage settings and reset the settings at the end of the process.
            let internationalCharacter = self._printerManager.internationalCharacter
            let codePage = self._printerManager.codePage
            defer {
                // Reset the settings of internationalCharacter and codePage.
                self._printerManager.internationalCharacter = internationalCharacter
                self._printerManager.codePage = codePage

                // Get printer response to confirm printing is finished
                _ = response_request()
            }
            var receiptStr = ""
            
            // Get current system language to set language for receipt
            let lang = Locale.preferredLanguages[0]
            if lang.hasPrefix("ja") {
                //  Set internationalCharacter and codePage of printer to Japanese for printing a Japanese receipt
                self._printerManager.internationalCharacter = SII_PM_COUNTRY_JAPAN
                self._printerManager.codePage = SII_PM_CODE_PAGE_KATAKANA
                receiptStr = "\n" +
                "--------------------------------\n" +
                "ｸﾞﾘﾙﾄﾞﾁｷﾝﾌﾞﾚｽﾄ            ¥1,850\n" +
                "ｻｰﾛｲﾝｽﾃｰｷ                 ¥3,200\n" +
                "ﾛｰｽﾄﾗﾑ                    ¥2,000\n" +
                "ｻﾗﾀﾞ                      ¥1,000\n" +
                "ｸｯｷｰ                        ¥350\n" +
                "ｸｯｷｰ                        ¥350\n" +
                "ｱｲｽｸﾘｰﾑ                     ¥500\n" +
                "ﾁｭｳｶｿﾊﾞ                   ¥1,500\n" +
                "ｽｷﾔｷ                      ¥3,000\n" +
                "ｻﾝﾄﾞｲｯﾁ                   ¥1,000\n" +
                "ﾋﾟｻﾞ                      ¥2,000\n" +
                "ｺｳﾁｬ                        ¥350\n" +
                "ｺｰﾋｰ                        ¥350\n" +
                "\n" +
                "--------------------------------\n" +
                "        小計             ¥17,450\n" +
                "        消費税              ¥873\n" +
                "        合計             ¥18,323\n" +
                "\n" +
                "ご利用ありがとうございます\n" +
                "またのご利用をお待ちしております\n\n"
            } else {
                //  Set internationCharacter and codePage of printer to English for printing an English receipt
                self._printerManager.internationalCharacter = SII_PM_COUNTRY_USA
                self._printerManager.codePage = SII_PM_CODE_PAGE_1252
                receiptStr = "\n" +
                "--------------------------------\n" +
                "GRILLED CHICKEN BREAST    $18.50\n" +
                "SIRLOIN STEAK             $32.00\n" +
                "ROAST LAMB                $20.00\n" +
                "SALAD                     $10.00\n" +
                "COKE                       $3.50\n" +
                "COKE                       $3.50\n" +
                "ICE CREAM                  $5.00\n" +
                "CHINESE NOODLE            $15.00\n" +
                "SUKIYAKI                  $30.00\n" +
                "SANDWICH                  $10.00\n" +
                "PIZZA                     $20.00\n" +
                "TEA                        $3.50\n" +
                "COFFEE                     $3.50\n" +
                "\n" +
                "--------------------------------\n" +
                "        SUBTOTAL         $174.50\n" +
                "        SALES TAX          $8.73\n" +
                "        TOTAL            $183.23\n" +
                "\n" +
                "Thank you and see you again!\n\n"
            }
            
            // Print image with center alignment and dithering
            let fileName = Bundle.main.path(forResource: "logo", ofType: "jpg")!
            try self._printerManager.sendDataFile(fileName, alignment: .SII_PM_ALIGNMENT_CENTER, dithering: .SII_PM_DITHERING_ERRORDIFFUSION)
            
            // Get current date
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
            let date = Date()
            let dateFormatted = dateFormatter.string(from: date)
            let dateText = "\nNo.00001    " + dateFormatted
            
            // Print current date with center alignment
            try self._printerManager.sendTextEx(dateText, bold: .SII_PM_BOLD_CANCEL, underline: .SII_PM_UNDERLINE_CANCEL, reverse: .SII_PM_REVERSE_CANCEL, inversion: .SII_PM_INVERSION_CANCEL, font: .SII_PM_FONT_A, scale: .SII_PM_VARTICAL_1_HORIZONTAL_1, alignment: .SII_PM_ALIGNMENT_CENTER)
            
            // Print receipt details with center alignment
            try self._printerManager.sendTextEx(receiptStr, bold: .SII_PM_BOLD_CANCEL, underline: .SII_PM_UNDERLINE_CANCEL, reverse: .SII_PM_REVERSE_CANCEL, inversion: .SII_PM_INVERSION_CANCEL, font: .SII_PM_FONT_A, scale: .SII_PM_VARTICAL_1_HORIZONTAL_1, alignment: .SII_PM_ALIGNMENT_CENTER)
            
            // DPU-S245 & DPU-S445
            if self._printerManager.printerModel == SII_PM_PRINTER_MODEL_DPU_S245 || self._printerManager.printerModel == SII_PM_PRINTER_MODEL_DPU_S445 {
                // Print a QRcode
                let qrData = "QR Sample"
                try self._printerManager.printQRcode(qrData, errorCorrection: .SII_PM_QR_ERROR_CORRECTION_M, moduleSize: .SII_PM_QR_MODULE_SIZE_4, alignment: .SII_PM_ALIGNMENT_LEFT, model: .SII_PM_QR_MODEL_2)
                
                // Print an EAN13 barcode
                try self._printerManager.printBarcode(.SII_PM_BARCODE_EAN13, text: "012345678901", moduleSize: .SII_PM_BARCODE_MODULE_WIDTH_3, moduleHeight: 80, hriPosition: .SII_PM_HRI_POSITION_BELOW, hriFont: .SII_PM_FONT_A, alignment: .SII_PM_ALIGNMENT_LEFT)
            } else {
                // Print a QRcode
                let qrData = "QR Sample"
                try self._printerManager.printQRcode(qrData, errorCorrection: .SII_PM_QR_ERROR_CORRECTION_M, moduleSize: .SII_PM_QR_MODULE_SIZE_4, alignment: .SII_PM_ALIGNMENT_CENTER, model: .SII_PM_QR_MODEL_2)
                
                // Print an EAN13 barcode
                try self._printerManager.printBarcode(.SII_PM_BARCODE_EAN13, text: "0123456789012", moduleSize: .SII_PM_BARCODE_MODULE_WIDTH_3, moduleHeight: 80, hriPosition: .SII_PM_HRI_POSITION_BELOW, hriFont: .SII_PM_FONT_A, alignment: .SII_PM_ALIGNMENT_CENTER)
                /// Specify the barcode for CODE93 (Data:12345)
                /// How to binary input.
                /// 1. Input any data from 00H to 2EH. Multiple data can be input
                /// 2. Input 2FH or more lastly as the stop code
                //  let rawArray: [UInt8] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x2F]
                //  let data = rawArray.withUnsafeBufferPointer({Data(buffer: $0)})
                //  try self._printerManager.printBarcode(.SII_PM_BARCODE_CODE93, data: data, moduleSize: .SII_PM_BARCODE_MODULE_WIDTH_3, moduleHeight: 80, hriPosition: .SII_PM_HRI_POSITION_BELOW, hriFont: .SII_PM_FONT_A, alignment: .SII_PM_ALIGNMENT_CENTER)
                
                // Partial cut with pre-feed
                // If using printer does not have cutter, it will only feed paper
                try self._printerManager.cutPaper(.SII_PM_CUT_PARTIAL)
            }
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }
    
    /// Sample for printing a page mode sample
    static func printPageModeSample() -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do{
            defer {
                // Get printer response to confirm printing is finished
                _ = response_request()
                // Exit page mode finally
                try? self._printerManager.exitPageMode()
            }
            // Start page mode
            try self._printerManager.enterPageMode()
            
            // Specify the print area in page mode
            // The number of printable dots in one dot line has to be set to 355 dots for this sample code.
            try self._printerManager.setPageModeArea(0, y: 0, width: 355, height: 576)
            
            // Specify the rectangle and the rule
            try self._printerManager.printPageModeRectangle(0, startY: 0, endX: 344, endY: 575, lineStyle: .SII_PM_LINESTYLE_THIN)
            try self._printerManager.printPageModeRectangle(7, startY: 7, endX: 336, endY: 567, lineStyle: .SII_PM_LINESTYLE_THIN)
            try self._printerManager.printPageModeLine(11, startY: 404, endX: 334, endY: 404, lineStyle: .SII_PM_LINESTYLE_THIN)
            
            // Specify the print direction in page mode
            try self._printerManager.setPageModeDirection(.SII_PM_DIRECTION_TOP_TO_BOTTOM)
            
            // Specify the text
            try self._printerManager.printPageModeText(21, startY: 47, text: "No.123456789")
            try self._printerManager.printPageModeText(212, startY: 340, text: "Date 2023-01-01")
            
            // Specify the image file
            let filePath = Bundle.main.path(forResource: "TicketImage", ofType: "jpg")
            try self._printerManager.printPageModeImageFile(10, startY: 222, fileName: filePath, dithering: .SII_PM_DITHERING_DISABLE)
            
            // Specify the print area in page mode
            try self._printerManager.setPageModeArea(0, y: 404, width: 345, height: 163)
            
            // Specify the direction of the print
            try self._printerManager.setPageModeDirection(.SII_PM_DIRECTION_LEFT_TO_RIGHT)
            
            // Specify the barcode for CODE128
            let rawArray: [UInt8] = [0x67, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x68]
            let data = rawArray.withUnsafeBufferPointer({Data(buffer: $0)})
            try self._printerManager.printPageModeBarcode(20, startY: 132, barcodeSymbol: .SII_PM_BARCODE_CODE128, data: data, moduleSize: .SII_PM_BARCODE_MODULE_WIDTH_2, moduleHeight: 80, hriPosition: .SII_PM_HRI_POSITION_ABOVE, hriFont: .SII_PM_FONT_A)
            
            /// Specify the barcode for CODE128 (Data:123456789)
            /// How to input using the CODE128 Code Set table
            /// 1. Input the start code of 67H(Code Set A), 68H(Code Set B), or 69H(Code Set C) shown in the table of CODE128 Code Set
            /// 2. Input any data from 00H to 66H. Multiple data can be input
            /// 3. Input 67H or more lastly as the stop code
            //  let rawArray: [UInt8] = [0x68, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x67]
            //  let data = rawArray.withUnsafeBufferPointer({Data(buffer: $0)})

            /// How to input using the CODE128 Special Code Set table
            /// 1. Input the start code (START A, START B, or START C) of the code set to be selected shown in the table of CODE128 Special Code
            /// 2. Input the data in the respective formats
            ///       Code Set A : Data from 00H to 5FH can be input
            ///       Code Set B : Data from 20H to 7FH can be input
            ///       Code Set C : Data from 00H(00) to 63H(99) can be input
            //  let rawArray: [UInt8] = [0x7B, 0x42, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39]
            //  let data = rawArray.withUnsafeBufferPointer({Data(buffer: $0)})
            //  try self._printerManager.printPageModeBarcode(10, startY: 132, barcodeSymbol: .SII_PM_BARCODE_CODE128, data: data, moduleSize: .SII_PM_BARCODE_MODULE_WIDTH_2, moduleHeight: 80, hriPosition: .SII_PM_HRI_POSITION_ABOVE, hriFont: .SII_PM_FONT_A)
            
            // Print the page mode and partial cut with pre-feed
            // If using printer does not have cutter, it will only feed paper
            try self._printerManager.printPageMode(.SII_PM_CUT_PARTIAL)
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }
    
    /// Sample for printing a sample smart label
    static func smartLabelSample() -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            defer {
                // Get printer response to confirm printing is finished
                _ = response_request()
            }
            
            // Specify a label file(*.sl) to print or replace data.
            // Sample.sl is defined following objects.
            //  * Text    Object (ID = 1) : "Jane Smith"
            //  * Image   Object (ID = 1) : woman.jpg
            //  * Barcode Object (ID = 1) : "0123456" (Code128)
            // Label Type of Sample.sl is User Paper[ Printer:MP-B21L, PaperType:Receipt, PositionDetection:None, PaperWidth58mm, PaperLength:300mm ].
            let path = Bundle.main.path(forResource: "Sample", ofType: "sl")!
            try self._labelManager.selectSmartLabelFile(path)
            
            // Print Smart Label image
            try self._printerManager.printSmartLabelImageData(_labelManager.labelManager)
            
            // Replace the text data with "John Smith".
            try self._labelManager.replaceSmartLabelTextData(1, text: "John Smith")
            
            // Get image data for replacement
            let imagePath = Bundle.main.path(forResource: "man", ofType: "jpg")!
            let image = UIImage(contentsOfFile: imagePath)
            // Replace the image data with "man.jpg".
            try self._labelManager.replaceSmartLabelImageData(1, image: image)
            
            // Replace the barcode data with "ABCDEFG".
            try self._labelManager.replaceSmartLabelBarcodeData(1, text: "ABCDEFG")
            
            // Print Smart Label image
            try self._printerManager.printSmartLabelImageData(_labelManager.labelManager)
            
            // Full cut with pre-feed.
            try self._printerManager.cutPaper(.SII_PM_CUT_FULL)
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }
    
    /// Sample for showing payment samples in display
    static func displaySample() -> Bool {
        self._resultMessage = STR_SUCCEEDED
        
        var displayData = DisplayData()
        var result = true
        do {
            try result = displaySample_total(total: displayData.total)
            let lang = Locale.preferredLanguages[0]
            for _ in 0..<5 {
                displayData.pickAnItem(lang: lang)
                try result = displaySample_detail(subTotal: displayData.total, itemName: displayData.itemName, price: displayData.itemPrice)
            }
            displayData.calculateTotal()
            try result = displaySample_payment(total:displayData.total, paid:displayData.paid, change:displayData.change)
            try result = SampleFunctions.displaySample_standby()
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return result
    }
    
    /// Sample for sending file to printer
    static func sendDataFileSample(_ filePath: String) -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            defer {
                // Get printer response to confirm printing is finished
                _ = response_request()
            }
            // Specifiy the print or data file.
            try self._printerManager.sendDataFile(filePath, alignment:.SII_PM_ALIGNMENT_LEFT)
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }

    /// Sample for print PDF file
    static func printPDFSample(_ filePath: String) -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            defer {
                // Get printer response to confirm printing is finished
                _ = response_request()
            }
            // Specifies the print PDF file.
            // To print all pages of a PDF file, set “startIndex” to -1.
            try self._printerManager.printPDF(
                    filePath,
                    start: -1,
                    end: -1,
                    rotate: .SII_PM_ROTATE_NONE,
                    imageScale: .SII_PM_IMAGE_SCALE_WIDTH_FIT,
                    bottomMargin: -1,
                    dithering: .SII_PM_DITHERING_ERRORDIFFUSION,
                    alignment: .SII_PM_ALIGNMENT_CENTER
                )
            // To print any page of a PDF file
            // Example: To print pages 2 through 5, specify 2 for “startIndex” and 5 for “endIndex”.
//            try self._printerManager.printPDF(
//                    filePath,
//                    start: 2,
//                    end: 5,
//                    rotate: .SII_PM_ROTATE_NONE,
//                    imageScale: .SII_PM_IMAGE_SCALE_WIDTH_FIT,
//                    bottomMargin: -1,
//                    dithering: .SII_PM_DITHERING_ERRORDIFFUSION,
//                    alignment: .SII_PM_ALIGNMENT_CENTER
//                )
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }

    /// Sample for opening external drawer
    static func openDrawerSample() -> Bool {
        self._resultMessage = STR_SUCCEEDED
        do {
            // Specify the drawer you want to open.
            try self._printerManager.openDrawer(.SII_PM_DRAWER_1, onOffTime: .SII_PM_ON_OFF_TIME_100)
        } catch let error as NSError {
            self._resultMessage = getErrorMessage(Int32(error.code))
            return false
        }
        return true
    }

    /// Sample for starting lan printer discovery
    static func startLanDiscoveryPrinterSample(_ retryCount: Int, _ timeout: Int) {
        self._printerDiscoveryCompletion  = false
        self._printerManager.startDiscoveryPrinter(retryCount, timeout: timeout, completion: { (printerList:[Any]!) in
            // Set discovery completion flag to true when discovery completed
            self._printerDiscoveryCompletion  = true
        })
    }

    /// Sample for get lan printer discovery result
    static func getPrinterDiscoveryComletion() -> Bool {
        return self._printerDiscoveryCompletion
    }

    /// Sample for starting bluetooth printer discovery
    static func startBluetoothDiscoveryPrinterSample() {
        self._printerManager.startDiscoveryPrinter(nil, completion: nil)
    }

    /// Sample for cancel printer discovery immediately
    static func cancelDiscoveryPrinterSample() {
        self._printerManager.cancelDiscoveryPrinter()
    }

    /// Sample for getting discovered printer list
    static func getFoundPrinterSample() -> [Any] {
        var foundPrinterList = [Any]()
        let foundPrinterListOptional = self._printerManager.getFoundPrinter()
        if let foundPrinterListBinded = foundPrinterListOptional {
            foundPrinterList = foundPrinterListBinded
        }
        return foundPrinterList
    }
    
    /// Get SDK version
    static func getVersionSample() -> String {
        return self._printerManager.getVersion()!
    }

    static func get_sentTimeoutSample() -> Int32 {
        return _printerManager.sendTimeout
    }

    static func set_sendTimeoutSample(time: Int32) -> Int32{
        _printerManager.sendTimeout = time

        if _printerManager.sendTimeout == time {
            _resultMessage = STR_SUCCEEDED
        } else {
            _resultMessage = "sendTimeout is rounded"
        }
        return _printerManager.sendTimeout
    }

    static func get_receiveTimeoutSample() -> Int32 {
        return _printerManager.receiveTimeout
    }

    static func set_receiveTimeoutSample(time: Int32)  -> Int32{
        _printerManager.receiveTimeout = time

        if _printerManager.receiveTimeout == time {
            _resultMessage = STR_SUCCEEDED
        } else {
            _resultMessage = "receiveTimeout is rounded"
        }
        return _printerManager.receiveTimeout
    }

    static func get_internationalCharacterSample() -> Int32 {
        return _printerManager.internationalCharacter
    }

    static func set_internationalCharacterSample(internationalCharacter: Int32)  -> Int32{
        _printerManager.internationalCharacter = internationalCharacter

        if _printerManager.internationalCharacter == internationalCharacter {
            _resultMessage = STR_SUCCEEDED
        } else {
            _resultMessage = "Fail to set internationalCharacter"
        }
        return _printerManager.internationalCharacter
    }

    static func get_codePageSample() -> Int32 {
        return _printerManager.codePage
    }

    static func set_codePageSample(codePage: Int32)  -> Int32{
        _printerManager.codePage = codePage

        if _printerManager.codePage == codePage {
            _resultMessage = STR_SUCCEEDED
        } else {
            _resultMessage = "Fail to set codePage"
        }
        return _printerManager.codePage
    }

    static func get_socketKeepingTimeSample() -> Int32 {
        return _printerManager.socketKeepingTime
    }

    static func set_socketKeepingTimeSample(time: Int32)  -> Int32{
        _printerManager.socketKeepingTime = time

        if _printerManager.socketKeepingTime == time {
            _resultMessage = STR_SUCCEEDED
        } else {
            _resultMessage = "socketKeepingTime is rounded"
        }
        return _printerManager.socketKeepingTime
    }

    static func getResultMessage() -> String {
        return self._resultMessage
    }
    
    /// Set a SIIPrinterManagerDelegate instance as delegate referred to Status class
    static func setDelegate(delegate: Status) {
        self._printerManager.delegate = delegate
    }
    
    /// Set a SIIPrinterManagerDelegate instance to nil to disable delegate
    static func disableDelegate() {
        self._printerManager.delegate = nil
    }
    
    /// Sample using object selection and template showing #1
    static func displaySample_total(total: Int) throws -> Bool {
        var result = true
        
        // Change the display content to match the language of the device.
        var templateID: Int32 = 119
        var rate = 100
        var currencyUnit = "$"
        var title = "Total"
        var strTotal = ""
        
        let lang = Locale.preferredLanguages[0]
        if lang.hasPrefix("ja") {
            //Language used: Japanese
            self._printerManager.internationalCharacter = SII_PM_COUNTRY_JAPAN
            self._printerManager.codePage = SII_PM_CODE_PAGE_KATAKANA
            
            currencyUnit = "¥"
            rate = 1
            title = "合計"
            templateID = 120
            
            strTotal = currencyUnit + (String)(total/rate)
        } else {
            //Language used: English
            self._printerManager.internationalCharacter = SII_PM_COUNTRY_USA
            self._printerManager.codePage = SII_PM_CODE_PAGE_1252
            
            strTotal = currencyUnit + (String)(total/rate) + "." + (String)(total%rate)
        }
        
        do {  
            // Select template (ID=119 : for List Up(En)) with Slide 80
            // Select template (ID=120 : for List Up(Jp)) with Slide 80
            try self._printerManager.selectTemplate(templateID, slideID: 80)
            
            // Select Text area 0
            try self._printerManager.selectTemplateTextObject(0)
            try self._printerManager.setTemplateTextData(title)
            
            // Select Text area 1
            try self._printerManager.selectTemplateTextObject(1)
            try self._printerManager.setTemplateTextData(strTotal)
            
            // Display
            try self._printerManager.showTemplate(0)
            Thread.sleep(forTimeInterval: 0.3)
        } catch let error as NSError {
            result = false
            throw error
        }
        return result
    }
    
    /// Sample using object selection and template showing #2
    static func displaySample_detail(subTotal: Int, itemName: String, price: Int) throws -> Bool {
        var result = true
        
        // Change the display content to match the language of the device.
        var rate = 100
        var currencyUnit = "$"
        var strSubTotal = ""
        var strPrice = ""
        
        let lang = Locale.preferredLanguages[0]
        if lang.hasPrefix("ja") {
            //Language used: Japanese
            self._printerManager.internationalCharacter = SII_PM_COUNTRY_JAPAN
            self._printerManager.codePage = SII_PM_CODE_PAGE_KATAKANA
            
            currencyUnit = "¥"
            rate = 1
            
            strSubTotal = currencyUnit + (String)(subTotal/rate)
            strPrice = currencyUnit + (String)(price/rate)
        } else {
            //Language used: English
            self._printerManager.internationalCharacter = SII_PM_COUNTRY_USA
            self._printerManager.codePage = SII_PM_CODE_PAGE_1252
            strSubTotal = currencyUnit + (String)(subTotal/rate) + "." + (String)(subTotal%rate)
            strPrice = currencyUnit + (String)(price/rate) + "." + (String)(price%rate)
        }
        
        do {
            // Select Text area 1
            try self._printerManager.selectTemplateTextObject(1)
            try self._printerManager.setTemplateTextData(strSubTotal)
            
            // Select Text area 6
            try self._printerManager.selectTemplateTextObject(6)
            try self._printerManager.setTemplateTextData(itemName)
            
            // Select Text area 7
            try self._printerManager.selectTemplateTextObject(7)
            try self._printerManager.setTemplateTextData(strPrice)
            
            // Display
            try self._printerManager.showTemplate(0)
            Thread.sleep(forTimeInterval: 0.3)
        } catch let error as NSError {
            result = false
            throw error
        }
        return result
    }
    
    /// Sample using object selection and template showing #3
    static func displaySample_payment(total: Int, paid: Int, change: Int) throws -> Bool {
        var result = true
        
        // Change the display content to match the language of the device.
        var templateID: Int32 = 123
        var slideID: Int32 = 82
        var rate = 100
        var currencyUnit = "$"
        var strTotal = ""
        var strPaid = ""
        var strChange = ""
        
        let lang = Locale.preferredLanguages[0]
        if lang.hasPrefix("ja") {
            //Language used: Japanese
            self._printerManager.internationalCharacter = SII_PM_COUNTRY_JAPAN
            self._printerManager.codePage = SII_PM_CODE_PAGE_KATAKANA
            
            currencyUnit = "¥"
            rate = 1
            templateID = 124
            slideID = 83
            
            strTotal = currencyUnit + (String)(total/rate)
            strPaid = currencyUnit + (String)(paid/rate)
            strChange = currencyUnit + (String)(change/rate)
        } else {
            //Language used: English
            self._printerManager.internationalCharacter = SII_PM_COUNTRY_USA
            self._printerManager.codePage = SII_PM_CODE_PAGE_1252
            
            strTotal = currencyUnit + (String)(total/rate) + "." + (String)(total%rate)
            strPaid = currencyUnit + (String)(paid/rate) + "." + (String)(paid%rate)
            strChange = currencyUnit + (String)(change/rate) + "." + (String)(change%rate)
        }
        
        do {
            // Select template (ID=123 : for 3 lines(En)) with Slide 82
            // Select template (ID=124 : for 3 lines(Jp)) with Slide 83
            try self._printerManager.selectTemplate(templateID, slideID: slideID)
            
            // Select Text area 3
            try self._printerManager.selectTemplateTextObject(3)
            try self._printerManager.setTemplateTextData(strTotal)
            
            // Select Text area 4
            try self._printerManager.selectTemplateTextObject(4)
            try self._printerManager.setTemplateTextData(strPaid)
            
            // Select Text area 5
            try self._printerManager.selectTemplateTextObject(5)
            try self._printerManager.setTemplateTextData(strChange)
            
            // Display
            try self._printerManager.showTemplate(0)
            Thread.sleep(forTimeInterval: 3.0)
        } catch let error as NSError {
            result = false
            throw error
        }
        return result
    }
    
    /// Sample of putting the display on standby
    static func displaySample_standby() throws -> Bool {
        var result = true
        do {
            try self._printerManager.enterStandbyMode()
        } catch let error as NSError {
            result = false
            throw error
        }
        return result
    }
    
    /// Sample of getting printer response
    static func response_request() -> Bool {
        do {
            // When getting response success, response code will be saved in val.
            var val = [0] as [Int]
            try self._printerManager.getPrinterResponse(SII_PM_PRINTER_RESPONSE_REQUEST, param: 0x00, response: &val)
            return true
        } catch _ as NSError {
            return false
        }
    }

    static func getErrorMessage(_ errorCode: Int32) -> String {
        switch errorCode {
            case SII_PM_ERROR_ACCESS_DENIED:
                return "Exception:ACCESS_DENIED"
            case SII_PM_ERROR_SHARING_VIOLATION:
                return "Exception:SHARING_VIOLATION"
            case SII_PM_ERROR_PORT_NOT_OPENED:
                return "Exception:PORT_NOT_OPENED"
            case SII_PM_ERROR_DEVICE_NOT_CONNECTED:
                return "Exception:DEVICE_NOT_CONNECTED"
            case SII_PM_ERROR_OFFLINE:
                return "Exception:OFFLINE"
            case SII_PM_ERROR_EXTERNAL_DEVICE_NOT_CONNECTED:
                return "Exception:EXTERNAL_DEVICE_NOT_CONNECTED"
            case SII_PM_ERROR_DEVICE_INITIALIZE_FAILED:
                return "Exception:DEVICE_INITIALIZE_FAILED"
            case SII_PM_ERROR_DATA_SIZE_ZERO:
                return "Exception:DATA_SIZE_ZERO"
            case SII_PM_ERROR_OVER_MAX_DATA_SIZE:
                return "Exception:OVER_MAX_DATA_SIZE"
            case SII_PM_ERROR_DATA_SIZE_INVALID:
                return "Exception:DATA_SIZE_INVALID"
            case SII_PM_ERROR_ENCODE_FAILED:
                return "Exception:ENCODE_FAILED"
            case SII_PM_ERROR_TIMEOUT:
                return "Exception:TIMEOUT"
            case SII_PM_ERROR_FILE_NOT_FOUND:
                return "Exception:FILE_NOT_FOUND"
            case SII_PM_ERROR_FILE_USED:
                return "Exception:FILE_USED"
            case SII_PM_ERROR_FILE_INVALID:
                return "Exception:FILE_INVALID"
            case SII_PM_ERROR_LOW_MEMORY:
                return "Exception:LOW_MEMORY"
            case SII_PM_ERROR_OVER_MAX_IMAGE:
                return "Exception:OVER_MAX_IMAGE"
            case SII_PM_ERROR_LOGO_NOT_DEFINED:
                return "Exception:LOGO_NOT_DEFINED"
            case SII_PM_ERROR_LOW_USER_AREA:
                return "Exception:LOW_USER_AREA"
            case SII_PM_ERROR_LOW_EXTERNAL_RAM:
                return "Exception:LOW_EXTERNAL_RAM"
            case SII_PM_ERROR_NOT_REGISTERD:
                return "Exception:NOT_REGISTERD"
            case SII_PM_ERROR_NOT_UNREGISTERD:
                return "Exception:NOT_UNREGISTERD"
            case SII_PM_ERROR_INVALID_NO:
                return "Exception:INVALID_NO"
            case SII_PM_ERROR_OVER_STYLE_NUM:
                return "Exception:OVER_STYLE_NUM"
            case SII_PM_ERROR_INVALID_DATA:
                return "Exception:INVALID_DATA"
            case SII_PM_ERROR_PAGE_MODE_SPECIFIED:
                return "Exception:PAGE_MODE_SPECIFIED"
            case SII_PM_ERROR_PAGE_MODE_NOT_SPECIFIED:
                return "Exception:PAGE_MODE_NOT_SPECIFIED"
            case SII_PM_ERROR_LABEL_FILE_NOT_SELECTED:
                return "Exception:LABEL_FILE_NOT_SELECTED"
            case SII_PM_ERROR_GET_LABEL_IMAGE:
                return "Exception:GET_LABEL_IMAGE"
            case SII_PM_ERROR_INVALID_PARAM:
                return "Exception:INVALID_PARAM"
            default:
                return "Exception:Unknown error"
        }
    }
}
