package DTCDemo;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.TitledBorder;

import net.miginfocom.swing.MigLayout;
import SDK.SDKlib;
import SDK.SDKlib.Action;
import SDK.SDKlib.BitsPerChar;
import SDK.SDKlib.BitsPerInch;
import SDK.SDKlib.Coercivity;
import SDK.SDKlib.EncodingType;
import SDK.SDKlib.LRC;
import SDK.SDKlib.MagData;
import SDK.SDKlib.MagData2;
import SDK.SDKlib.MagDef;
import SDK.SDKlib.Parity;
import SDK.SDKlib.PrinterType;
import SDK.SDKlib.Return;
import SDK.SDKlib.Verify;

import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;

import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

import static DTCDemo.Utils.*;
import static DTCDemo.Main.tabbedPane;

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

class Encoding {
	private static final byte TRACK1 = 0x01;
	private static final byte TRACK2 = 0x02;
	private static final byte TRACK3 = 0x04;
	private static final byte ALL_TRACKS = TRACK1 | TRACK2 | TRACK3;

	private final String RADIOGET    = "RADIOGET";
	private final String RADIOSET    = "RADIOSET";
	private final String CLEAR       = "CLEAR";
	private final String MAGSTART    = "MAGSTART";
	private final String ENCODEMAG   = "ENCODEMAG";
	private final String ENCODETYPE  = "ENCODETYPE";
	private final String READMAG     = "READMAG";
	private final String READTRACKS  = "READTRACKS";
	private final String TRACKCLICK1 = "TRACKCLICK1";
	private final String TRACKCLICK2 = "TRACKCLICK2";
	private final String TRACKCLICK3 = "TRACKCLICK3";

	private final ActionHandler ah = new ActionHandler();

	public static final JPanel panelEncoding = new JPanel();

	private final JPanel panelMagStart = new JPanel();
	private final JButton btnMagStart = new JButton("Mag Start");
	private final JRadioButton rdbtnGet = new JRadioButton("Get");
	private final JRadioButton rdbtnSet = new JRadioButton("Set");
	private final ButtonGroup buttonGroup = new ButtonGroup();
	private final JLabel lblStartPosition = new JLabel("Start Position");
	private final JSpinner spinnerStartPosition = new JSpinner(new SpinnerNumberModel(0, 0, 85000, 1));
	
	private final JLabel labelType = new JLabel("Type");
	private final JComboBox<ComboItem> comboEncoding = new JComboBox<ComboItem>();
	private final JLabel labelCoercivity = new JLabel("Coercivity");
	private final JComboBox<ComboItem> comboCoercivity = new JComboBox<ComboItem>();
	private final JCheckBox checkVerify = new JCheckBox("Verify");
	private final JLabel labelTrack1 = new JLabel("Track 1");
	private final JCheckBox checkTrack1Write = new JCheckBox("");
	private final JTextField textTrack1 = new JTextField("THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG");
	private final JLabel labelTrack2 = new JLabel("Track 2");
	private final JCheckBox checkTrack2Write = new JCheckBox("");
	private final JTextField textTrack2 = new JTextField();
	private final JLabel labelTrack3 = new JLabel("Track 3");
	private final JCheckBox checkTrack3Write = new JCheckBox("");
	private final JTextField textTrack3 = new JTextField();
	private final JLabel labelBitsPerChar = new JLabel("Bits Per Char");
	private final JLabel labelBitsPerInch = new JLabel("Bits Per Inch");
	private final JLabel labelParity = new JLabel("Parity");
	private final JLabel labelLRC = new JLabel("LRC");
	private final JLabel labelConfigTrack1 = new JLabel("Track 1");
	private final JComboBox<ComboItem> comboT1BPC = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT1BPI = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT1Par = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT1LRC = new JComboBox<ComboItem>();
	private final JLabel labelConfigTrack2 = new JLabel("Track 2");
	private final JComboBox<ComboItem> comboT2BPC = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT2BPI = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT2Par = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT2LRC = new JComboBox<ComboItem>();
	private final JLabel labelConfigTrack3 = new JLabel("Track 3");
	private final JComboBox<ComboItem> comboT3BPC = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT3BPI = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT3Par = new JComboBox<ComboItem>();
	private final JComboBox<ComboItem> comboT3LRC = new JComboBox<ComboItem>();
	private final JButton btnEncodeMag = new JButton("Encode Mag");

	private final JCheckBox checkTrack1Read = new JCheckBox("Track 1");
	private final JCheckBox checkTrack2Read = new JCheckBox("Track 2");
	private final JCheckBox checkTrack3Read = new JCheckBox("Track 3");
	private final JButton btnReadMagTracks = new JButton("Read Mag Tracks");
	private final JButton btnReadMag = new JButton("Read Mag");

	private final JTextArea textEncodingMsg = new JTextArea();
	private final JScrollPane scrollPane = new JScrollPane(textEncodingMsg);    
	private final JButton btnClear = new JButton("Clear");

	private HANDLE hSession;
	private SDKlib SDK;

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

	public Encoding() {
		panelEncoding.setLayout(new MigLayout("", "[grow]", "[][][grow]"));
		
		panelEncoding.add(panelMagStart, "cell 0 0,grow");
		panelMagStart.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
				   													 "", 
																	 TitledBorder.LEADING,
																	 TitledBorder.TOP, 
																	 null, 
																	 new Color(0, 0, 0)));
		panelMagStart.setLayout(new MigLayout("", "[132.00,center][][98.00][][grow]", "[]"));
		
		panelMagStart.add(rdbtnGet, "flowx,cell 0 0");
		buttonGroup.add(rdbtnGet);
		rdbtnGet.setActionCommand(RADIOGET);
		rdbtnGet.addActionListener(ah);
		rdbtnGet.setSelected(true);
		
		panelMagStart.add(rdbtnSet, "cell 0 0");
		buttonGroup.add(rdbtnSet);
		rdbtnSet.setActionCommand(RADIOSET);
		rdbtnSet.addActionListener(ah);
		
		panelMagStart.add(lblStartPosition, "flowx,cell 1 0");
		panelMagStart.add(spinnerStartPosition, "cell 2 0,growx");
		spinnerStartPosition.setEnabled(false);

		panelMagStart.add(btnMagStart, "cell 4 0,alignx center");
		btnMagStart.setActionCommand(MAGSTART);
		btnMagStart.addActionListener(ah);
		
	// ===== Encode Panel =====
		JPanel panelSelections = new JPanel();
		panelSelections.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
																	   "",
                													   TitledBorder.LEADING,
                													   TitledBorder.TOP,
                													   null,
                													   new Color(0, 0, 0)));
		panelEncoding.add(panelSelections, "cell 0 1,grow");
		panelSelections.setLayout(new MigLayout("", "[42.00][90.00,grow][90.00,grow][90.00,grow][90.00,grow]", "[][][][][][][][][]"));
		labelType.setHorizontalAlignment(SwingConstants.LEFT);

		panelSelections.add(labelType, "cell 0 0,alignx left");
		panelSelections.add(comboEncoding, "cell 1 0,growx");
		comboEncoding.addItem(new ComboItem("ISO",  EncodingType.ISO));
		comboEncoding.addItem(new ComboItem("JIS2", EncodingType.JIS2));
		comboEncoding.setActionCommand(ENCODETYPE);
		comboEncoding.addActionListener(ah);

		panelSelections.add(labelCoercivity, "flowx,cell 2 0,alignx trailing");
		panelSelections.add(comboCoercivity, "cell 3 0,growx");
		comboCoercivity.addItem(new ComboItem("Default", Coercivity.DEFAULT));
		comboCoercivity.addItem(new ComboItem("HiCo", Coercivity.HI_CO));
		comboCoercivity.addItem(new ComboItem("LoCo", Coercivity.LO_CO));

		panelSelections.add(checkVerify, "cell 4 0,alignx right");
		checkVerify.setSelected(true);

		panelSelections.add(labelTrack1, "flowx,cell 0 1");
		panelSelections.add(checkTrack1Write, "cell 0 1");
		checkTrack1Write.setSelected(true);
		checkTrack1Write.setActionCommand(TRACKCLICK1);
		checkTrack1Write.addActionListener(ah);
		panelSelections.add(textTrack1, "cell 1 1 4 1,growx");

		labelTrack2.setEnabled(false);
		panelSelections.add(labelTrack2, "flowx,cell 0 2");
		panelSelections.add(checkTrack2Write, "cell 0 2");
		checkTrack2Write.setActionCommand(TRACKCLICK2);
		checkTrack2Write.addActionListener(ah);
		textTrack2.setEnabled(false);
		panelSelections.add(textTrack2, "cell 1 2 4 1,growx");

		labelTrack3.setEnabled(false);
		panelSelections.add(labelTrack3, "flowx,cell 0 3");
		panelSelections.add(checkTrack3Write, "cell 0 3");
		checkTrack3Write.setActionCommand(TRACKCLICK3);
		checkTrack3Write.addActionListener(ah);
		textTrack3.setEnabled(false);
		panelSelections.add(textTrack3, "cell 1 3 4 1,growx");

		panelSelections.add(labelBitsPerChar, "cell 1 4,alignx center");
		panelSelections.add(labelBitsPerInch, "cell 2 4,alignx center");
		panelSelections.add(labelParity, "cell 3 4,alignx center");
		panelSelections.add(labelLRC, "cell 4 4,alignx center");

		panelSelections.add(labelConfigTrack1, "cell 0 5,alignx left");

		panelSelections.add(comboT1BPC, "cell 1 5,growx");
		comboT1BPC.addItem(new ComboItem("Default", BitsPerChar.DEFAULT));
		comboT1BPC.addItem(new ComboItem("1", BitsPerChar.BPC1));
		comboT1BPC.addItem(new ComboItem("5", BitsPerChar.BPC5));
		comboT1BPC.addItem(new ComboItem("7", BitsPerChar.BPC7));

		panelSelections.add(comboT1BPI, "cell 2 5,growx");
		comboT1BPI.addItem(new ComboItem("Default", BitsPerInch.DEFAULT));
		comboT1BPI.addItem(new ComboItem("210", BitsPerInch.BPI210));
		comboT1BPI.addItem(new ComboItem("75", BitsPerInch.BPI75));

		panelSelections.add(comboT1Par, "cell 3 5,growx");
		comboT1Par.addItem(new ComboItem("Default", Parity.DEFAULT));
		comboT1Par.addItem(new ComboItem("Odd", Parity.ODD));
		comboT1Par.addItem(new ComboItem("Even", Parity.EVEN));
		comboT1Par.addItem(new ComboItem("Off", Parity.OFF));

		panelSelections.add(comboT1LRC, "cell 4 5,growx");
		comboT1LRC.addItem(new ComboItem("Default", LRC.DEFAULT));
		comboT1LRC.addItem(new ComboItem("Odd", LRC.ODD));
		comboT1LRC.addItem(new ComboItem("Even", LRC.EVEN));
		comboT1LRC.addItem(new ComboItem("Off", LRC.OFF));

		labelConfigTrack2.setEnabled(false);
		panelSelections.add(labelConfigTrack2, "cell 0 6,alignx left");

		comboT2BPC.setEnabled(false);
		panelSelections.add(comboT2BPC, "cell 1 6,growx");
		comboT2BPC.addItem(new ComboItem("Default", BitsPerChar.DEFAULT));
		comboT2BPC.addItem(new ComboItem("1", BitsPerChar.BPC1));
		comboT2BPC.addItem(new ComboItem("5", BitsPerChar.BPC5));
		comboT2BPC.addItem(new ComboItem("7", BitsPerChar.BPC7));

		comboT2BPI.setEnabled(false);
		panelSelections.add(comboT2BPI, "cell 2 6,growx");
		comboT2BPI.addItem(new ComboItem("Default", BitsPerInch.DEFAULT));
		comboT2BPI.addItem(new ComboItem("210", BitsPerInch.BPI210));
		comboT2BPI.addItem(new ComboItem("75", BitsPerInch.BPI75));

		comboT2Par.setEnabled(false);
		panelSelections.add(comboT2Par, "cell 3 6,growx");
		comboT2Par.addItem(new ComboItem("Default", Parity.DEFAULT));
		comboT2Par.addItem(new ComboItem("Odd", Parity.ODD));
		comboT2Par.addItem(new ComboItem("Even", Parity.EVEN));
		comboT2Par.addItem(new ComboItem("Off", Parity.OFF));
		
		comboT2LRC.setEnabled(false);
		panelSelections.add(comboT2LRC, "cell 4 6,growx");
		comboT2LRC.addItem(new ComboItem("Default", LRC.DEFAULT));
		comboT2LRC.addItem(new ComboItem("Odd", LRC.ODD));
		comboT2LRC.addItem(new ComboItem("Even", LRC.EVEN));
		comboT2LRC.addItem(new ComboItem("Off", LRC.OFF));
		
		labelConfigTrack3.setEnabled(false);
		panelSelections.add(labelConfigTrack3, "cell 0 7,alignx left");

		comboT3BPC.setEnabled(false);
		panelSelections.add(comboT3BPC, "cell 1 7,growx");
		comboT3BPC.addItem(new ComboItem("Default", BitsPerChar.DEFAULT));
		comboT3BPC.addItem(new ComboItem("1", BitsPerChar.BPC1));
		comboT3BPC.addItem(new ComboItem("5", BitsPerChar.BPC5));
		comboT3BPC.addItem(new ComboItem("7", BitsPerChar.BPC7));

		comboT3BPI.setEnabled(false);
		panelSelections.add(comboT3BPI, "cell 2 7,growx");
		comboT3BPI.addItem(new ComboItem("Default", BitsPerInch.DEFAULT));
		comboT3BPI.addItem(new ComboItem("210", BitsPerInch.BPI210));
		comboT3BPI.addItem(new ComboItem("75", BitsPerInch.BPI75));

		comboT3Par.setEnabled(false);
		panelSelections.add(comboT3Par, "cell 3 7,growx");
		comboT3Par.addItem(new ComboItem("Default", Parity.DEFAULT));
		comboT3Par.addItem(new ComboItem("Odd", Parity.ODD));
		comboT3Par.addItem(new ComboItem("Even", Parity.EVEN));
		comboT3Par.addItem(new ComboItem("Off", Parity.OFF));

		comboT3LRC.setEnabled(false);
		panelSelections.add(comboT3LRC, "cell 4 7,growx");
		comboT3LRC.addItem(new ComboItem("Default", LRC.DEFAULT));
		comboT3LRC.addItem(new ComboItem("Odd", LRC.ODD));
		comboT3LRC.addItem(new ComboItem("Even", LRC.EVEN));
		comboT3LRC.addItem(new ComboItem("Off", LRC.OFF));

		panelSelections.add(btnEncodeMag, "cell 0 8 5 1,alignx center");
		btnEncodeMag.setActionCommand(ENCODEMAG);
		btnEncodeMag.addActionListener(ah);

		// ===== Read Mag Panel =====
		JPanel panelResults = new JPanel();
		panelResults.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), 
				                                "", 
				                                TitledBorder.LEADING,
				                                TitledBorder.TOP, 
				                                null, 
				                                new Color(0, 0, 0)));
		panelEncoding.add(panelResults, "cell 0 2,grow");
		panelResults.setLayout(new MigLayout("", "[70.00][88.00][grow]", "[][grow][]"));

		panelResults.add(checkTrack1Read, "flowx,cell 0 0,alignx left,aligny baseline");
		checkTrack1Read.setSelected(true);
		panelResults.add(checkTrack2Read, "cell 0 0");
		checkTrack2Read.setSelected(true);
		panelResults.add(checkTrack3Read, "cell 0 0");
		checkTrack3Read.setSelected(true);

		panelResults.add(btnReadMagTracks, "cell 1 0,growx");
		btnReadMagTracks.setActionCommand(READTRACKS);
		btnReadMagTracks.addActionListener(ah);

		panelResults.add(btnReadMag, "cell 2 0,alignx right");
		btnReadMag.setActionCommand(READMAG);
		btnReadMag.addActionListener(ah);
		
		panelResults.add(scrollPane, "cell 0 1 3 1,grow");
		textEncodingMsg.setEditable(false);
		textEncodingMsg.setBorder(BorderFactory.createLineBorder(Color.black));

		panelResults.add(btnClear, "cell 0 2 3 1,alignx center");
		btnClear.setActionCommand(CLEAR);
		btnClear.addActionListener(ah);
	}

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

	void Init(HANDLE handle, SDKlib sdk) {
		tabbedPane.addTab("Mag Encoding", null, panelEncoding, null);
		this.hSession = handle;
		this.SDK = sdk;

		if (connectedPrinter == PrinterType.GENERATION2) {
			labelParity.setVisible(false);
			labelLRC.setVisible(false);
			comboT1Par.setVisible(false);
			comboT2Par.setVisible(false);
			comboT3Par.setVisible(false);
			comboT1LRC.setVisible(false);
			comboT2LRC.setVisible(false);
			comboT3LRC.setVisible(false);

			//...Magnetic Encoding Start Position
			IntByReference MagStart = new IntByReference();
			GetMagStart(MagStart);
		}
		else {
			btnMagStart.setEnabled(false);
			rdbtnGet.setEnabled(false);
			rdbtnSet.setEnabled(false);
		}
	}

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

	private void GetSetControls(Boolean state) {
		spinnerStartPosition.setEnabled(state);
	}

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

	private void EncodingChanged() {
		// Enable/Disable appropriate controls according to ISO or JIS2 being selected
		Boolean visible = (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.ISO);

		checkTrack1Write.setVisible(visible);
		labelConfigTrack1.setVisible(visible);
		labelTrack2.setVisible(visible);
		textTrack2.setVisible(visible);
		checkTrack2Write.setVisible(visible);
		labelConfigTrack2.setVisible(visible);
		labelTrack3.setVisible(visible);
		textTrack3.setVisible(visible);
		checkTrack3Write.setVisible(visible);
		labelConfigTrack3.setVisible(visible);

		comboT1BPC.setVisible(visible);
		comboT1BPI.setVisible(visible);
		comboT2BPC.setVisible(visible);
		comboT2BPI.setVisible(visible);
		comboT3BPC.setVisible(visible);
		comboT3BPI.setVisible(visible);
		labelBitsPerChar.setVisible(visible);
		labelBitsPerInch.setVisible(visible);
		
		if (connectedPrinter == PrinterType.ENDURO) {
			comboT1LRC.setVisible(visible);
			comboT1Par.setVisible(visible);
			comboT2LRC.setVisible(visible);
			comboT2Par.setVisible(visible);
			comboT3LRC.setVisible(visible);
			comboT3Par.setVisible(visible);
			labelParity.setVisible(visible);
			labelLRC.setVisible(visible);
		}
		
		labelTrack1.setText(visible ? "Track 1" : "Data");

		checkTrack1Read.setVisible(visible);
		checkTrack2Read.setVisible(visible);
		checkTrack3Read.setVisible(visible);
		btnReadMagTracks.setVisible(visible);
	}

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

	private void CheckDataAvailable() {
		btnEncodeMag.setEnabled(   checkTrack1Write.isSelected()
				                || checkTrack2Write.isSelected() 
				                || checkTrack3Write.isSelected());
	}

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

	private void Track1Clicked() {
		// Enable/Disable the appropriate controls according to the selection
		Boolean control = checkTrack1Write.isSelected();
		labelTrack1.setEnabled(control);
		labelConfigTrack1.setEnabled(control);
		textTrack1.setEnabled(control);
		comboT1BPC.setEnabled(control);
		comboT1BPI.setEnabled(control);
		
		if (connectedPrinter == PrinterType.ENDURO) {
			comboT1Par.setEnabled(control);
			comboT1LRC.setEnabled(control);
		}

		CheckDataAvailable();
	}

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

	private void Track2Clicked() {
		// Enable/Disable the appropriate controls according to the selection
		Boolean control = checkTrack2Write.isSelected();
		labelTrack2.setEnabled(control);
		labelConfigTrack2.setEnabled(control);
		textTrack2.setEnabled(control);
		comboT2BPC.setEnabled(control);
		comboT2BPI.setEnabled(control);

		if (connectedPrinter == PrinterType.ENDURO) {
			comboT2Par.setEnabled(control);
			comboT2LRC.setEnabled(control);
		}

		CheckDataAvailable();
	}

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

	private void Track3Clicked() {
		// Enable/Disable the appropriate controls according to the selection
		Boolean control = checkTrack3Write.isSelected();
		labelTrack3.setEnabled(control);
		labelConfigTrack3.setEnabled(control);
		textTrack3.setEnabled(control);
		comboT3BPC.setEnabled(control);
		comboT3BPI.setEnabled(control);
		
		if (connectedPrinter == PrinterType.ENDURO) {
			comboT3Par.setEnabled(control);
			comboT3LRC.setEnabled(control);
		}

		CheckDataAvailable();
	}

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

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

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

	private final char ISO_7_BIT_START_SENTINEL = '%';
	private final char ISO_5_BIT_START_SENTINEL = ';';
	private final char ISO_END_SENTINEL         = '?';
	private final char JIS2_SENTINEL            = 0x7f;

	private void EncodeMagData() {
		CursorWait();

		// Initialise common encoding parameters
		MagDef Def = new MagDef();
		Def.encoding   = ((ComboItem)comboEncoding.getSelectedItem()).getValue();
		Def.verify     = checkVerify.isSelected() ? Verify.ON : Verify.OFF;
		Def.coercivity = ((ComboItem)comboCoercivity.getSelectedItem()).getValue();

		if (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.JIS2) {
			Def.track[0].data = JIS2_SENTINEL + textTrack1.getText() + JIS2_SENTINEL;
		}

		else {
			// ISO Track 1
			if (checkTrack1Write.isSelected()) {
				// Initialise for ISO Track 1 Encoding
				if (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.ISO) {
					Def.track[0].data = ISO_7_BIT_START_SENTINEL + textTrack1.getText() + ISO_END_SENTINEL;
				}
				else {
					Def.track[0].data = textTrack1.getText();
				}
				Def.track[0].bitsPerChar = ((ComboItem)comboT1BPC.getSelectedItem()).getValue();
				Def.track[0].bitsPerInch = ((ComboItem)comboT1BPI.getSelectedItem()).getValue();
				if (connectedPrinter == PrinterType.ENDURO) {
					Def.track[0].parity = ((ComboItem)comboT1Par.getSelectedItem()).getValue();
					Def.track[0].lrc    = ((ComboItem)comboT1LRC.getSelectedItem()).getValue();
				}
			}

			// ISO Track 2
			if (checkTrack2Write.isSelected()) {
				// Initialise for ISO Track 2 Encoding
				if (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.ISO) {
					Def.track[1].data = ISO_5_BIT_START_SENTINEL + textTrack2.getText() + ISO_END_SENTINEL;
				}
				else {
					Def.track[1].data = textTrack2.getText();
				}
				Def.track[1].bitsPerChar = ((ComboItem)comboT2BPC.getSelectedItem()).getValue();
				Def.track[1].bitsPerInch = ((ComboItem)comboT2BPI.getSelectedItem()).getValue();
				if (connectedPrinter == PrinterType.ENDURO) {
					Def.track[1].parity = ((ComboItem)comboT2Par.getSelectedItem()).getValue();
					Def.track[1].lrc    = ((ComboItem)comboT2LRC.getSelectedItem()).getValue();
				}
			}

			// ISO Track 3
			if (checkTrack3Write.isSelected()) {
				// Initialise for ISO Track 3 Encoding
				if (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.ISO) {
					Def.track[2].data = ISO_5_BIT_START_SENTINEL + textTrack3.getText() + ISO_END_SENTINEL;
				}
				else {
					Def.track[2].data = textTrack3.getText();
				}
				Def.track[2].bitsPerChar = ((ComboItem)comboT3BPC.getSelectedItem()).getValue();
				Def.track[2].bitsPerInch = ((ComboItem)comboT3BPI.getSelectedItem()).getValue();
				if (connectedPrinter == PrinterType.ENDURO) {
					Def.track[2].parity = ((ComboItem)comboT3Par.getSelectedItem()).getValue();
					Def.track[2].lrc    = ((ComboItem)comboT3LRC.getSelectedItem()).getValue();
				}
			}
		}

		// Call SDK to perform the mag encoding
		byte sdkReturn = SDK.ID_EncodeMag(hSession, Def);
		if (sdkReturn != Return.SUCCESS) {
			DisplayError("EncodeMagStripe", sdkReturn);
		} 
		else {
			// Wait for the printer to complete the encoding
			sdkReturn = WaitForPrinterToFinish(hSession, SDK);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("EncodeMagStripeWait", sdkReturn);
			}
		}

		CursorDefault();
	}

	//****************************************************************************
	
	private void DisplayEnduroMagData(SDK.SDKlib.MagData MagData, int Tracks) {
		String temp;

		//Output the data to the message box
		if ((Tracks & TRACK1) != 0)
		{
			temp = "(1): ";
			temp += MagData.tk1_pass ? "PASS," : "FAIL";
			temp += MagData.tk1;
			textEncodingMsg.append(temp + "\n");
		}

		if (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.ISO) {
			if ((Tracks & TRACK2) != 0)
			{
				temp = "(2): ";
				temp += !MagData.tk2_pass ? "PASS," : "FAIL";
				temp += MagData.tk2;
				textEncodingMsg.append(temp + "\n");
			}

			if ((Tracks & TRACK3) != 0)
			{
				temp = "(3): ";
				temp += MagData.tk3_pass ? "PASS," : "FAIL";
				temp += MagData.tk3;
				textEncodingMsg.append(temp + "\n");
			}
		}
		textEncodingMsg.append("\n");
	}

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

	private void DisplayGeneration2MagData(SDK.SDKlib.MagData2 MagData, int Tracks) {
		//Output the data to the message box
		if ((Tracks & TRACK1) != 0) 
			textEncodingMsg.append("(1): " + MagData.track1 + "\n");
		
		if (((ComboItem)comboEncoding.getSelectedItem()).getValue() == EncodingType.ISO) {
			if ((Tracks & TRACK2) != 0) 
				textEncodingMsg.append("(2): " + MagData.track2 + "\n");
			if ((Tracks & TRACK3) != 0) 
				textEncodingMsg.append("(3): " + MagData.track3 + "\n");
		}
		textEncodingMsg.append("\n");
	}

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

	private void ReadMagData(byte Tracks) {
		CursorWait();

		byte sdkReturn;
		if (connectedPrinter == PrinterType.GENERATION2) {
			MagData2 MD = new MagData2();
			sdkReturn = SDK.ID_ReadMagTracks(hSession, 
										     MD,
										     ((ComboItem)comboEncoding.getSelectedItem()).getValue(),
										     Tracks);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("ReadMagStripe", sdkReturn);
			}
			else {
				DisplayGeneration2MagData(MD, Tracks);
			}
		}
		else {
			MagData MD = new MagData();
			sdkReturn = SDK.ID_ReadMagTracks(hSession, 
										     MD,
										     ((ComboItem)comboEncoding.getSelectedItem()).getValue(),
										     Tracks);
			if (sdkReturn != Return.SUCCESS) {
				DisplayError("ReadMagStripe", sdkReturn);
			}
			else {
				DisplayEnduroMagData(MD, Tracks);
			}
		}
		
		CursorDefault();
	}

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

	private void ReadMagTracks() {
		byte Tracks = 0;
		if (checkTrack1Read.isSelected()) Tracks |= 0x01;
		if (checkTrack2Read.isSelected()) Tracks |= 0x02;
		if (checkTrack3Read.isSelected()) Tracks |= 0x04;

		if (Tracks != 0) {
			ReadMagData(Tracks);
		}
	}

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

	private byte GetMagStart(IntByReference MagStart) {
		byte SDKReturn = SDK.ID_MagStart(hSession, Action.READ, MagStart);
		if (SDKReturn != Return.SUCCESS) {
			DisplayError("MagStart", SDKReturn);
		}
		else {
			spinnerStartPosition.setValue(MagStart.getValue());
		}

		return SDKReturn;
	}

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

	private void MagStartToMsgBox(int MagStart, byte action) {
		//Update the message box with the Start Position setting
		textEncodingMsg.append("MagStart" + Separator(action) + MagStart + "\n\n");
	}

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


	private void MagStart() {
		IntByReference MagStart = new IntByReference();

		if (rdbtnGet.isSelected()) {
			if (GetMagStart(MagStart) == Return.SUCCESS) {
				MagStartToMsgBox(MagStart.getValue(), Action.READ);
			}
		}
		else {
			//Call the SDK to write to the driver
			MagStart.setValue((int)spinnerStartPosition.getValue());
			int SDKReturn = SDK.ID_MagStart(hSession, Action.WRITE, MagStart);
			if (SDKReturn != Return.SUCCESS) {
				DisplayError("SetMagStart", SDKReturn);
			}
			else {
				MagStartToMsgBox(MagStart.getValue(), Action.WRITE);
			}
		}
	}

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

	class ActionHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			switch (e.getActionCommand()) {
			case RADIOGET:    GetSetControls(false);   break;
			case RADIOSET:    GetSetControls(true);    break;
			case CLEAR:       ClearMsg();              break;
			case MAGSTART:    MagStart();              break;
			case ENCODETYPE:  EncodingChanged();       break;
			case ENCODEMAG:   EncodeMagData();         break;
			case TRACKCLICK1: Track1Clicked();         break;
			case TRACKCLICK2: Track2Clicked();         break;
			case TRACKCLICK3: Track3Clicked();         break;
			case READTRACKS:  ReadMagTracks();         break;
			case READMAG:     ReadMagData(ALL_TRACKS); break;
			}
		}
	}
}
