package com.xinzhongxin.bletester;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.UUID;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.xinzhongxin.service.BleService;
import com.xinzhongxinbletester.R;

public class ChangeCharActivity extends Activity implements OnClickListener {
	TextView descriptor1;
	TextView descriptor2;
	TextView charHex;
	TextView charString;
	TextView charformat;
	TextView time;
	TextView resultcount;
	Button writeButton;
	Button readButton;
	Button clear_result;
	Button notifyButton;
	Button save_result;
	ScrollView scroll;
	TextView notify_resualt;
	RadioGroup radioGroup;
	RadioButton format_hex;
	RadioButton format_string;
	Button timing_write;
	Boolean writing = false;
	EditText write_time;
	UUID charUuid;
	UUID serUuid;
	BleService bleService;
	BluetoothGattCharacteristic gattChar;
	SharedPreferences sharedPreferences;
	SharedPreferences.Editor editor;
	String text_hex = null;
	String text_string = null;
	String result = null;
	String resultLength = null;
	int resultLengthNum;
	int prop;
	int rssi;
	long period;
	int write_byte_number;
	boolean startNotify;
	boolean isNotifyHex;
	boolean isHex;

	private ServiceConnection conn = new ServiceConnection() {
		@SuppressLint("NewApi")
		@Override
		public void onServiceConnected(ComponentName arg0, IBinder service) {
			// TODO Auto-generated method stub
			bleService = ((BleService.LocalBinder) service).getService();
			gattChar = bleService.mBluetoothGatt.getService(serUuid)
					.getCharacteristic(charUuid);
			bleService.mBluetoothGatt.readCharacteristic(gattChar);
			if (gattChar.getDescriptors().size() != 0) {
				BluetoothGattDescriptor des = gattChar.getDescriptors().get(0);
				des.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
				bleService.mBluetoothGatt.writeDescriptor(des);
			}
			int prop = gattChar.getProperties();
			if ((prop & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
				bleService.mBluetoothGatt.setCharacteristicNotification(
						gattChar, false);
			}
			if ((prop & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
				bleService.mBluetoothGatt.setCharacteristicNotification(
						gattChar, false);
			}
			if ((prop & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
				bleService.mBluetoothGatt.setCharacteristicNotification(
						gattChar, false);
			}
			if ((prop & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
				bleService.mBluetoothGatt.setCharacteristicNotification(
						gattChar, true);
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {
			// TODO Auto-generated method stub
			bleService = null;
		}
	};

	BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

		@SuppressLint("NewApi")
		@Override
		public void onReceive(Context arg0, Intent intent) {
			// TODO Auto-generated method stub
			String action = intent.getAction();
			if (BleService.ACTION_GATT_RSSI.equals(action)) {
				rssi = intent.getExtras().getInt(BleService.EXTRA_DATA_RSSI);
				ChangeCharActivity.this.invalidateOptionsMenu();
			}
			if (BleService.ACTION_CHAR_READED.equals(action)) {
				final String des1String = intent.getExtras().getString(
						"desriptor1");
				final String des2String = intent.getExtras().getString(
						"desriptor2");
				final String stringValue = intent.getExtras().getString(
						"StringValue");
				final String hexValue = intent.getExtras()
						.getString("HexValue");
				final String readTime = intent.getExtras().getString("time");
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						// TODO Auto-generated methdo stub
						charString.setText("�ַ���: " + stringValue);
						charHex.setText("ʮ������: " + hexValue);
						time.setText("��ȡʱ��: " + readTime);
						descriptor1.setText(des1String);
						descriptor2.setText(des2String);
					}
				});
			}

			if (BleService.ACTION_DATA_AVAILABLE.equals(action)) {
				if (isNotifyHex) {
					result = intent.getExtras()
							.getString(BleService.EXTRA_DATA);
				} else {
					result = intent.getExtras().getString(
							BleService.EXTRA_STRING_DATA);
				}
				int countNumber = intent.getExtras().getInt(
						BleService.EXTRA_DATA_LENGTH);
				if (resultLengthNum != 0) {
					resultLengthNum += countNumber;
				} else {
					resultLengthNum = countNumber;
				}
				if (text_string != null) {
					text_string = text_string + result;
				} else {
					text_string = result;
				}
				resultLength = resultLengthNum + "";
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						// TODO Auto-generated method stub
						notify_resualt.setText(text_string);
						resultcount.setText("�ֽ���� " + resultLength);
					}
				});
			}
			if (BleService.ACTION_GATT_DISCONNECTED.equals(action)) {
				Toast.makeText(ChangeCharActivity.this, "�豸���ӶϿ�",
						Toast.LENGTH_SHORT).show();
				if (sharedPreferences.getBoolean("AutoConnect", true)) {
					bleService.connect(DeviceConnect.bleAddress);
				}
			}
		}
	};

	private IntentFilter makeIntentFilter() {
		// TODO Auto-generated method stub
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(BleService.ACTION_CHAR_READED);
		intentFilter.addAction(BleService.ACTION_GATT_CONNECTED);
		intentFilter.addAction(BleService.ACTION_GATT_DISCONNECTED);
		intentFilter.addAction(BleService.ACTION_GATT_SERVICES_DISCOVERED);
		intentFilter.addAction(BleService.ACTION_DATA_AVAILABLE);
		intentFilter.addAction(BleService.BATTERY_LEVEL_AVAILABLE);
		intentFilter.addAction(BleService.ACTION_GATT_RSSI);
		return intentFilter;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_changechar);
		getActionBar().setTitle("������");
		sharedPreferences = this
				.getSharedPreferences("writedata", MODE_PRIVATE);
		editor = sharedPreferences.edit();
		init();
		bindService(new Intent(this, BleService.class), conn, BIND_AUTO_CREATE);
		registerReceiver(mBroadcastReceiver, makeIntentFilter());
	}

	private void init() {
		// TODO Auto-generated method stub
		descriptor1 = (TextView) findViewById(R.id.tv_descriptor1);
		descriptor2 = (TextView) findViewById(R.id.tv_descriptor2);
		charHex = (TextView) findViewById(R.id.tv_charHex);
		charString = (TextView) findViewById(R.id.tv_charString);
		charformat = (TextView) findViewById(R.id.tv_charformat);
		time = (TextView) findViewById(R.id.tv_time);
		writeButton = (Button) findViewById(R.id.btn_write);
		readButton = (Button) findViewById(R.id.btn_read);
		notifyButton = (Button) findViewById(R.id.btn_notify);
		clear_result = (Button) findViewById(R.id.clear_result);
		save_result = (Button) findViewById(R.id.save_result);
		notify_resualt = (TextView) findViewById(R.id.et_notify_resualt);
		resultcount = (TextView) findViewById(R.id.result_count);
		scroll = (ScrollView) findViewById(R.id.scrollview);
		radioGroup = (RadioGroup) findViewById(R.id.rg_hex_string);
		radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup arg0, int arg1) {
				// TODO Auto-generated method stub
				if (arg1 == R.id.rb_string) {
					if (text_string != null) {
						if (isNotifyHex) {
							text_string = hexStr2Str(text_string);
						}
						notify_resualt.setText(text_string);
					}
					isNotifyHex = false;
				} else {
					if (text_string != null) {
						if (!isNotifyHex) {
							text_string = str2HexStr(text_string);
						}
						notify_resualt.setText(text_string);
					}
					isNotifyHex = true;
				}
			}
		});
		writeButton.setOnClickListener(this);
		readButton.setOnClickListener(this);
		notifyButton.setOnClickListener(this);

		charUuid = UUID.fromString(getIntent().getExtras().get("charUUID")
				.toString());
		serUuid = UUID.fromString(getIntent().getExtras().get("serUUID")
				.toString());
		prop = getIntent().getExtras().getInt("properties");

		if ((prop & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
			writeButton.setVisibility(View.VISIBLE);
		}
		if ((prop & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
			writeButton.setVisibility(View.VISIBLE);
		}
		if ((prop & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
			readButton.setVisibility(View.VISIBLE);
		}
		if ((prop & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
			notifyButton.setVisibility(View.VISIBLE);
			radioGroup.setVisibility(View.VISIBLE);
			scroll.setVisibility(View.VISIBLE);
			resultcount.setVisibility(View.VISIBLE);
			clear_result.setVisibility(View.VISIBLE);
			save_result.setVisibility(View.VISIBLE);
		}
		clear_result.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				text_string = null;
				result = null;
				text_hex = null;
				notify_resualt.setText("");
				resultLengthNum = 0;
				resultcount.setText("�ֽ��:0");
			}
		});
		save_result.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				saveResualt(notify_resualt.getText().toString());
			}
		});
	}

	private void saveResualt(String result) {
		// TODO Auto-generated method stub
		if (result.isEmpty()) {
			Toast.makeText(this, "û�пɱ�������ݣ�", Toast.LENGTH_SHORT).show();
		} else {
			try {
				File file = new File(Environment.getExternalStorageDirectory(),
						"BLElog" + System.currentTimeMillis() + ".txt");
				if (!file.getParentFile().exists()) {
					file.getParentFile().mkdirs();
				}
				if (!file.exists())
					file.createNewFile();
				FileOutputStream out = new FileOutputStream(file);
				OutputStreamWriter writer = new OutputStreamWriter(out);
				writer.write(result);
				writer.flush();
				writer.close();
				out.close();
				Toast.makeText(
						ChangeCharActivity.this,
						"BLElog" + System.currentTimeMillis()
								+ ".txt�ļ��ɹ����浽SD����Ŀ¼��", Toast.LENGTH_SHORT)
						.show();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		unbindService(conn);
		unregisterReceiver(mBroadcastReceiver);
	}

	@SuppressLint("InflateParams")
	public void writeDialog() {
		AlertDialog.Builder dialog = new Builder(this);
		View dialogview = LayoutInflater.from(this).inflate(
				R.layout.writedialog, null);
		final RadioGroup writeGroup = (RadioGroup) dialogview
				.findViewById(R.id.rg_write_format);
		final EditText editText = (EditText) dialogview
				.findViewById(R.id.char_value);
		final Button timing_write = (Button) dialogview
				.findViewById(R.id.btn_timing_write);
		write_time = (EditText) dialogview.findViewById(R.id.ed_writetime);
		final Button btn_0 = (Button) dialogview.findViewById(R.id.btn_00);
		final Button btn_1 = (Button) dialogview.findViewById(R.id.btn_01);
		final Button btn_2 = (Button) dialogview.findViewById(R.id.btn_02);
		final TextView timing_write_count = (TextView) dialogview
				.findViewById(R.id.tv_timing_write_count);
		final RadioButton radio1 = (RadioButton) dialogview
				.findViewById(R.id.rb_write_string);
		final RadioButton radio2 = (RadioButton) dialogview
				.findViewById(R.id.rb_write_hex);
		final EditText editbtn1 = (EditText) dialogview
				.findViewById(R.id.ed_edit_btn1);
		final EditText editbtn2 = (EditText) dialogview
				.findViewById(R.id.ed_edit_btn2);
		final EditText editbtn3 = (EditText) dialogview
				.findViewById(R.id.ed_edit_btn3);

		btn_0.setText(sharedPreferences.getString("btn00" + charUuid, "00"));
		btn_1.setText(sharedPreferences.getString("btn01" + charUuid, "01"));
		btn_2.setText(sharedPreferences.getString("btn02" + charUuid, "02"));
		if (sharedPreferences.getBoolean("isHex", false)) {
			isHex = true;
			radio2.setChecked(true);
			radio1.setChecked(false);
		} else {
			isHex = false;
			radio1.setChecked(true);
			radio2.setChecked(false);
		}

		writeGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup arg0, int arg1) {
				// TODO Auto-generated method stub
				if (arg1 == R.id.rb_write_string) {
					isHex = false;
					editor.putBoolean("isHex", false);
				}
				if (arg1 == R.id.rb_write_hex) {
					isHex = true;
					editor.putBoolean("isHex", true);
				}
				editor.commit();
			}
		});
		editbtn1.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence arg0, int arg1, int arg2,
					int arg3) {
				// TODO Auto-generated method stub
			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
				// TODO Auto-generated method stub
			}

			@Override
			public void afterTextChanged(Editable arg0) {
				// TODO Auto-generated method stub
				checkInputkey(arg0);
				String str = arg0.toString();
				if (arg0.length() > 0) {
					btn_0.setText(str);
				}
				editor.putString("btn00" + charUuid, str);
				editor.commit();
			}
		});
		editText.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// TODO Auto-generated method stub
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// TODO Auto-generated method stub
			}

			@Override
			public void afterTextChanged(Editable s) {
				// TODO Auto-generated method stub
				checkInputkey(s);
			}
		});
		editbtn2.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence arg0, int arg1, int arg2,
					int arg3) {
				// TODO Auto-generated method stub
			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
				// TODO Auto-generated method stub
			}

			@Override
			public void afterTextChanged(Editable arg0) {
				// TODO Auto-generated method stub
				checkInputkey(arg0);
				if (arg0.length() > 0) {
					btn_1.setText(arg0);
				}
				editor.putString("btn01" + charUuid, arg0.toString());
				editor.commit();
			}
		});
		editbtn3.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence arg0, int arg1, int arg2,
					int arg3) {
				// TODO Auto-generated method stub

			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
				// TODO Auto-generated method stub
			}

			@Override
			public void afterTextChanged(Editable arg0) {
				// TODO Auto-generated method stub
				checkInputkey(arg0);
				if (arg0.length() > 0) {
					btn_2.setText(arg0);
				}
				editor.putString("btn02" + charUuid, arg0.toString());
				editor.commit();
			}
		});
		btn_0.setOnClickListener(new OnClickListener() {

			@SuppressLint("NewApi")
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				String transStr = btn_0.getText().toString();
				try {
					if (isHex) {
						gattChar.setValue(str2Byte(transStr));
					} else {
						if (transStr.contains("\n")) {
							transStr = transStr.replace("\n", "\r\n");
						}
						gattChar.setValue(transStr);
					}
					bleService.mBluetoothGatt.writeCharacteristic(gattChar);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		});
		btn_1.setOnClickListener(new OnClickListener() {
			@SuppressLint("NewApi")
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				String transStr = btn_1.getText().toString();
				try {
					if (isHex) {
						gattChar.setValue(str2Byte(transStr));
					} else {
						if (transStr.contains("\n")) {
							transStr = transStr.replace("\n", "\r\n");
						}
						gattChar.setValue(transStr);
					}
					bleService.mBluetoothGatt.writeCharacteristic(gattChar);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		});
		btn_2.setOnClickListener(new OnClickListener() {

			@SuppressLint("NewApi")
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				String transStr = btn_2.getText().toString();
				try {
					if (isHex) {
						gattChar.setValue(str2Byte(transStr));
					} else {
						if (transStr.contains("\n")) {
							transStr = transStr.replace("\n", "\r\n");
						}
						gattChar.setValue(transStr);
					}
					bleService.mBluetoothGatt.writeCharacteristic(gattChar);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
			}
		});
		timing_write.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				period = Integer.parseInt(write_time.getText().toString());
				if (writing) {
					timing_write.setText("��ʱ����");
					writing = false;
				} else {
					timing_write.setText("ֹͣ����");
					write_byte_number = 0;
					writing = true;
				}
				new Thread(new Runnable() {
					@SuppressLint("NewApi")
					public void run() {
						try {
							while (writing) {
								String charvalue = editText.getText()
										.toString();
								if (!charvalue.isEmpty()) {
									if (isHex) {
										write_byte_number += charvalue.length()
												/ 2 + charvalue.length() % 2;
										byte[] str = str2Byte(charvalue);
										gattChar.setValue(str);
									} else {
										write_byte_number += charvalue.length();
										gattChar.setValue(charvalue);
									}
									bleService.mBluetoothGatt
											.writeCharacteristic(gattChar);
									Thread.sleep(period);
									runOnUiThread(new Runnable() {
										@SuppressLint("NewApi")
										@Override
										public void run() {
											// TODO Auto-generated method stub
											timing_write_count.setText("��:"
													+ write_byte_number);
										}
									});
								}
							}
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}).start();
			}
		});
		dialog.setView(dialogview);
		dialog.setPositiveButton("����", new DialogInterface.OnClickListener() {
			@SuppressLint("NewApi")
			@Override
			public void onClick(DialogInterface arg0, int arg1) {
				// TODO Auto-generated method stub
				String charvalue = editText.getText().toString();
				if (!charvalue.isEmpty()) {
					if (isHex) {
						byte[] str = str2Byte(charvalue);
						gattChar.setValue(str);
					} else {
						gattChar.setValue(charvalue);
					}
					bleService.mBluetoothGatt.writeCharacteristic(gattChar);
				}
			}
		});
		dialog.show();
	}

	private void checkInputkey(Editable arg0) {
		if (isHex && arg0.length() > 0) {
			int pos = arg0.length() - 1;
			for (int i = 0; i < arg0.length(); i++) {
				char c = arg0.charAt(i);
				if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
						|| (c >= 'A' && c <= 'F')) {
				} else {
					arg0.delete(pos, pos + 1);
				}
			}
		}
	}

	@SuppressLint("NewApi")
	@Override
	public void onClick(View view) {
		// TODO Auto-generated method stub
		switch (view.getId()) {
		case R.id.btn_read:
			bleService.mBluetoothGatt.readCharacteristic(gattChar);
			break;
		case R.id.btn_write:
			writeDialog();
			break;
		case R.id.btn_notify:
			if (!startNotify) {
				bleService.mBluetoothGatt.setCharacteristicNotification(
						gattChar, true);
				startNotify = true;
				notifyButton.setText("ֹ֪ͣͨ");
			} else {
				bleService.mBluetoothGatt.setCharacteristicNotification(
						gattChar, false);
				startNotify = false;
				notifyButton.setText("��ʼ֪ͨ");
			}
			break;
		}
	}

	public static String str2HexStr(String str) {

		char[] chars = "0123456789ABCDEF".toCharArray();
		StringBuilder sb = new StringBuilder("");
		byte[] bs = str.getBytes();
		int bit;
		for (int i = 0; i < bs.length; i++) {
			bit = (bs[i] & 0x0f0) >> 4;
			sb.append(chars[bit]);
			bit = bs[i] & 0x0f;
			sb.append(chars[bit]);
		}
		return sb.toString().trim();
	}

	public static String hexStr2Str(String hexStr) {
		String str = "0123456789ABCDEF";
		char[] hexs = hexStr.toCharArray();
		byte[] bytes = new byte[hexStr.length() / 2];
		int n;
		for (int i = 0; i < bytes.length; i++) {
			n = str.indexOf(hexs[2 * i]) * 16;
			n += str.indexOf(hexs[2 * i + 1]);
			bytes[i] = (byte) (n & 0xff);
		}
		return new String(bytes);
	}

	public static byte[] str2Byte(String hexStr) {
		int b = hexStr.length() % 2;
		if (b != 0) {
			hexStr = "0" + hexStr;
		}
		String[] a = new String[hexStr.length() / 2];
		byte[] bytes = new byte[hexStr.length() / 2];
		for (int i = 0; i < bytes.length; i++) {
			a[i] = hexStr.substring(2 * i, 2 * i + 2);
		}
		for (int i = 0; i < bytes.length; i++) {
			bytes[i] = (byte) Integer.parseInt(a[i], 16);
		}
		return bytes;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		getMenuInflater().inflate(R.menu.services, menu);
		menu.getItem(1).setVisible(false);
		menu.getItem(0).setTitle(rssi + "");
		return true;
	}

}