////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Datacard Corporation.  All Rights Reserved.
////////////////////////////////////////////////////////////////////////////////
package common_java;

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import common_java.XPS_Java_SDK.XpsDriverInteropLib;

public class PrinterOptions {
    private String mPrinterName;
    
    public String  _colorPrintResolution = "";
    public String  _connectionPortType = "";
    public String  _connectionProtocol = "";
    public String  _embosserVersion = "";
    public String  _laminator = "";
    public String  _laminatorFirmwareVersion = "";
    public String  _laminatorImpresser = "";
    public String  _laminatorScanner = "";
    public String  _lockState = "";
    public String  _moduleEmbosser = "";
    public String  _monochromePrintResolution = "";
    public String  _optionDuplex = "";
    public String  _multiHopperVersion = "";
    public String  _optionInputHopperType = "";
    public String  _optionInputhopper = "";
    public String  _optionObscureBlackPanel = "";
    public String  _optionLocks = "";
    public String  _optionMagstripe = "";
    public String  _optionSecondaryMagstripeJIS = "";
    public String  _optionPrinterBarcodeReader = "";
    public String  _optionRewrite = "";
    public String  _optionSmartcard = "";
    public String  _optionTactileImpresser = "";
    public String  _printEngineType = "";
    public String  _printerAddress = "";
    public int     _printerMessageNumber = 0;	
    public String  _printerModel = "";
    public String  _printerSerialNumber = "";
    public String  _printerStatus = "";
    public String  _printerVersion = "";
    public String  _printHead = "";
    public String  _topcoatPrintResolution = "";
    public String  _rearPickOption = "";
    public String  _kioskOption = "";
    public String  _optionUVCure = "";

    public PrinterOptions(String aPrinterName) {
        mPrinterName = aPrinterName;
    }

    public String GetPrinterOptions() {
        byte returnBuffer[] = new byte[XPS_Java_SDK.BUFFSIZE];
        int bufferSize[] = new int[1];
        bufferSize[0] = XPS_Java_SDK.BUFFSIZE;
        int S_OK = 0;
        int hResult = -1; // not S_OK
        String returnValue = "";

        // get driver SDK version
        hResult = XpsDriverInteropLib.INSTANCE.GetSDKVersion(mPrinterName, returnBuffer, bufferSize);

        returnValue = cStringToJavaString(returnBuffer, bufferSize[0]);
        if (S_OK == hResult) {
            System.out.format("'%s' GetSDKVersion() return length: %d\n\n%s\n", mPrinterName,
                    bufferSize[0], returnValue);
        } else {
            System.out.format("GetSDKVersion() failed. Return buffersize = %d\n %s", bufferSize[0],
                    returnValue);
            return returnValue;
        }
        // reset buffersize
        bufferSize[0] = bufferSize[0] = XPS_Java_SDK.BUFFSIZE;

        // call driver to get printer options
        hResult = XpsDriverInteropLib.INSTANCE.GetPrinterOptions2(mPrinterName, returnBuffer,
                bufferSize);

        //returnValue = PrinterStatusXML.cStringToJavaString(returnBuffer, bufferSize[0]);
        returnValue = cStringToJavaString(returnBuffer, bufferSize[0]);
        if (S_OK == hResult) {
            System.out.format("'%s' GetPrinterOptions() return length: %d\n\n%s", mPrinterName,
                    bufferSize[0], returnValue);
        } else {
            System.out.format("GetPrinterOptions() failed. Return buffersize = %d\n %s",
                    bufferSize[0], returnValue);
        }

        return returnValue;
    }
    

    
    ///////////////////////////////////////////////
    // GetPrinterOptionValue()
    //////////////////////////////////////////////
    private String GetPrinterOptionValue( Element eElement, String optionName) {
    	String str = "";
    	try {
            NodeList nodeList = eElement.getElementsByTagName(optionName).item(0).getChildNodes();
            Node nodeValue = (Node) nodeList.item(0);
            str = nodeValue.getNodeValue();                       
		} catch (Exception e) {
			// do nothing
			// the option may not be specified for this printer and that is OK
		}
    	return str;
    }

    
    ///////////////////////////////////////////////
    // cStringToJavaString()
    //////////////////////////////////////////////
    private static String cStringToJavaString(byte b[], int bufferLength) {
        // Converts C string to Java String
        int len = 0;
        while (len < bufferLength && b[len] != 0) {
            ++len;
        }

        if (len > bufferLength) {
            len = bufferLength;
        }

        return new String(b, 0, len);
    }

    ///////////////////////////////////////////////
    // ParsePrinterOptions()
    //////////////////////////////////////////////
    public void ParsePrinterOptions(byte returnXML[], int sizeOfReturnXML[]) 
    {        
    	try {
	    	String xmlString = null;
	        if (returnXML != null && sizeOfReturnXML != null && sizeOfReturnXML[0] > 0) {
	        	xmlString = cStringToJavaString(returnXML, sizeOfReturnXML[0]);
	        }        
     	            	
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xmlString));

            Document doc = dBuilder.parse(is);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getElementsByTagName("PrinterInfo2");

			// FYI - there should only be one item in the nodelist
            for (int nodeListIndex = 0; nodeListIndex < nodeList.getLength(); nodeListIndex++) {
                Node node = nodeList.item(nodeListIndex);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element tElement = (Element) node;
	                _colorPrintResolution = GetPrinterOptionValue(tElement, "ColorPrintResolution");
	                _connectionPortType   = GetPrinterOptionValue(tElement, "ConnectionPortType");
	                _connectionProtocol   = GetPrinterOptionValue(tElement, "ConnectionProtocol");
	                _embosserVersion      = GetPrinterOptionValue(tElement, "EmbosserVersion");
	                _laminator            = GetPrinterOptionValue(tElement, "Laminator");
	                _laminatorFirmwareVersion = GetPrinterOptionValue(tElement, "LaminatorFirmwareVersion");
	                _laminatorImpresser   = GetPrinterOptionValue(tElement, "LaminatorImpresser");
	                _laminatorScanner     = GetPrinterOptionValue(tElement, "LaminatorScanner");
	                _lockState            = GetPrinterOptionValue(tElement, "LockState");
	                _moduleEmbosser       = GetPrinterOptionValue(tElement, "ModuleEmbosser");
	                _monochromePrintResolution = GetPrinterOptionValue(tElement, "MonochromePrintResolution");
	                _optionDuplex         = GetPrinterOptionValue(tElement, "OptionDuplex");
	                _multiHopperVersion   = GetPrinterOptionValue(tElement, "MultiHopperVersion");
	                _optionInputHopperType = GetPrinterOptionValue(tElement, "OptionInputHopperType");
	                _optionInputhopper    = GetPrinterOptionValue(tElement, "OptionInputHopper");
	                _optionLocks          = GetPrinterOptionValue(tElement, "OptionLocks");
	                _optionMagstripe      = GetPrinterOptionValue(tElement, "OptionMagstripe");
	                _optionSecondaryMagstripeJIS = GetPrinterOptionValue(tElement, "OptionSecondaryMagstripeJIS");
	                _optionSmartcard      = GetPrinterOptionValue(tElement, "OptionSmartcard");
	                _printerAddress       = GetPrinterOptionValue(tElement, "PrinterAddress");
	                
	                //_printerMessageNumber = Integer.parseInt(GetPrinterOptionValue(tElement, "PrinterMessageNumber"));
	                String temp = GetPrinterOptionValue(tElement, "PrinterMessageNumber");
	                if (temp != "") {
	                	_printerMessageNumber = Integer.parseInt(temp);
	                }

	                _printerModel         = GetPrinterOptionValue(tElement, "PrinterModel");
	                _printerSerialNumber  = GetPrinterOptionValue(tElement, "PrinterSerialNumber");
	                _printerStatus        = GetPrinterOptionValue(tElement, "PrinterStatus");
	                _printerVersion       = GetPrinterOptionValue(tElement, "PrinterVersion");
	                _printHead            = GetPrinterOptionValue(tElement, "PrintHead");
	                _topcoatPrintResolution = GetPrinterOptionValue(tElement, "TopcoatPrintResolution");
	                _optionRewrite        = GetPrinterOptionValue(tElement, "OptionRewritable");
	                _optionPrinterBarcodeReader = GetPrinterOptionValue(tElement, "OptionPrinterBarcodeReader");
	
	                //  as of version 7.0, printEngine defaults to direct-to-card...
	                _printEngineType      = GetPrinterOptionValue(tElement, "PrintEngineType");
	
	                _optionObscureBlackPanel = GetPrinterOptionValue(tElement, "ObscureBlackPanel");
	
	                // tactile impresser
	                _optionTactileImpresser = GetPrinterOptionValue(tElement, "TactileImpresser");
	                _optionUVCure         = GetPrinterOptionValue(tElement, "UVCureModule");
	
	                _rearPickOption       = GetPrinterOptionValue(tElement, "RearPick");
	                _kioskOption          = GetPrinterOptionValue(tElement, "Kiosk");    
	                
                }
	        }   
			
		} catch (Exception e) {
			e.printStackTrace();
		}    
    }

	public String GetPrinterOptions3() {
	    byte returnBuffer[] = new byte[XPS_Java_SDK.BUFFSIZE];
	    int bufferSize[] = new int[1];
	    bufferSize[0] = XPS_Java_SDK.BUFFSIZE;
	    int S_OK = 0;
	    int hResult = -1; // not S_OK
	    String returnValue = "";
	
	    // get driver SDK version
	    hResult = XpsDriverInteropLib.INSTANCE.GetSDKVersion(mPrinterName, returnBuffer, bufferSize);

	    returnValue = cStringToJavaString(returnBuffer, bufferSize[0]);
	    if (S_OK == hResult) {
	        System.out.format("'%s' GetSDKVersion() return length: %d\n\n%s\n", mPrinterName,
	                bufferSize[0], returnValue);
	    } else {
	        System.out.format("GetSDKVersion() failed. Return buffersize = %d\n %s", bufferSize[0],
	                returnValue);
	        return returnValue;
	    }
	    // reset bufferSize
	    bufferSize[0] = bufferSize[0] = XPS_Java_SDK.BUFFSIZE;
	
	    // call driver to get printer options
	    hResult = XpsDriverInteropLib.INSTANCE.GetPrinterOptions3(mPrinterName, returnBuffer,
	                bufferSize);
	

	    returnValue = cStringToJavaString(returnBuffer, bufferSize[0]);
	    if (S_OK == hResult) {
	        System.out.format("'%s' GetPrinterOptions3() return length: %d\n\n%s", mPrinterName,
	                bufferSize[0], returnValue);
	    } else {
	        System.out.format("GetPrinterOptions3() failed. Return buffersize = %d\n %s",
	                bufferSize[0], returnValue);
	    }
	
	    return returnValue;
	}
	
	public String GetInputHopper(String inputHopper, String commandLineHopperID) {
		String hopperID = "1";
		if (commandLineHopperID.length() > 0) {
			hopperID = commandLineHopperID;
		}
	    //Detect if printer has 3/3 MH option. If so, set hopper ID to 4. 
	    if (inputHopper.equals("MultiHopper3WithExceptionSlot")) {
	        System.out.format("3/3 multihopper option detected.");
	        if (commandLineHopperID.length() > 0) {
	            if (commandLineHopperID.equals("1") || commandLineHopperID.equals("2") || commandLineHopperID.equals("3")) {
	            	String exceptionText = "Use a compatible hopper ID for the 3 input/3 output Multi-Hopper option.";
	                System.out.println(exceptionText);
	                System.exit(-1);
	            }
	        } else {
				hopperID = "4";
			}
	    }
		
		return hopperID;
	}
}

