package DTCDemo;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterJob;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;

import net.miginfocom.swing.MigLayout;

import SDK.SDKlib;
import SDK.SDKlib.Action;
import SDK.SDKlib.CardPosition;
import SDK.SDKlib.CardLocation;
import SDK.SDKlib.Config;
import SDK.SDKlib.DyePanel;
import SDK.SDKlib.EjectMode;
import SDK.SDKlib.EraseSpeed;
import SDK.SDKlib.FeedMode;
import SDK.SDKlib.HandFeed;
import SDK.SDKlib.HorzEject;
import SDK.SDKlib.IPData;
import SDK.SDKlib.IPMode;
import SDK.SDKlib.InfoMask;
import SDK.SDKlib.Model;
import SDK.SDKlib.PrinterInfo;
import SDK.SDKlib.PrinterType;
import SDK.SDKlib.Response;
import SDK.SDKlib.Return;
import SDK.SDKlib.SmartMode;

import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
import com.sun.jna.ptr.ByteByReference;

import static DTCDemo.Utils.*;
import static DTCDemo.Main.InfoTab;
import static DTCDemo.Main.EncodingTab;
import static DTCDemo.Main.Driver1Tab;
import static DTCDemo.Main.Driver2Tab;
import static DTCDemo.Main.PrintDemoTab;
import static DTCDemo.Main.UtilityTab;

//====================================================================================

class Printer {
	static final int MAX_ERASECOUNT = 499;	//Maximum number of cards that can be erased
	static final int MAX_OFFSET     = 99;	//Maximum Smart card offset position
	
	private final String OPEN        = "OPEN";
	private final String CLOSE       = "CLOSE";
	private final String RESPONSE    = "RESPONSE";
	private final String GENERAL     = "GENERAL";
	private final String FEEDMOVE    = "FEEDMOVE";
	private final String MOVEFILM    = "MOVEFILM";
	private final String EJECT       = "EJECT";
	private final String FLIP        = "FLIP";
	private final String CLEAN       = "CLEAN";
	private final String RESTART     = "RESTART";
	private final String TEST        = "TEST";
	private final String LOCATION    = "LOCATION";
	private final String ERASE       = "ERASE";
	private final String HANDFEED    = "HANDFEED";
	private final String EJECTMODE   = "EJECTMODE";
	private final String HORZEJECT   = "HORZEJECT";
	private final String SMARTMODE   = "SMARTMODE";
	private final String SMARTOFFSET = "SMARTOFFSET";
	private final String ERASESPEED  = "ERASESPEED";
	private final String IPSETTINGS  = "IPSETTINGS";
	private final String RADIOGET    = "RADIOGET";
	private final String RADIOSET    = "RADIOSET";
	private final String CLEAR       = "CLEAR";

	private final ActionHandler ah = new ActionHandler();

	private final JPanel panelPrinter = new JPanel();
	private final JPanel cardsOpenCloseSession = new JPanel(new CardLayout());
	private final JPanel panelOpen = new JPanel();
	private final JPanel panelClose = new JPanel();
	private final JButton btnOpenSession = new JButton("Open Session");
	private final JButton btnCloseSession = new JButton("Close Session");
	private final JComboBox<ComboItem> comboOpenSession = new JComboBox<>();

	private final JPanel panelGeneralCommand = new JPanel();
	private final JTextField editGenCommand;
	private final JButton btnGenCommand = new JButton("Send");

	private final JPanel panelErrorResponse = new JPanel();
	private final JComboBox<ComboItem> comboErrorResponse = new JComboBox<>();
	private final JButton btnErrorResponse = new JButton("Error Response");

	private final JPanel panelPrinterControl = new JPanel();
	private final JButton btnFeedMove = new JButton("Feed Card");
	private final JButton btnMoveFilm = new JButton("Move Film");
	private final JButton btnEjectCard = new JButton("Eject Card");
	private final JButton btnCleanPrinter = new JButton("Clean Ptr");
	private final JButton btnTestCard = new JButton("Test Card");
	private final JButton btnFlipCard = new JButton("Flip Card");
	private final JButton btnRestartPrinter = new JButton("Restart");
	private final JButton btnCardLocation = new JButton("Card Locn");
	private final JComboBox<ComboItem> comboFeedMove = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboMoveFilm = new JComboBox<ComboItem>();
	
	private final JPanel panelRewritable = new JPanel();
	private final JLabel labelEraseAreaBotL = new JLabel("Bot L");
	private final JSpinner spinnerEraseAreaBotLX = new JSpinner(new SpinnerNumberModel(0, 0, maxXCoord, 1));
	private final JSpinner spinnerEraseAreaBotLY = new JSpinner(new SpinnerNumberModel(0, 0, MAX_Y_COORD, 1));
	private final JLabel labelEraseAreaTopR = new JLabel("Top R");
	private final JSpinner spinnerEraseAreaTopRX = new JSpinner(new SpinnerNumberModel(maxXCoord, 0, maxCardLength, 1));
	private final JSpinner spinnerEraseAreaTopRY = new JSpinner(new SpinnerNumberModel(MAX_Y_COORD, 0, MAX_CARD_HEIGHT, 1));
	private final JLabel labelEraseAreaCount = new JLabel("Count");
	private final JSpinner spinnerEraseCount = new JSpinner(new SpinnerNumberModel(1, 1, MAX_ERASECOUNT, 1));
	private final JLabel labelEraseAreaX = new JLabel("X");
	private final JLabel labelEraseAreaY = new JLabel("Y");
	private final JButton btnErase = new JButton("Erase Area");

	private final JPanel panelPrinterConfig = new JPanel();
	private final JLabel labelAction = new JLabel("Action:");
	private final JRadioButton rdbtnGet = new JRadioButton("Get");
	private final JRadioButton rdbtnSet = new JRadioButton("Set");
	private final ButtonGroup buttonGroup = new ButtonGroup();
	private final JComboBox<ComboItem> comboHandFeed = new JComboBox<ComboItem>();
	private final JButton btnHandFeed = new JButton("Hand Feed");
	private final JComboBox<ComboItem> comboEjectMode = new JComboBox<ComboItem>();
	private final JButton btnEjectMode = new JButton("Eject Mode");
	private final JComboBox<ComboItem> comboHorzEject = new JComboBox<ComboItem>();
	private final JButton btnHorzEject = new JButton("Horz Eject");
	private final JComboBox<ComboItem> comboSmartMode = new JComboBox<ComboItem>();
	private final JButton btnSmartMode = new JButton("Smart Mode");
	private final JSpinner spinnerSmartOffset = new JSpinner(new SpinnerNumberModel(new Byte("0"), 
																					new Byte("0"), 
																					new Byte((byte)MAX_OFFSET), 
																					new Byte("1")));
	private final JButton btnSmartOffset = new JButton("Smart Offset");
	private final JComboBox<ComboItem> comboEraseSpeed = new JComboBox<ComboItem>();
	private final JButton btnEraseSpeed = new JButton("Erase Speed");

	private final JPanel panelIPSettings = new JPanel();
	private final JLabel labelIPMode = new JLabel("Mode");
	private final JComboBox<ComboItem> comboIPMode = new JComboBox<ComboItem>();
	private final JLabel labelIPAddress = new JLabel("Address");
	private final JTextField textIPAddress = new JTextField();
	private final JLabel labelIPSubnet = new JLabel("Subnet");
	private final JTextField textIPSubnet = new JTextField();
	private final JLabel labelIPGateway = new JLabel("Gateway");
	private final JTextField textIPGateway = new JTextField();
	private final JButton btnIPSettings = new JButton("IP Settings");

	private final JPanel panelPrinterMsg = new JPanel();
	private final JTextArea textPrinterMsg = new JTextArea();
	private final JScrollPane scrollPane = new JScrollPane(textPrinterMsg);    
	private final JButton btnClear = new JButton("Clear");

	private JTabbedPane tabbedPane;

	private HANDLE hSession; 
	private SDKlib SDK = new SDKlib();

	static PrinterJob pj;
	
	//====================================================================================

	protected Printer(JTabbedPane mainTab) {
		tabbedPane = mainTab;
		tabbedPane.addTab("Printer", null, panelPrinter, null);

		panelPrinter.setLayout(new MigLayout("", "[250.00px][248px][248px][167px]", "[53px][53px][120.00][][]"));
		
		// ===== Session Control =====
		cardsOpenCloseSession.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
										                 "Session Control",
										                 TitledBorder.LEADING, 
										                 TitledBorder.TOP, 
										                 null,
										                 new Color(0, 0, 0)));
		panelPrinter.add(cardsOpenCloseSession, "cell 0 0 3 1,grow");
		cardsOpenCloseSession.add(panelOpen, "OpenSessionPanel");
		cardsOpenCloseSession.add(panelClose, "CloseSessionPanel");

		panelOpen.setLayout(new MigLayout("", "[][grow]", "[]"));
		btnOpenSession.setActionCommand(OPEN);
		btnOpenSession.addActionListener(ah);
		panelOpen.add(btnOpenSession, "cell 0 0");

		comboOpenSession.addItem(new ComboItem("Config Normal", Config.NORMAL));
		comboOpenSession.addItem(new ComboItem("Config Quiet",  Config.QUIET));
		panelOpen.add(comboOpenSession, "cell 1 0,growx");

		btnCloseSession.setActionCommand(CLOSE);
		btnCloseSession.addActionListener(ah);
		panelClose.add(btnCloseSession);

		// ===== Error Response =====
		panelErrorResponse.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
				                                      "Error Handling",
				                                      TitledBorder.LEADING, 
				                                      TitledBorder.TOP, 
				                                      null,
				                                      new Color(0, 0, 0)));
		panelPrinter.add(panelErrorResponse, "cell 3 0 1 2,grow");
		panelErrorResponse.setLayout(new MigLayout("", "[167px,grow]", "[53px][]"));
		comboErrorResponse.setEnabled(false);

		comboErrorResponse.addItem(new ComboItem("OK",     Response.OK));
		comboErrorResponse.addItem(new ComboItem("Cancel", Response.CANCEL));
		panelErrorResponse.add(comboErrorResponse, "cell 0 0,growx");
		btnErrorResponse.setEnabled(false);

		panelErrorResponse.add(btnErrorResponse, "cell 0 1,alignx center");
		btnErrorResponse.setActionCommand(RESPONSE);
		btnErrorResponse.addActionListener(ah);
		btnErrorResponse.setEnabled(false);

		// ===== General Command =====
		panelGeneralCommand.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
				                                       "General Command",
				                                       TitledBorder.LEADING, 
				                                       TitledBorder.TOP, 
				                                       null,
				                                       new Color(0, 0, 0)));
		panelPrinter.add(panelGeneralCommand, "cell 0 1 3 1,grow");
		panelGeneralCommand.setLayout(new MigLayout("", "[grow]", "[]"));

		editGenCommand = new JTextField();
		editGenCommand.setEnabled(false);
		panelGeneralCommand.add(editGenCommand, "flowx,cell 0 0,growx");
		btnGenCommand.setEnabled(false);

		panelGeneralCommand.add(btnGenCommand, "cell 0 0");
		btnGenCommand.setActionCommand(GENERAL);
		btnGenCommand.addActionListener(ah);

		// ===== Printer Control =====
		panelPrinterControl.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
				                                       "Printer Control",
				                                       TitledBorder.LEADING, 
				                                       TitledBorder.TOP, 
				                                       null,
				                                       new Color(0, 0, 0)));
		panelPrinter.add(panelPrinterControl, "cell 0 2 2 1,grow");
		panelPrinterControl.setLayout(new MigLayout("", "[][][]", "[grow][grow][grow][grow]"));

		panelPrinterControl.add(btnFeedMove, "cell 0 0,growx");
		btnFeedMove.setActionCommand(FEEDMOVE);
		btnFeedMove.addActionListener(ah);
		btnFeedMove.setEnabled(false);
		panelPrinterControl.add(comboFeedMove, "cell 1 0 2 1,growx");
		comboFeedMove.setEnabled(false);
		btnMoveFilm.setEnabled(false);

		panelPrinterControl.add(btnMoveFilm, "cell 0 1,growx");
		btnMoveFilm.setActionCommand(MOVEFILM);
		btnMoveFilm.addActionListener(ah);
		btnMoveFilm.setEnabled(false);
		panelPrinterControl.add(comboMoveFilm, "cell 1 1 2 1,growx");
		comboMoveFilm.addItem(new ComboItem("Initialise", DyePanel.INITIALISE));
		comboMoveFilm.addItem(new ComboItem("Next",       DyePanel.NEXT));
		comboMoveFilm.addItem(new ComboItem("Yellow",     DyePanel.YELLOW));
		comboMoveFilm.addItem(new ComboItem("Magenta",    DyePanel.MAGENTA));
		comboMoveFilm.addItem(new ComboItem("Cyan",       DyePanel.CYAN));
		comboMoveFilm.addItem(new ComboItem("KResin",     DyePanel.KRESIN));
		comboMoveFilm.addItem(new ComboItem("Overcoat",   DyePanel.OVERCOAT));
		comboMoveFilm.setEnabled(false);

		panelPrinterControl.add(btnEjectCard, "cell 0 2,growx");
		btnEjectCard.setActionCommand(EJECT);
		btnEjectCard.addActionListener(ah);
		btnEjectCard.setEnabled(false);

		panelPrinterControl.add(btnFlipCard, "cell 1 2,growx");
		btnFlipCard.setActionCommand(FLIP);
		btnFlipCard.addActionListener(ah);
		btnFlipCard.setEnabled(false);

		panelPrinterControl.add(btnCleanPrinter, "cell 2 3,growx");
		btnCleanPrinter.setActionCommand(CLEAN);
		btnCleanPrinter.addActionListener(ah);
		btnCleanPrinter.setEnabled(false);

		panelPrinterControl.add(btnRestartPrinter, "cell 1 3,growx");
		btnRestartPrinter.setActionCommand(RESTART);
		btnRestartPrinter.addActionListener(ah);
		btnRestartPrinter.setEnabled(false);

		panelPrinterControl.add(btnTestCard, "cell 2 2,growx");
		btnTestCard.setActionCommand(TEST);
		btnTestCard.addActionListener(ah);
		btnTestCard.setEnabled(false);

		panelPrinterControl.add(btnCardLocation, "cell 0 3,growx");
		btnCardLocation.setActionCommand(LOCATION);
		btnCardLocation.addActionListener(ah);
		btnCardLocation.setEnabled(false);
		
		// ===== Erase Area =====
		panelPrinter.add(panelRewritable, "cell 2 2 2 1,grow");
		panelRewritable.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
								                   "Rewritable Cards", 
								                   TitledBorder.LEADING, 
								                   TitledBorder.TOP, 
								                   null, 
								                   new Color(0, 0, 0)));
		panelRewritable.setLayout(new MigLayout("", "[grow][grow,center][grow,center]", "[grow][grow][grow][][grow]"));

		panelRewritable.add(labelEraseAreaX, "cell 1 0");
		panelRewritable.add(labelEraseAreaY, "cell 2 0");

		panelRewritable.add(labelEraseAreaBotL, "cell 0 1,alignx left");

		panelRewritable.add(spinnerEraseAreaBotLX, "cell 1 1,growx");
		spinnerEraseAreaBotLX.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaBotLX,"#"));
		spinnerEraseAreaBotLX.setEnabled(false);

		panelRewritable.add(spinnerEraseAreaBotLY, "cell 2 1,growx");
		spinnerEraseAreaBotLY.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaBotLY,"#"));
		spinnerEraseAreaBotLY.setEnabled(false);

		panelRewritable.add(labelEraseAreaTopR, "cell 0 2,alignx left");

		spinnerEraseAreaTopRX.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaTopRX,"#"));
		spinnerEraseAreaTopRX.setEnabled(false);
		panelRewritable.add(spinnerEraseAreaTopRX, "cell 1 2,growx");

		spinnerEraseAreaTopRY.setEditor(new JSpinner.NumberEditor(spinnerEraseAreaTopRY,"#"));
		spinnerEraseAreaTopRY.setEnabled(false);
		panelRewritable.add(spinnerEraseAreaTopRY, "cell 2 2,growx");
		
		panelRewritable.add(labelEraseAreaCount, "cell 0 3,alignx left");
		spinnerEraseCount.setEnabled(false);
		
		panelRewritable.add(spinnerEraseCount, "cell 1 3,growx");
		btnErase.setEnabled(false);

		panelRewritable.add(btnErase, "cell 0 4 3 1,alignx center");
		btnErase.setActionCommand(ERASE);
		btnErase.addActionListener(ah);

		// ===== Printer Config =====
		panelPrinter.add(panelPrinterConfig, "cell 0 3 2 1,grow");
		panelPrinterConfig.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
									                  "Printer Config", 
									                  TitledBorder.LEADING, 
									                  TitledBorder.TOP, 
									                  null, 
									                  new Color(0, 0, 0)));
		panelPrinterConfig.setLayout(new MigLayout("", "[][grow]", "[][][][][][][]"));

		panelPrinterConfig.add(labelAction, "flowx,cell 0 0 2 1,alignx center");
		panelPrinterConfig.add(rdbtnGet, "cell 0 0");
		rdbtnGet.setEnabled(false);
		rdbtnGet.setSelected(true);
		buttonGroup.add(rdbtnGet);
		rdbtnGet.setActionCommand(RADIOGET);
		buttonGroup.add(rdbtnSet);
		panelPrinterConfig.add(rdbtnSet, "cell 0 0");
		rdbtnSet.setEnabled(false);
		buttonGroup.add(rdbtnSet);
		rdbtnSet.setActionCommand(RADIOSET);
		rdbtnSet.addActionListener(ah);
		rdbtnGet.addActionListener(ah);

		panelPrinterConfig.add(btnHandFeed, "cell 0 1,growx");
		btnHandFeed.setEnabled(false);
		btnHandFeed.setActionCommand(HANDFEED);
		btnHandFeed.addActionListener(ah);
		panelPrinterConfig.add(comboHandFeed, "cell 1 1,growx");
		comboHandFeed.addItem(new ComboItem("Off", HandFeed.OFF));
		comboHandFeed.addItem(new ComboItem("On",  HandFeed.ON));
		comboHandFeed.setEnabled(false);

		panelPrinterConfig.add(btnEjectMode, "cell 0 2,growx");
		btnEjectMode.setEnabled(false);
		btnEjectMode.setActionCommand(EJECTMODE);
		btnEjectMode.addActionListener(ah);
		panelPrinterConfig.add(comboEjectMode, "cell 1 2,growx");
		comboEjectMode.addItem(new ComboItem("Off", EjectMode.OFF));
		comboEjectMode.addItem(new ComboItem("On",  EjectMode.ON));
		comboEjectMode.setEnabled(false);

		panelPrinterConfig.add(btnSmartOffset, "cell 0 3,growx");
		btnSmartOffset.setEnabled(false);
		btnSmartOffset.setActionCommand(SMARTOFFSET);
		btnSmartOffset.addActionListener(ah);
		panelPrinterConfig.add(spinnerSmartOffset, "cell 1 3,growx");
		spinnerSmartOffset.setEnabled(false);

		panelPrinterConfig.add(btnSmartMode, "cell 0 4,growx");
		btnSmartMode.setEnabled(false);
		btnSmartMode.setActionCommand(SMARTMODE);
		btnSmartMode.addActionListener(ah);
		panelPrinterConfig.add(comboSmartMode, "cell 1 4,growx");
		comboSmartMode.addItem(new ComboItem("Default", SmartMode.DEFAULT));
		comboSmartMode.addItem(new ComboItem("Platen",  SmartMode.PLATEN));
		comboSmartMode.addItem(new ComboItem("XLI",     SmartMode.XLI));
		comboSmartMode.setEnabled(false);

		panelPrinterConfig.add(btnHorzEject, "cell 0 5,growx");
		btnHorzEject.setEnabled(false);
		btnHorzEject.setActionCommand(HORZEJECT);
		btnHorzEject.addActionListener(ah);
		panelPrinterConfig.add(comboHorzEject, "cell 1 5,growx");
		comboHorzEject.addItem(new ComboItem("Off", HorzEject.OFF));
		comboHorzEject.addItem(new ComboItem("On",  HorzEject.ON));
		comboHorzEject.setEnabled(false);

		panelPrinterConfig.add(btnEraseSpeed, "cell 0 6,growx");
		btnEraseSpeed.setEnabled(false);
		btnEraseSpeed.setActionCommand(ERASESPEED);
		btnEraseSpeed.addActionListener(ah);
		panelPrinterConfig.add(comboEraseSpeed, "cell 1 6,growx");
		comboEraseSpeed.addItem(new ComboItem("Thorough", EraseSpeed.THOROUGH));
		comboEraseSpeed.addItem(new ComboItem("Quick",    EraseSpeed.QUICK));
		comboEraseSpeed.setEnabled(false);

		// ===== IP Settings =====
		panelPrinter.add(panelIPSettings, "cell 0 4 2 1,grow");
		panelIPSettings.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
								                   "", 
								                   TitledBorder.LEADING, 
								                   TitledBorder.TOP, 
								                   null,
								                   new Color(0, 0, 0)));
		panelIPSettings.setLayout(new MigLayout("", "[][grow]", "[][][][][]"));

		panelIPSettings.add(labelIPMode, "cell 0 0,alignx left");
		panelIPSettings.add(comboIPMode, "cell 1 0,growx");
		comboIPMode.addItem(new ComboItem("Static",  IPMode.STATIC));
		comboIPMode.addItem(new ComboItem("Dynamic", IPMode.DYNAMIC));
		comboIPMode.setEnabled(false);

		panelIPSettings.add(labelIPAddress, "cell 0 1,alignx left");
		panelIPSettings.add(textIPAddress, "cell 1 1,growx");
		textIPAddress.setEnabled(false);

		panelIPSettings.add(labelIPSubnet, "cell 0 2,alignx left");
		panelIPSettings.add(textIPSubnet, "cell 1 2,growx");
		textIPSubnet.setEnabled(false);

		panelIPSettings.add(labelIPGateway, "cell 0 3,alignx left");
		panelIPSettings.add(textIPGateway, "cell 1 3,growx");
		textIPGateway.setEnabled(false);

		panelIPSettings.add(btnIPSettings, "cell 0 4 2 1,alignx center");
		btnIPSettings.setActionCommand(IPSETTINGS);
		btnIPSettings.addActionListener(ah);
		btnIPSettings.setEnabled(false);

		// ===== Printer Msg =====
		panelPrinter.add(panelPrinterMsg, "cell 2 3 2 2,grow");
		panelPrinterMsg.setLayout(new MigLayout("", "[grow]", "[grow][]"));
		panelPrinterMsg.add(scrollPane, "cell 0 0,grow");
		textPrinterMsg.setEditable(false);
		textPrinterMsg.setBorder(BorderFactory.createLineBorder(Color.black));
		
		panelPrinterMsg.add(btnClear, "cell 0 1,alignx center");
		btnClear.setActionCommand(CLEAR);
		btnClear.addActionListener(ah);
		
		textPrinterMsg.append("Demo Version: "      + demoVersion + "\n");
		textPrinterMsg.append("Java Shim Version: " + SDK.shimVersion  + "\n");
		textPrinterMsg.append(SDK.ID_SDKBits() +" Bit SDK\n\n");
	}

	//====================================================================================

	private void ShowHideControls()
	{
		boolean bControl = (connectedPrinter == PrinterType.GENERATION2);

	    //Controls for Rio Pro 360
		btnMoveFilm.setVisible(bControl);
		comboMoveFilm.setVisible(bControl);
		btnCardLocation.setVisible(bControl);

	    //Controls for Enduro
		panelGeneralCommand.setVisible(!bControl);
		editGenCommand.setVisible(!bControl);
		btnGenCommand.setVisible(!bControl);
		btnCleanPrinter.setVisible(!bControl);
		btnSmartMode.setVisible(!bControl);
		comboSmartMode.setVisible(!bControl);
		btnHorzEject.setVisible(!bControl);
		comboHorzEject.setVisible(!bControl);
		btnEraseSpeed.setVisible(!bControl);
		comboEraseSpeed.setVisible(!bControl);
	}

	//------------------------------------------------------------------------------------

	private void EnableGetSetControls(Boolean state) {
		comboHandFeed.setEnabled(state);
		comboEjectMode.setEnabled(state);
		comboSmartMode.setEnabled(state);
		spinnerSmartOffset.setEnabled(state);
		comboEraseSpeed.setEnabled(state);
		comboHorzEject.setEnabled(state);

		if (ProntoPrinter()) {
			btnIPSettings.setEnabled(false);
		}
		else {
			comboIPMode.setEnabled(state);
			textIPAddress.setEnabled(state);
			textIPSubnet.setEnabled(state);
			textIPGateway.setEnabled(state);
		}
	}

	//------------------------------------------------------------------------------------

	private void EnableControls(Boolean state) {
		btnFeedMove.setEnabled(state);
		comboFeedMove.setEnabled(state);
		btnMoveFilm.setEnabled(state);
		comboMoveFilm.setEnabled(state);
		btnCardLocation.setEnabled(state);
		btnEjectCard.setEnabled(state);
		btnFlipCard.setEnabled(state);
		btnTestCard.setEnabled(state);
		btnCleanPrinter.setEnabled(state);
		btnRestartPrinter.setEnabled(state);
		btnGenCommand.setEnabled(state);
		editGenCommand.setEnabled(state);
		btnErase.setEnabled(state);
		spinnerEraseAreaBotLX.setEnabled(state);
		spinnerEraseAreaBotLY.setEnabled(state);
		spinnerEraseAreaTopRX.setEnabled(state);
		spinnerEraseAreaTopRY.setEnabled(state);
		spinnerEraseCount.setEnabled(state);
		btnErrorResponse.setEnabled(state);
		comboErrorResponse.setEnabled(state);
		rdbtnGet.setEnabled(state);
		rdbtnSet.setEnabled(state);
		btnHandFeed.setEnabled(state);
		btnEjectMode.setEnabled(state);
		btnHorzEject.setEnabled(state);
		btnSmartMode.setEnabled(state);
		btnSmartOffset.setEnabled(state);
		btnEraseSpeed.setEnabled(state);
		btnIPSettings.setEnabled(state);

		EnableGetSetControls(rdbtnSet.isSelected());
	}

	//------------------------------------------------------------------------------------

	private void ClearMsg() {
		textPrinterMsg.setText(null);
	}

	//------------------------------------------------------------------------------------

    private Boolean ProntoPrinter() {
    	if (connectedPrinter != PrinterType.ENDURO) {
    		return false;
    	}
    	
    	//Get the SDK function address
		//Check if base model is pronto - doesn't have ethernet
		int sdkReturn = SDK.ID_PrinterModel(hSession);
		if (sdkReturn == Return.ERROR) {
			return false;
		}
		else {
			return ((sdkReturn & Model.PRONTO) != 0);
		}
    }

    //====================================================================================

	private void OpenSession() {
		pj = PrinterJob.getPrinterJob();
		if (pj.printDialog()) {
			CursorWait();
			
			HANDLEByReference HandleRef = new HANDLEByReference();
			String printername = pj.getPrintService().getName();
	    	byte sdkReturn = SDK.ID_OpenSession(printername, 
	    										HandleRef, 
	    										((ComboItem)comboOpenSession.getSelectedItem()).getValue());	
	    	if (sdkReturn != Return.SUCCESS) {
				DisplayError("OpenSession", sdkReturn);
			}
			else {
				hSession = HandleRef.getValue();
				
				//Call the SDK to get the printer model
				connectedPrinter = SDK.ID_PrinterType(hSession);
				if ((connectedPrinter != PrinterType.ENDURO)
				&&  (connectedPrinter != PrinterType.GENERATION2)) {
					JOptionPane.showMessageDialog(null, 
												  "Invalid Printer - DTC Only", 
												  "SDK ERROR", 
												  JOptionPane.INFORMATION_MESSAGE);
					CloseSession();
				}
				else {
					ShowHideControls();
	
					//Select the 'Close Session' card
					CardLayout cl = (CardLayout)(cardsOpenCloseSession.getLayout());
					cl.last(cardsOpenCloseSession);
					
					maxCardLength = SDK.ID_CardWidth(hSession);
					maxXCoord     = maxCardLength - 1;
					spinnerEraseAreaBotLX.setModel(new SpinnerNumberModel(0, 0, maxXCoord, 1));
					spinnerEraseAreaTopRX.setModel(new SpinnerNumberModel(maxXCoord, 0, maxXCoord, 1));
					spinnerEraseAreaTopRX.setValue(maxXCoord);

			        InfoTab.Init(hSession, SDK);
					EncodingTab.Init(hSession, SDK);
					Driver1Tab.Init(hSession, SDK);
					Driver2Tab.Init(hSession, SDK, pj.getPrintService().getName());
					PrintDemoTab.Init(hSession, SDK);
					UtilityTab.Init(hSession,SDK);
					
					if (connectedPrinter == PrinterType.GENERATION2)
					{
						btnFeedMove.setText("MoveCard");
						comboFeedMove.addItem(new ComboItem("Standby",     CardPosition.STANDBY));
						comboFeedMove.addItem(new ComboItem("Contact",     CardPosition.CONTACT_ENCODER));
						comboFeedMove.addItem(new ComboItem("Contactless", CardPosition.CONTACTLESS_ENCODER));
						comboFeedMove.addItem(new ComboItem("Flip",        CardPosition.FLIP_STANDBY));
						comboFeedMove.addItem(new ComboItem("Eject",       CardPosition.EJECT));
						comboFeedMove.addItem(new ComboItem("Initialise",  CardPosition.INITIALISE));
						comboFeedMove.addItem(new ComboItem("Reject",      CardPosition.REJECT));
						comboFeedMove.setSelectedIndex(0);
                        comboFeedMove.setEnabled(true);

                        //Get Hand Feed status
						ByteByReference HandFeed = new ByteByReference();
						GetHandFeed(HandFeed);
						HandFeedDisplay(HandFeed.getValue());
					}
					else
					{
						btnFeedMove.setText("FeedCard");
						comboFeedMove.addItem(new ComboItem("Contact",     FeedMode.CHIPCARD));
						comboFeedMove.addItem(new ComboItem("Contactless", FeedMode.CONTACTLESS));
						comboFeedMove.setSelectedIndex(0);
                        comboFeedMove.setEnabled(true);

                    	//Get Printer Info to Initialise the dialog fields
						PrinterInfo PI = new PrinterInfo();
						sdkReturn = SDK.ID_PrinterInfo(hSession, PI);
						if (sdkReturn != Return.SUCCESS) {
							DisplayError("Open-GetPrinterInfo", sdkReturn);
						}
						else {
							HandFeedDisplay((byte)PI.handFeed);
							switch (PI.bitFields & InfoMask.ENCODE_MODE)
							{
							case InfoMask.ENCODE_PLATEN: SmartModeDisplay(SmartMode.PLATEN);  break;
							case InfoMask.ENCODE_XLI:    SmartModeDisplay(SmartMode.XLI);     break;
							default:                     SmartModeDisplay(SmartMode.DEFAULT); break;
							}
							EraseSpeedDisplay((PI.bitFields & InfoMask.ERASE_SPEED) != 0 ? EraseSpeed.QUICK : EraseSpeed.THOROUGH);
							EjectModeDisplay((PI.bitFields  & InfoMask.EJECT_MODE)  != 0 ? EjectMode.ON     : EjectMode.OFF);
							HorzEjectDisplay((PI.bitFields  & InfoMask.HORZ_EJECT)  != 0 ? HorzEject.ON     : HorzEject.OFF);
							SmartOffsetDisplay((byte)PI.smartOffset);
						}
					}
		
					if (ProntoPrinter()) {
						btnIPSettings.setVisible(false);
						comboIPMode.setVisible(false);
						textIPAddress.setVisible(false);
						textIPSubnet.setVisible(false);
						textIPGateway.setVisible(false);
						panelIPSettings.setVisible(false);
						labelIPMode.setVisible(false);
						labelIPAddress.setVisible(false);
						labelIPSubnet.setVisible(false);
						labelIPGateway.setVisible(false);
					}
					else {
						//Display IP Settings
						IPData IP = new IPData();
						GetIPSettings(IP);
						IPSettingsToCtrl(IP);
					}

					//Update the display to show the Session is open
					btnOpenSession.setVisible(false);
					comboOpenSession.setVisible(false);
					btnCloseSession.setVisible(true);

					EnableControls(true);
				}

				//Force a resize of the main Frame
				((JFrame)tabbedPane.getTopLevelAncestor()).pack();
			}
	    	
	    	CursorDefault();
		}
	}

	//====================================================================================

	private void CloseSession() {
		//Select the 'Open Session' card
		CardLayout cl = (CardLayout)(cardsOpenCloseSession.getLayout());
		cl.first(cardsOpenCloseSession);
		
		tabbedPane.remove(Info.panelInfo);
		tabbedPane.remove(Encoding.panelEncoding);
		tabbedPane.remove(Driver1.panelDriver1);
		tabbedPane.remove(Driver2.panelDriver2);
		tabbedPane.remove(PrintDemo.panelPrintDemo);

		// Clean up.
		btnOpenSession.setVisible(true);
		comboOpenSession.setVisible(true);
		btnCloseSession.setVisible(false);
		EnableControls(false);
		EnableGetSetControls(false);

		byte sdkReturn = SDK.ID_CloseSession(hSession);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("CloseSession", sdkReturn);
		}
	}
	
	//====================================================================================

	private void FeedMove() {
       	if (connectedPrinter == PrinterType.GENERATION2) {
            MoveCard();
        }
        else
        {
            FeedCard();
        }
	}

	//====================================================================================

	private void FeedCard() {
		CursorWait();
		
		byte sdkReturn = SDK.ID_FeedCard(hSession, 
										 ((ComboItem)comboFeedMove.getSelectedItem()).getValue(),
										 0);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("FeedCard", sdkReturn);
		}
		else {
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("FeedCardWait", sdkReturn);
			}
		}

		CursorDefault();
	}
	
	//====================================================================================

	private void MoveCard()
	{
		CursorWait();
		
		byte sdkReturn = SDK.ID_MoveCard(hSession, ((ComboItem)comboFeedMove.getSelectedItem()).getValue());	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("MoveCardWait", sdkReturn);
		}

		CursorDefault();
	}

	//====================================================================================

	private void MoveFilm()
	{
		CursorWait();
		
		byte sdkReturn = SDK.ID_MoveFilm(hSession, ((ComboItem)comboMoveFilm.getSelectedItem()).getValue());	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("MoveFilmWait", sdkReturn);
		}

		CursorDefault();
	}

	//====================================================================================

	private void CardLocation()
	{
		CursorWait();
		ByteByReference location = new ByteByReference();

		byte sdkReturn = SDK.ID_CardLocation(hSession, location);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("CardLocation", sdkReturn);
		}

		else {
			String temp_string;
			switch (location.getValue())
			{
			case CardLocation.UNKNOWN:     temp_string = "Unknown"; break;
			case CardLocation.NO_CARD:     temp_string = "No Card"; break;
			case CardLocation.PRINT_READY: temp_string = "Standby"; break;
			case CardLocation.ENCODER:     temp_string = "Encoder"; break;
			default:                       temp_string = "???????"; break;
			}
			textPrinterMsg.append("Card Location: " + temp_string + "\n\n");
		}
		
		CursorDefault();
	}

	//====================================================================================

	private void ErrorResponse() {
		byte sdkReturn = SDK.ID_ErrorResponse(hSession, 
											  ((ComboItem)comboErrorResponse.getSelectedItem()).getValue());	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("ErrorResponse", sdkReturn);
		}
	}
	
	//====================================================================================

	private void EjectCard() {
		CursorWait();
		
		byte sdkReturn = SDK.ID_EjectCard(hSession);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("EjectCard", sdkReturn);
		}

		else {
			//Wait for the card to be ejected
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("EjectCardWait", sdkReturn);
			}
		}

		CursorDefault();
	}
	
	//====================================================================================

	private void GeneralCommand() {
		if (editGenCommand.getText().length() != 0) {
			CursorWait();
			
			byte sdkReturn = SDK.ID_GeneralCommand(hSession, editGenCommand.getText());	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("GeneralCommand", sdkReturn);
			}
	    	
			CursorDefault();
		}
	}
	
	//====================================================================================

	private void FlipCard() {
		CursorWait();
		
		byte sdkReturn = SDK.ID_FlipCard(hSession);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("FlipCard", sdkReturn);
		}

		else {
			//Wait for the card to be flipped
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("FlipCardWait", sdkReturn);
			}
		}

		CursorDefault();
	}

	//====================================================================================

	private void CleanPrinter() {
		CursorWait();
		
		byte sdkReturn = SDK.ID_CleanPrinter(hSession);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("CleanPrinter", sdkReturn);
		}
		else {
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("CleanPrinterWait", sdkReturn);
			}
		}
		
		CursorDefault();
	}

	//====================================================================================

	private void RestartPrinter() {
		CursorWait();
		
		byte sdkReturn = SDK.ID_RestartPrinter(hSession);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("RestartPrinter", sdkReturn);
		}
		else {
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("RestartPrinterWait", sdkReturn);
			}
		}
    	
		CursorDefault();
	}

	//====================================================================================

	private void PrintTestCard() {
		CursorWait();
		
    	byte sdkReturn;
    	if (connectedPrinter == PrinterType.GENERATION2) {
            //Call SDK to Prepare to Print a Test Card
    		sdkReturn = SDK.ID_PrepareForPrint(hSession);
            if (sdkReturn != Return.SUCCESS) {
            	DisplayError("PrintTestCardPrepare", sdkReturn);
                return;
            }
        }

		sdkReturn = SDK.ID_PrintTestCard(hSession);	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("PrintTestCard", sdkReturn);
		}
		else {
			if (connectedPrinter == PrinterType.GENERATION2) {
            	sdkReturn = SDK.ID_WaitPrintComplete(hSession);
                if (sdkReturn != Return.SUCCESS) {
                	DisplayError("PrintTestCardComplete", sdkReturn);
                }
            }
            else {
				sdkReturn = WaitForPrinterToFinish(hSession, SDK);
				if (sdkReturn != Return.SUCCESS) {
					DisplayError("PrintTestCardWait", sdkReturn);
				}
            }
		}
		
		CursorDefault();
	}

	//====================================================================================

	private void EraseCard() {
		CursorWait();
		
		byte sdkReturn = SDK.ID_EraseCard(hSession, 
										  (int)spinnerEraseCount.getValue(),
										  (int)spinnerEraseAreaBotLX.getValue(), 
										  (int)spinnerEraseAreaBotLY.getValue(), 
										  (int)spinnerEraseAreaTopRX.getValue(), 
										  (int)spinnerEraseAreaTopRY.getValue());	
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("EraseCard", sdkReturn);
		}
		else {
			//Wait for the card to be erased
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("EjectCardWait", sdkReturn);
			}
		}
    
		CursorDefault();
	}
	
	//====================================================================================

	private String HandFeedString(byte mode) {
		return comboHandFeed.getItemAt(mode).toString();
	}

	//------------------------------------------------------------------------------------

	private void HandFeedDisplay(byte HandFeed) {
		comboHandFeed.setSelectedIndex(HandFeed);
	}

	//------------------------------------------------------------------------------------

	private void HandFeedToMsgBox(byte action, byte mode) {
		textPrinterMsg.append("Hand Feed" + Separator(action) + HandFeedString(mode) + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private byte GetHandFeed(ByteByReference mode) {
		CursorWait();

		byte sdkReturn = SDK.ID_HandFeed(hSession, Action.READ, mode);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetHandFeed", sdkReturn);
		}
		else {
			HandFeedDisplay(mode.getValue());
		}

		CursorDefault();
		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void HandFeed() {
		ByteByReference mode = new ByteByReference(((ComboItem)comboHandFeed.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetHandFeed(mode) == Return.SUCCESS) {
				HandFeedToMsgBox(Action.READ, mode.getValue());
			}
		}
		else {
			byte sdkReturn = SDK.ID_HandFeed(hSession, Action.WRITE, mode);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetHandFeed", sdkReturn);
			}
			else {
				HandFeedToMsgBox(Action.WRITE, mode.getValue());
			}
		}
	}

	//====================================================================================

	private String EjectModeString(byte mode) {
		return comboEjectMode.getItemAt(mode).toString();
	}

	//------------------------------------------------------------------------------------

	private void EjectModeDisplay(byte mode) {
		comboEjectMode.setSelectedIndex(mode);
	}

	//------------------------------------------------------------------------------------

	private void EjectModeToMsgBox(byte action, byte mode) {
		textPrinterMsg.append("Eject Mode" + Separator(action) + EjectModeString(mode) + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private byte GetEjectMode(ByteByReference mode) {
		CursorWait();

		byte sdkReturn = SDK.ID_EjectMode(hSession, Action.READ, mode);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetEjectMode", sdkReturn);
		}
		else {
			EjectModeDisplay(mode.getValue());
		}

		CursorDefault();
		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void EjectMode() {
		ByteByReference mode = new ByteByReference(((ComboItem)comboEjectMode.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetEjectMode(mode) == Return.SUCCESS) {
				EjectModeToMsgBox(Action.READ, mode.getValue());
			}
		}
		else {
			byte sdkReturn = SDK.ID_EjectMode(hSession, Action.WRITE, mode);	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("EjectMode", sdkReturn);
			}
			else {
				EjectModeToMsgBox(Action.WRITE, mode.getValue());
			}
		}
	}

	//====================================================================================

	private String HorzEjectString(byte mode) {
		return comboHorzEject.getItemAt(mode).toString();
	}

	//------------------------------------------------------------------------------------

	private void HorzEjectDisplay(byte mode) {
		comboHorzEject.setSelectedIndex(mode);
	}

	//------------------------------------------------------------------------------------

	private void HorzEjectToMsgBox(byte action, byte mode) {
		textPrinterMsg.append("Horz Eject" + Separator(action) + HorzEjectString(mode) + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private byte GetHorzEject(ByteByReference mode) {
		CursorWait();

		byte sdkReturn = SDK.ID_HorzEject(hSession, Action.READ, mode);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetHorzEject", sdkReturn);
		}
		else {
			HorzEjectDisplay(mode.getValue());
		}

		CursorDefault();
		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void HorzEject() {
		ByteByReference mode = new ByteByReference(((ComboItem)comboHorzEject.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetHorzEject(mode) == Return.SUCCESS) {
				HorzEjectToMsgBox(Action.READ, mode.getValue());
			}
		}
		else {
			byte sdkReturn = SDK.ID_HorzEject(hSession, Action.WRITE, mode);	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("HorzEject", sdkReturn);
			}
			else {
				HorzEjectToMsgBox(Action.WRITE, mode.getValue());
			}
		}
	}

	//====================================================================================

	static String SmartModeString(byte mode) {
		switch (mode) {
		case SmartMode.PLATEN: return "Platen";
		case SmartMode.XLI:    return "XLI";
		default:               return "Default";
		}
	}

	//------------------------------------------------------------------------------------
	private void SmartModeDisplay(byte mode) {
		comboSmartMode.setSelectedIndex(mode);
	}

	//------------------------------------------------------------------------------------

	private void SmartModeToMsgBox(byte action, byte mode) {
		textPrinterMsg.append("Smart Mode" + Separator(action) + SmartModeString(mode) + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private byte GetSmartMode(ByteByReference mode) {
		CursorWait();

		byte sdkReturn = SDK.ID_SmartMode(hSession, Action.READ, mode);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetSmarMode", sdkReturn);
		}
		else {
			SmartModeDisplay(mode.getValue());
		}

		CursorDefault();
		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void SmartMode() {
		ByteByReference mode = new ByteByReference(((ComboItem)comboSmartMode.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetSmartMode(mode) == Return.SUCCESS) {
				SmartModeToMsgBox(Action.READ, mode.getValue());
			}
		}
		else {
			byte sdkReturn = SDK.ID_SmartMode(hSession, Action.WRITE, mode);	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SmartMode", sdkReturn);
			}
			else {
				SmartModeToMsgBox(Action.WRITE, mode.getValue());
			}
		}
	}

	//====================================================================================

	private void SmartOffsetDisplay(byte offset) {
		spinnerSmartOffset.setValue(offset);
	}

	//------------------------------------------------------------------------------------

	private void SmartOffsetToMsgBox(byte action, byte offset) {
		String sep = Separator(action);
		textPrinterMsg.append("Smart Offset" + sep + offset + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private byte GetSmartOffset(ByteByReference offset) {
		CursorWait();

		byte sdkReturn = SDK.ID_SmartOffset(hSession, Action.READ, offset);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetSmartOffset", sdkReturn);
		}
		
		else {
			SmartOffsetDisplay(offset.getValue());
		}

		CursorDefault();
		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void SmartOffset() {
		ByteByReference offset = new ByteByReference();
		if (rdbtnGet.isSelected()) {
			if (GetSmartOffset(offset) == Return.SUCCESS) {
				SmartOffsetToMsgBox(Action.READ, offset.getValue());
			}
		}

		else {
			offset.setValue((byte)spinnerSmartOffset.getValue());
			byte sdkReturn = SDK.ID_SmartOffset(hSession, Action.WRITE, offset);	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("SetSmartOffset", sdkReturn);
			}

			else {
				SmartOffsetToMsgBox(Action.WRITE, offset.getValue());
			}
		}
	}

	//====================================================================================

	private String EraseSpeedString(byte mode) {
		return comboEraseSpeed.getItemAt(mode).toString();
	}

	//------------------------------------------------------------------------------------

	private void EraseSpeedDisplay(byte speed) {
		comboEraseSpeed.setSelectedIndex(speed);
	}

	//------------------------------------------------------------------------------------

	private void EraseSpeedToMsgBox(byte action, byte speed) {
		textPrinterMsg.append("Erase Speed" + Separator(action) + EraseSpeedString(speed) + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private byte GetEraseSpeed(ByteByReference speed) {
		CursorWait();

		byte sdkReturn = SDK.ID_EraseSpeed(hSession, Action.READ, speed);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetEraseSpeed", sdkReturn);
		}
		
		else {
			EraseSpeedDisplay(speed.getValue());
		}

		CursorDefault();
		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void EraseSpeed() {
		ByteByReference speed = new ByteByReference(((ComboItem)comboEraseSpeed.getSelectedItem()).getValue());
		if (rdbtnGet.isSelected()) {
			if (GetEraseSpeed(speed) == Return.SUCCESS) {
				EraseSpeedToMsgBox(Action.READ, speed.getValue());
			}
		}

		else {
			byte sdkReturn = SDK.ID_EraseSpeed(hSession, Action.WRITE, speed);	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("EraseSpeed", sdkReturn);
			}
	
			else {
				EraseSpeedToMsgBox(Action.WRITE, speed.getValue());
			}
		}
	}

	//====================================================================================

	private String IPModeString(byte mode) {
		return comboIPMode.getItemAt(mode).toString();
	}

	//------------------------------------------------------------------------------------

	private void IPSettingsToMsgBox(byte action, IPData IP) {
		String sep = Separator(action);
		textPrinterMsg.append("IP Settings:\n" 
				              + "Address Mode" + sep + IPModeString(IP.mode)    + "\n"
				              + "IP Address"   + sep + IP.getString(IP.address) + "\n"
				              + "Subnet"       + sep + IP.getString(IP.subnet)  + "\n"
				              + "Gateway"      + sep + IP.getString(IP.gateway) + "\n\n");
	}
	
	//------------------------------------------------------------------------------------

	private void IPSettingsToCtrl(IPData IP) {
		comboIPMode.setSelectedIndex(IP.mode);
		textIPAddress.setText(IP.getString(IP.address));
		textIPSubnet.setText(IP.getString(IP.subnet));
		textIPGateway.setText(IP.getString(IP.gateway));
	}

	//------------------------------------------------------------------------------------

	private byte GetIPSettings(IPData IP) {
		byte sdkReturn = SDK.ID_IPSettings(hSession, Action.READ, IP);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("GetIPSettings", sdkReturn);
		}

		return sdkReturn;
	}
	
	//------------------------------------------------------------------------------------

	private void IPSettings() {
		CursorWait();

		IPData IP = new IPData();		
		if (rdbtnGet.isSelected()) {
			if (GetIPSettings(IP) == Return.SUCCESS) {
				IPSettingsToMsgBox(Action.READ, IP);
				IPSettingsToCtrl(IP);
			}
		}
		else {
			IP.mode    = ((ComboItem)comboIPMode.getSelectedItem()).getValue();
 			IP.address = IP.getInt(textIPAddress.getText());
			IP.subnet  = IP.getInt(textIPSubnet.getText());
			IP.gateway = IP.getInt(textIPGateway.getText());

			byte sdkReturn = SDK.ID_IPSettings(hSession, Action.WRITE, IP);	
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("IPSettings", sdkReturn);
			}
			else {
				IPSettingsToMsgBox(Action.WRITE, IP);
			}
		}

		CursorDefault();
	}

	//====================================================================================

	class ActionHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			switch (e.getActionCommand()) {
			case RADIOGET:    EnableGetSetControls(false); break;
			case RADIOSET:    EnableGetSetControls(true);  break;
			case OPEN:        OpenSession();               break;
			case CLOSE:       CloseSession();              break;
			case RESPONSE:    ErrorResponse();             break;
			case CLEAR:       ClearMsg();                  break;
			case GENERAL:     GeneralCommand();            break;
			case FEEDMOVE:    FeedMove();                  break;
			case MOVEFILM:    MoveFilm();                  break;
			case LOCATION:    CardLocation();              break;
			case EJECT:       EjectCard();                 break;
			case FLIP:        FlipCard();                  break;
			case CLEAN:       CleanPrinter();              break;
			case RESTART:     RestartPrinter();            break;
			case TEST:        PrintTestCard();             break;
			case ERASE:       EraseCard();                 break;
			case HANDFEED:    HandFeed();                  break;
			case EJECTMODE:   EjectMode();                 break;
			case HORZEJECT:   HorzEject();                 break;
			case SMARTMODE:   SmartMode();                 break;
			case SMARTOFFSET: SmartOffset();               break;
			case ERASESPEED:  EraseSpeed();                break;
			case IPSETTINGS:  IPSettings();                break;
			}
		}
	}
}
