package com.bixolon.farsitest;

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

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

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.util.Log;
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.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
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;

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

	private String TAG = MainActivity.class.toString();

	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 String logicalName = null;
	private String strProductName = BXLConst.SRP_350PLUSIII;

	private BXLConfigLoader bxlConfigLoader;
	private POSPrinter posPrinter;

	private Button btnConnect;
	private Button btnPrintText;
	private Button btnPrintTest;
	private Button btnDisconnect;

	private EditText editText;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btnConnect = (Button)findViewById(R.id.buttonConnect);
		btnConnect.setOnClickListener(this);
		btnPrintText = (Button)findViewById(R.id.buttonPrintText);
		btnPrintText.setOnClickListener(this);
		btnPrintTest = (Button)findViewById(R.id.buttonPrintTest);
		btnPrintTest.setOnClickListener(this);
		btnDisconnect = (Button)findViewById(R.id.buttonDisconnect);
		btnDisconnect.setOnClickListener(this);
		editText = (EditText)findViewById(R.id.editText1);

		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);

		if(bxlConfigLoader == null){
			bxlConfigLoader = new BXLConfigLoader(this);
		}
		try {
			bxlConfigLoader.openFile();
		} catch (Exception e) {
			e.printStackTrace();
			bxlConfigLoader.newFile();
		}

		if (posPrinter == null) {
			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) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		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 onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.buttonConnect:
			connect();
			break;

		case R.id.buttonPrintText:

			try {
				posPrinter.setCharacterSet(BXLConst.CS_FARSI);
				posPrinter.setOptReorderForFarsi(BXLConst.OPT_REORDER_FARSI_MIXED);
			} catch (JposException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			if(editText.getText().toString().length()>0){
				String data = editText.getText().toString();
				printInputData(data);
				
			}

			break;


		case R.id.buttonPrintTest:

			try {
				posPrinter.setCharacterSet(BXLConst.CS_FARSI);
				posPrinter.setOptReorderForFarsi(BXLConst.OPT_REORDER_FARSI_MIXED);
				printReceiptforFarsi();
				posPrinter.setCharacterSet(BXLConst.CS_FARSI);
				posPrinter.setOptReorderForFarsi(BXLConst.OPT_REORDER_FARSI_RTL);
				printReceiptforFarsi();

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

			break;



		case R.id.buttonDisconnect:
			disconnect();

			break;

		default:
			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();

		}
	}


	@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();
		}

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

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


	private void printInputData(String data){
		
		String[] data_line= data.split("\n");
		int cntLine = 0;
		for(int i = 0; i<data.length()-1; i++){
			if(data.substring(i, i+1).equals("\n")){
				cntLine++;
			}
		}
		String[] Str_Lines = new String[cntLine+1];
		for(int i = 0; i<Str_Lines.length; i++){
			Str_Lines[i] = "\n";
		}
		for(int i = 0; i<data_line.length; i++){
			if(data_line[i].length() !=0){
				Str_Lines[i] = data_line[i];
			}
		}
		
		try {
			for(int i = 0; i<Str_Lines.length; i++){
				posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + Str_Lines[i] + EscapeSequence.Right_justify
						+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);
			}
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n\n");
		} catch (JposException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void printReceiptforFarsi(){

		BitmapDrawable bitmapDrawable = null;
		Bitmap bitmap = null;

		try {
			
			bitmapDrawable = (BitmapDrawable)this.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, posPrinter.getRecLineWidth(), POSPrinterConst.PTR_BM_CENTER);
			} catch (JposException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

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


			String address = "";
			address = "BIXOLON شرکت با مسئولیت محدود . 7 FL،";
			address += "MiraeAsset سرمایه گذاری برج 685 ،" ;
			address += "Sampyeong دونگ، Bundang گو ، سئونگنام - سی،"; 
			address += "گیونگی-دو ، 463-400 ، کره";

			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + address + EscapeSequence.Right_justify
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);


			String SEPARTOR = null;
			SEPARTOR = "------------------------------------------";


			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + SEPARTOR + EscapeSequence.Right_justify
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);

			String[] menu = {"زن محصولات", "Inners زن", "Inners مرد", "به پایان می رسد مرد", "زن به پایان می رسد", "تاپس زن", "تاپس مرد"};
			String[] count = {"2", "3", "2", "3", "2", "1", "1"};
			String[] price = {"17.00", "31.50", "17.00", "67.50", "40.00", "20.00", "20.50"};

			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]);

				posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + buffer.toString()  + EscapeSequence.Right_justify
						+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);
			}

			SEPARTOR = "------------------------------------------";
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" +SEPARTOR + EscapeSequence.Right_justify
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);

			NumberFormat nf = NumberFormat.getInstance();
			nf.setMinimumFractionDigits(2);
			String subTotal = "192.15";
			String serviceCharge = "-21.35";
			String total = "213.50";
			StringBuffer buffer = new StringBuffer();

			buffer.append("\n" + "زیر کل");
			for (int i = "زیر کل".length() + subTotal.length(); i < 42/*tabWidth2*/; i++) {
				buffer.append(" ");
			}
			buffer.append(subTotal);
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, buffer.toString() + EscapeSequence.Right_justify
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);


			buffer = new StringBuffer();
			buffer.append("\n" + "هزینه سرویس (10%)");
			for (int i = "هزینه سرویس (10%)".length() + serviceCharge.length(); i < 42/*tabWidth2*/; i++) {
				buffer.append(" ");
			}
			buffer.append(serviceCharge);
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, buffer.toString() + EscapeSequence.Right_justify
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);

			buffer = new StringBuffer();
			buffer.append("\n" + "جمع");
			for (int i = "جمع".length() + nf.format(Double.parseDouble(total)).length(); i < 42/*tabWidth2*/; i++) {
				buffer.append(" ");
			}
			buffer.append(nf.format(Double.parseDouble(total))+  "\n" + SEPARTOR);

			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, buffer.toString() + EscapeSequence.Right_justify
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n\n");


			String data = "\n" +"CALL برای تحویل" ;
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + data + EscapeSequence.Center
					+ EscapeSequence.Underline 
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);

			data = "\n" +"031-218-5500";
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + data + EscapeSequence.Center
					+ EscapeSequence.Disabled_underline + EscapeSequence.Bold 
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);

			data = "\n"  +"www.bixolon.com";
			posPrinter.printNormal(POSPrinterConst.PTR_S_RECEIPT, "\n" + data + EscapeSequence.Center
					+ EscapeSequence.Underline + EscapeSequence.Bold 
					+ EscapeSequence.Scale_1_time_horizontally + EscapeSequence.Scale_1_time_vertically);


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

			posPrinter.cutPaper(90);   


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

	}


	private String[] process_line_data(String data, int lenChar){
		int cnt = 0;
		int LineChar = lenChar;
		if(data.length()>LineChar){
			cnt = data.length()/LineChar +1;
		}
		String[] line_data = new String[cnt];

		int k = 0;
		for(int i = 0; i<cnt; i++){
			if(data.length()-k > LineChar){
				line_data[i] = data.substring(k, k+LineChar);
				k += LineChar;
			}else{
				line_data[i] = data.substring(k, data.length());
			}
		}
		return line_data;
	}
	
	@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();

				if(getSUEMessage(arg0.getStatus()).equals("Power off")){
					disconnect();
				}else if(getSUEMessage(arg0.getStatus()).equals("Power off")){
					disconnect();
				}else if(getSUEMessage(arg0.getStatus()).equals("Cover Open")){
					Toast.makeText(MainActivity.this, "check the printer - Cover Open", Toast.LENGTH_SHORT).show();
				}else if(getSUEMessage(arg0.getStatus()).equals("Cover OK")){
					Toast.makeText(MainActivity.this, "check the printer - Cover OK", Toast.LENGTH_SHORT).show();
				}else if(getSUEMessage(arg0.getStatus()).equals("Receipt Paper Empty")){
					Toast.makeText(MainActivity.this, "check the printer - Receipt Paper Empty", Toast.LENGTH_SHORT).show();
				}else if(getSUEMessage(arg0.getStatus()).equals("Receipt Paper OK")){
					Toast.makeText(MainActivity.this, "check the printer - Receipt Paper OK", 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";
		}
	}
}
