package com.bxl.eventtest;

import java.nio.ByteBuffer;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Set;

import jpos.JposConst;
import jpos.JposException;
import jpos.POSPrinter;
import jpos.POSPrinterConst;
import jpos.config.JposEntry;
import jpos.events.ErrorEvent;
import jpos.events.ErrorListener;
import jpos.events.OutputCompleteEvent;
import jpos.events.OutputCompleteListener;
import jpos.events.StatusUpdateEvent;
import jpos.events.StatusUpdateListener;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.bxl.BXLConst;
import com.bxl.config.editor.BXLConfigLoader;

public class MainActivity extends Activity 	implements OnItemClickListener, OnClickListener,
OutputCompleteListener, StatusUpdateListener, ErrorListener {

	private static final int REQUEST_CODE_BLUETOOTH = 1;

	private static final String DEVICE_ADDRESS_START = " (";
	private static final String DEVICE_ADDRESS_END = ")";

	private final ArrayList<CharSequence> bondedDevices = new ArrayList<>();
	private ArrayAdapter<CharSequence> arrayAdapter;

	private BXLConfigLoader bxlConfigLoader;
	private POSPrinter posPrinter;
	private String logicalName;
	private static String ESCAPE_SEQUENCE = new String(new byte[] {0x1b, 0x7c});
	
	private Button btnConnect;
	private Button btnPrint;
	private Button btnPrintReceipt;
	private Button btnPrintBitmap;
	private Button btnDisconnet;
	
	private int printerInch = 2;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		btnConnect = (Button)findViewById(R.id.buttonConnect);
		btnConnect.setOnClickListener(this);
		btnPrintReceipt = (Button)findViewById(R.id.buttonPrintReceipt);
		btnPrintReceipt.setOnClickListener(this);
		btnPrintBitmap = (Button)findViewById(R.id.buttonPrintBitmap);
		btnPrintBitmap.setOnClickListener(this);
		btnDisconnet = (Button)findViewById(R.id.buttonDisconnect);
		btnDisconnet.setOnClickListener(this);

		setBondedDevices();

		arrayAdapter = new ArrayAdapter<>(this,
				android.R.layout.simple_list_item_single_choice, bondedDevices);
		ListView listView = (ListView) findViewById(R.id.listViewPairedDevices);
		listView.setAdapter(arrayAdapter);

		listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
		listView.setOnItemClickListener(this);

		bxlConfigLoader = new BXLConfigLoader(this);
		try {
			bxlConfigLoader.openFile();
		} catch (Exception e) {
			e.printStackTrace();
			bxlConfigLoader.newFile();
		}
		
		posPrinter = new POSPrinter(this);
		posPrinter.addOutputCompleteListener(this);
		posPrinter.addStatusUpdateListener(this);
		posPrinter.addErrorListener(this);
		
		
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		try {
			posPrinter.close();
		} catch (JposException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
			startActivityForResult(intent, REQUEST_CODE_BLUETOOTH);
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == REQUEST_CODE_BLUETOOTH) {
			setBondedDevices();
		}
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		String device = ((TextView) view).getText().toString();

		logicalName = device.substring(0, device.indexOf(DEVICE_ADDRESS_START));

		String address = device.substring(device.indexOf(DEVICE_ADDRESS_START)
				+ DEVICE_ADDRESS_START.length(),
				device.indexOf(DEVICE_ADDRESS_END));

		try {
			for (Object entry : bxlConfigLoader.getEntries()) {
				JposEntry jposEntry = (JposEntry) entry;
				bxlConfigLoader.removeEntry(jposEntry.getLogicalName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		String strProduce = null;
		if(setProductName(logicalName).length() == 0){
			strProduce = logicalName;
		}else{
			strProduce = setProductName(logicalName);
		}

		try {
			bxlConfigLoader.addEntry(logicalName,
					BXLConfigLoader.DEVICE_CATEGORY_POS_PRINTER,
					strProduce,
					BXLConfigLoader.DEVICE_BUS_BLUETOOTH, address);

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

	private String setProductName(String name){
		String productName = null;

		if((logicalName.indexOf("SPP-R200II")>=0)){
			productName = BXLConst.SPP_R200II;
			setPrinterInch(2);
		}else if((logicalName.indexOf("SPP-R210")>=0)){
			productName = BXLConst.SPP_R210;
			setPrinterInch(2);
		}else if((logicalName.indexOf("SPP-R310")>=0)){
			productName = BXLConst.SPP_R310;
			setPrinterInch(3);
		}else if((logicalName.indexOf("SPP-R300")>=0)){
			productName = BXLConst.SPP_R300;
			setPrinterInch(3);
		}else if((logicalName.indexOf("SPP-R400")>=0)){
			productName = BXLConst.SPP_R400;
			setPrinterInch(4);
		}

		return productName;
	}
	
	private void setPrinterInch(int inch){
		printerInch = inch;
	}
	private int getPrinterInch(){
		return printerInch;
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.buttonConnect:
			connect();
			break;

		case R.id.buttonPrintReceipt:
			try {
				posPrinter.transactionPrint(POSPrinterConst.PTR_S_RECEIPT, POSPrinterConst.PTR_TP_TRANSACTION);
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				printReceipt();
				posPrinter.transactionPrint(POSPrinterConst.PTR_S_RECEIPT, POSPrinterConst.PTR_TP_NORMAL);

			} catch (JposException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			

			break;

		case R.id.buttonPrintBitmap:
			
			try {
				posPrinter.transactionPrint(POSPrinterConst.PTR_S_RECEIPT, POSPrinterConst.PTR_TP_TRANSACTION);
				printBitmap();
				posPrinter.transactionPrint(POSPrinterConst.PTR_S_RECEIPT, POSPrinterConst.PTR_TP_NORMAL);

			} catch (JposException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			
			break;


		case R.id.buttonDisconnect:
			disconnect();
			break;
		}
	}

	private void setBondedDevices() {
		logicalName = null;
		bondedDevices.clear();

		BluetoothAdapter bluetoothAdapter = BluetoothAdapter
				.getDefaultAdapter();
		Set<BluetoothDevice> bondedDeviceSet = bluetoothAdapter
				.getBondedDevices();

		for (BluetoothDevice device : bondedDeviceSet) {
			bondedDevices.add(device.getName() + DEVICE_ADDRESS_START
					+ device.getAddress() + DEVICE_ADDRESS_END);
		}

		if (arrayAdapter != null) {
			arrayAdapter.notifyDataSetChanged();
		}
	}

	private void connect() {
		try {
			posPrinter.open(logicalName);
			posPrinter.claim(0);
			posPrinter.setDeviceEnabled(true);
			posPrinter.setAsyncMode(true);


		} catch (JposException e) {
			try {
				posPrinter.close();
			} catch (JposException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
		}
	}

	private void disconnect() {
		try {
			posPrinter.close();
		} catch (JposException e) {
			Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();

		}
	}

	private void printReceipt(){

		try {
			printBitmap();
			
			String address = "";
			if(getPrinterInch() == 2){
				address = "BIXOLON Co.,Ltd.\n" + 
						"7th FL,\n" +
						"MiraeAsset Venture Tower 685,\n"+
						"Sampyeong-dong,Bundang-gu,\n" +
						"Seongnam-si,Gyeonggi-do,\n" +
						"463-400, Korea\n";
			}else if(getPrinterInch() == 4){
				address = "BIXOLON Co.,Ltd.\n" + 
						"7th FL, MiraeAsset Venture Tower 685, Sampyeong-dong, \n" +
						"Bundang-gu, Seongnam-si, Gyeonggi-do, 463-400, Korea\n";
			}else{
				address = "BIXOLON Co.,Ltd.\n" + 
						"7th FL, MiraeAsset Venture Tower 685,\n" +
						"Sampyeong-dong, Bundang-gu, Seongnam-si,\n" +
						"Gyeonggi-do, 463-400, Korea\n";
			}

			String data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
					ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" +  address + '\n';
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);


			String SEPARTOR = null;

			if(getPrinterInch() == 2){
				SEPARTOR = "--------------------------------";
			}else if(getPrinterInch() == 4){
				SEPARTOR = "-----------------------------------------------------------------";
			}else{
				SEPARTOR = "------------------------------------------";
			}


			data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
					ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" +  SEPARTOR + '\n';
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);

			String menu[] = {"hamburger",	"potato", "coke"};

			String[] count = {"1", "1", "1"};
			String[] price = {"10.90", "5.90", "5.50"};


			if(getPrinterInch() == 2){
				int maxWhiteSpace2 = 12;
				for (int i = 0; i < menu.length; i++) {
					StringBuffer buffer = new StringBuffer(menu[i]);
					for (int j = buffer.length(); j < 15; j++) {
						buffer.append(" ");
					}
					for (int j = count[i].length(); j < 5; j++) {
						buffer.append(" ");
					}
					buffer.append(count[i]);
					for (int j = price[i].length(); j < maxWhiteSpace2; j++) {
						buffer.append(" ");
					}
					buffer.append(price[i]);

					data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
							ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" +  buffer.toString() + '\n';
					posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);

				}	

			}else if(getPrinterInch() == 4){
				int maxWhiteSpace2 = 12;

				for (int i = 0; i < menu.length; i++) {
					StringBuffer buffer = new StringBuffer(menu[i]);
					for (int j = buffer.length(); j < 48; j++) {
						buffer.append(" ");
					}
					for (int j = count[i].length(); j < 5; j++) {
						buffer.append(" ");
					}
					buffer.append(count[i]);
					for (int j = price[i].length(); j < maxWhiteSpace2; j++) {
						buffer.append(" ");
					}
					buffer.append(price[i]);
					data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
							ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" +  buffer.toString() + '\n';
					posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);
				}
			}else{
				int maxWhiteSpace2 = 12;

				for (int i = 0; i < menu.length; i++) {
					StringBuffer buffer = new StringBuffer(menu[i]);
					for (int j = buffer.length(); j < 25; j++) {
						buffer.append(" ");
					}
					for (int j = count[i].length(); j < 5; j++) {
						buffer.append(" ");
					}
					buffer.append(count[i]);
					for (int j = price[i].length(); j < maxWhiteSpace2; j++) {
						buffer.append(" ");
					}
					buffer.append(price[i]);
					data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
							ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" +  buffer.toString() + '\n';
					posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);
				}
			}

			NumberFormat nf = NumberFormat.getInstance();
			nf.setMinimumFractionDigits(2);
			String subTotal = "20.27";
			String serviceCharge = "2.03";
			String total = "22.30";
			StringBuffer buffer = new StringBuffer();

			String whiteSpace = "";
			if(getPrinterInch() == 2){
				whiteSpace = "                      ";
			}else if(getPrinterInch() == 4){
				whiteSpace = "                                      ";
			}else{
				whiteSpace = "                            ";
			}

			int tabWidth1 = 9;
			int tabWidth2 = 33;
			String SEPARTOR2 = null;
			if(getPrinterInch() == 2){
				tabWidth1 = 2;
				tabWidth2 = 30;
				SEPARTOR = "--------------------------------\n";
				SEPARTOR2 = "---------\n";
			}else if(getPrinterInch() == 4){
				tabWidth1 = 15;
				tabWidth2 = 50;
				SEPARTOR = "-----------------------------------------------------------------\n";
				SEPARTOR2 = "----------------------------\n";
			}else{
				SEPARTOR = "------------------------------------------\n";
				SEPARTOR2 = "--------------\n";
			}

			buffer.append(SEPARTOR);
			for (int i = 0; i < tabWidth1; i++) {
				buffer.append(" ");
			}
			buffer.append("Sub-Total");
			for (int i = subTotal.length() + "Sub-Total".length(); i < tabWidth2; i++) {
				buffer.append(" ");
			}
			buffer.append(subTotal + "\n");
			for (int i = 0; i < tabWidth1; i++) {
				buffer.append(" ");
			}
			buffer.append("Service Charge(10%)");
			for (int i = serviceCharge.length() + "Service Charge(10%)".length(); i < tabWidth2; i++) {
				buffer.append(" ");
			}
			buffer.append(serviceCharge + "\n" + whiteSpace + SEPARTOR2);
			for (int i = 0; i < tabWidth1; i++) {
				buffer.append(" ");
			}
			buffer.append("Total");
			for (int i = nf.format(Double.parseDouble(total)).length() + "Total".length(); i < tabWidth2; i++) {
				buffer.append(" ");
			}
			buffer.append(nf.format(Double.parseDouble(total)) + "\n" + whiteSpace + SEPARTOR2);
			for (int i = 0; i < tabWidth1; i++) {
				buffer.append(" ");
			}

			data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
					ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" +  buffer.toString() + '\n';
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);

			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n\n");

			String info = "CALL FOR DELIVERY\n" +"031-218-5500\n" +	"www.bixolon.com\n";
			data = ESCAPE_SEQUENCE + "N" + ESCAPE_SEQUENCE + "cA" +
					ESCAPE_SEQUENCE + 1 + "hC" +  ESCAPE_SEQUENCE + 1 + "vC" + info + '\n';
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, data);

			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n\n\n\n\n");



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

	}

	private void printBitmap(){

		BitmapDrawable bitmapDrawable = null;
		Bitmap bitmap = null;

		try {

			bitmapDrawable = (BitmapDrawable)getResources().getDrawable(R.drawable.bixolon);
			bitmap = bitmapDrawable.getBitmap();

			ByteBuffer bitmapbuffer = ByteBuffer.allocate(4);
			bitmapbuffer.put((byte) POSPrinterConst.PTR_S_RECEIPT);
			bitmapbuffer.put((byte) 80);
			bitmapbuffer.put((byte) 0x00);
			bitmapbuffer.put((byte) 0x00);

			try {
				posPrinter.printBitmap(bitmapbuffer.getInt(0), bitmap, 200, POSPrinterConst.PTR_BM_CENTER);
			} catch (JposException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n");

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


	}


	@Override
	public void outputCompleteOccurred(final OutputCompleteEvent e) {
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				Toast.makeText(MainActivity.this, "complete print", Toast.LENGTH_SHORT).show();
			}
		});
	}

	@Override
	public void errorOccurred(final ErrorEvent arg0) {
		// TODO Auto-generated method stub
		runOnUiThread(new Runnable() {

			@Override
			public void run() {

				Toast.makeText(MainActivity.this, "Error status : " + getERMessage(arg0.getErrorCodeExtended()), Toast.LENGTH_SHORT).show();

				if(getERMessage(arg0.getErrorCodeExtended()).equals("Power off")){
					disconnect();
				}


			}
		});
	}

	@Override
	public void statusUpdateOccurred(final StatusUpdateEvent arg0) {
		// TODO Auto-generated method stub
		runOnUiThread(new Runnable() {

			@Override
			public void run() {
				Toast.makeText(MainActivity.this, "printer status : " + getSUEMessage(arg0.getStatus()), Toast.LENGTH_SHORT).show();

			}
		});

	}

	private static String getERMessage(int status){
		switch(status){
		case POSPrinterConst.JPOS_EPTR_COVER_OPEN:
			return "Cover open";

		case POSPrinterConst.JPOS_EPTR_REC_EMPTY:
			return "Paper empty";

		case JposConst.JPOS_SUE_POWER_OFF_OFFLINE:
			return "Power off";

		default:
			return "Unknown";
		}
	}


	private static String getSUEMessage(int status){
		switch(status){
		case JposConst.JPOS_SUE_POWER_ONLINE:
			return "Power on";

		case JposConst.JPOS_SUE_POWER_OFF_OFFLINE:
			return "Power off";

		case POSPrinterConst.PTR_SUE_COVER_OPEN:
			return "Cover Open";

		case POSPrinterConst.PTR_SUE_COVER_OK:
			return "Cover OK";

		case POSPrinterConst.PTR_SUE_REC_EMPTY:
			return "Receipt Paper Empty";

		case POSPrinterConst.PTR_SUE_REC_NEAREMPTY:
			return "Receipt Paper Near Empty";

		case POSPrinterConst.PTR_SUE_REC_PAPEROK:
			return "Receipt Paper OK";

		case POSPrinterConst.PTR_SUE_IDLE:
			return "Printer Idle";

		default:
			return "Unknown";
		}
	}

}
