package com.doorknocker.bluetooth;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;

import com.doorknocker.Constant;
import com.doorknocker.model.DoorItem;

public class BLEService extends Service {

	public static final String SERVERSBROADCASTINF = "com.mt.service_inf";
	public static final String SERVERSBROADCASTINF_KEY = "key";
	private int currentVersion;

	/**
	 * 开门的距离，正式上线之后要从配置文件中获取
	 */
	private int openDistance = -75;

	@Override
	public void onCreate() {
		super.onCreate();
		System.out.println("onCreate BLEService");

		// mHandler.sendEmptyMessage(REFLASH_PROTECT_SERVICE);

		if (!initBle()) {
			return;
		}
		
		/**
		 * 如果安卓版本低于4.3就不要往下执行了。
		 */
		currentVersion = android.os.Build.VERSION.SDK_INT;
		if (Constant.MIN_OS_VERSION > currentVersion) {
			return;
		}
		
		// 默认开门距离
		SharedPreferences preferences = getSharedPreferences(Constant.NAME_CONFIG, Context.MODE_PRIVATE);
		openDistance = preferences.getInt(Constant.KEY_DOOR_DISTANCE_DEFAULT, -75);

		initBroadcastReceiver();
		getDoorInfFromDB();

		scanBle();

		acquireWakeLock();
	}

	// 申请电源锁，禁止休眠
	private WakeLock mWakeLock = null;

	private void acquireWakeLock() {
		if (null == mWakeLock) {
			PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
			mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this
					.getClass().getCanonicalName());
			if (null != mWakeLock) {
				mWakeLock.acquire();
			}
		}
	}

	// 释放设备电源锁
	private void releaseWakeLock() {
		if (null != mWakeLock) {
			mWakeLock.release();
			mWakeLock = null;
		}
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {

		System.out.println("onStartCommand1");

		return START_STICKY;
	}

	// 获取门列表
	private DBAdapter db;
	private SharedPreferences prefs;
	private Map<String, DoorItem> doormap = new HashMap<String, DoorItem>();

	private void getDoorInfFromDB() {
		db = new DBAdapter(getApplicationContext());

		// 查看是否有权限
		SharedPreferences preferences = getSharedPreferences(
				Constant.NAME_CONFIG, Context.MODE_PRIVATE);
		boolean hasPermission = preferences.getBoolean(
				Constant.HAS_DOOR_PERMITION, false);
		if (!hasPermission) {
			return;
		}

		// 获取列表
		db.open();
		doormap = db.getAllClockListMap();
		if (doormap == null) {
			System.out.println("has no doors");
		}

		db.close();
	}

	public BluetoothManager mBluetoothManager;
	public BluetoothAdapter mBluetoothAdapter;
	//private BluetoothLeScanner scanner;
	public BluetoothGatt mBluetoothGatt;
	private List<MTBeacon> scan_devices = new ArrayList<MTBeacon>();

	// 初始化BLE
	@SuppressLint("NewApi")
	private boolean initBle() {
		System.out.println("initBle");
		mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

		if (null == mBluetoothManager) {
			System.out.println("获取 mBluetoothManager失败");
			return false;
		}

		mBluetoothAdapter = mBluetoothManager.getAdapter();
		if (null == mBluetoothAdapter) {
			System.out.println("获取 mBluetoothAdapter失败");
			return false;
		}
		//scanner = mBluetoothAdapter.getBluetoothLeScanner();

		return true;
	}

	// 扫描设备
	private Handler search_timer = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);

			new OpenDoorThread().start();

		}
	};
	
	@SuppressLint("NewApi")
	private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

		@Override
		public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
			int i = 0;
			MTBeacon beacon_tmp = new MTBeacon(device, rssi, scanRecord);

			// 是否为ibeacon
			if (!beacon_tmp.isIsClock()) {
				return;
			}
			
			for (i = 0; i < scan_devices.size(); i++) {
				if (0 == device.getAddress().compareTo(
						scan_devices.get(i).GetDevice().getAddress())) {
					scan_devices.get(i).ReflashInf(device, rssi, scanRecord); // 更新信息
					return;
				}
			}

			// 如果没有，就添加
			scan_devices.add(beacon_tmp);
		}
	};
	
	//扫描回调
	/*@SuppressLint("NewApi")
	private ScanCallback mScanCallback = new ScanCallback() {
		public void onBatchScanResults(List<ScanResult> results) {
			
			for (int index = 0, size = results.size(); index < size; index++) {
				ScanResult result = results.get(index);
				MTBeacon beacon_tmp = new MTBeacon(result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());
				// 是否为ibeacon
				if (!beacon_tmp.isIsClock()) {
					return;
				}
				
				if (0 == result.getDevice().getAddress().compareTo(
						scan_devices.get(index).GetDevice().getAddress())) {
					scan_devices.get(index).ReflashInf(result.getDevice(), result.getRssi(), result.getScanRecord().getBytes()); // 更新信息
					return;
				}
				
				// 如果没有，就添加
				scan_devices.add(beacon_tmp);
			}
		};
	};*/

	private void scanBle() {
		search_timer.sendEmptyMessage(0);
	}

	// 开门操作
	private boolean connect_flag = false;
	private boolean notification_flag = false;
	private boolean openclock_flag = false;
	private boolean scan_flag = false; // 是否正在扫描
	private boolean has_permition_clock_flag = false;

	private boolean timeout_flag = false; // 超时标志
	private final int REFLASH_PROTECT_SERVICE = 1;
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == 0) {
				timeout_flag = true;
				return;
			}
			if (msg.what == REFLASH_PROTECT_SERVICE) {
				Intent intent = new Intent(getApplicationContext(),
						ProtectService.class);
				startService(intent);
				mHandler.sendEmptyMessageDelayed(REFLASH_PROTECT_SERVICE, 10000);
				return;
			}
		};
	};

	@SuppressLint("NewApi")
	private class OpenDoorThread extends Thread {
		@Override
		public void run() {
			super.run();
			try {

				if (!mBluetoothAdapter.isEnabled()) {
					search_timer.sendEmptyMessageDelayed(0, 1000);
					scan_flag = true;
					return;
				}

				if (scan_flag) {
					// System.out.println("停止扫描");
					LogText.writeStr("      设备数量->" + scan_devices.size());
					Log.i("bluetooth", "设备数量==================================" + scan_devices.size());
					mBluetoothAdapter.stopLeScan(mLeScanCallback);
					//scanner.stopScan(mScanCallback);

					for (MTBeacon mtbeacon : scan_devices) {
						// System.out.println("getClockID-->"
						// + mtbeacon.getClockID());
						DoorItem clock = doormap.get(mtbeacon.getClockID());
						System.out.println("ID->" + mtbeacon.getClockID());
						if (clock == null) { // 判断此锁是否存在于权限中
							LogText.writeStr("没有权限->" + mtbeacon.getClockID());
							Log.i("bluetooth", "没有权限===================================");
							continue;
						}
						has_permition_clock_flag = true;

						if (mtbeacon.GetAveragerssi() < openDistance) { // 判断距离
							LogText.writeStr("距离太远->"
									+ mtbeacon.GetAveragerssi());
							Log.i("bluetooth", "距离太远===================================");
							continue;
						}

						if ((System.currentTimeMillis() - clock
								.getLast_open_time()) < 10000) { // 判断距离上次开锁多久了
							LogText.writeStr("距离上次开锁还不到10s");
							Log.i("bluetooth", "距离上次开锁还不到10s===================================");
							continue;
						}

						if (!connectBLETimeout(mtbeacon, 5000)) {
							LogText.writeStr("   连接超时");
							disConectBle();
							Log.i("bluetooth", "连接超时===================================");
							continue;
						}
						if (getService()) { // 获取通道
							if (!setNotifiTimeout(500)) {
								LogText.writeStr("   设置通知超时");
								disConectBle();
								Log.i("bluetooth", "设置通知超时===================================");
								continue;
							}

							// 密码验证
							if (!writeData(cmdCharacteristic,
									"AT+PWD[" + clock.getPassword() + "]", 500)) {
								LogText.writeStr("   密码验证超时");
								disConectBle();
								Log.i("bluetooth", "密码验证超时===================================");
								continue;
							}

							if (!recive_msg.equals("You Are User\r\n")) {
								LogText.writeStr("   密码配对错误");
								Log.i("bluetooth", "密码配对错误===================================");
								continue;
							}

							// 开门命令
							// writeData(cmdCharacteristic, "AT+SOPEN", 500);
							if (!writeData(cmdCharacteristic, "AT+SOPEN", 500)) {
								LogText.writeStr("   开门超时");
								disConectBle();
								Log.i("bluetooth", "开门超时===================================");
								continue;
							}
							if (!recive_msg.equals("OK+SOPEN\r\n")) {
								LogText.writeStr("   开门失败");
								Log.i("bluetooth", "开门失败===================================");
								continue;
							}

							broadcastUpdate(SERVERSBROADCASTINF, "开锁成功");
							LogText.writeStr("开锁成功");
							Log.i("bluetooth", "开锁成功===================================");
							clock.setLast_open_time(System.currentTimeMillis()); // 设置这次开锁时间
						}
						disConectBle();
						sleep(500);
					}
					scan_devices.clear();
					if (has_permition_clock_flag) {
						// search_timer.sendEmptyMessage(0);
						search_timer.sendEmptyMessageDelayed(0, 100);
					} else {
						search_timer.sendEmptyMessageDelayed(0, 5000);
					}
					has_permition_clock_flag = false;
					scan_flag = false; // 设置为没有扫描状态
				} else {
					broadcastUpdate(SERVERSBROADCASTINF, "开始扫描");
					LogText.writeStr("      开始扫描");
					Log.i("bluetooth", "开始扫描===================================");
					mBluetoothAdapter.startLeScan(mLeScanCallback);
					//scanner.startScan(mScanCallback);
					search_timer.sendEmptyMessageDelayed(0, 900); // 扫描1s
					scan_flag = true; // 设置为真正扫描状态
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		// 连接超时判断函数
		private boolean connectBLETimeout(MTBeacon mtbeacon, int millsec) {
			timeout_flag = false;
			connect_flag = false;

			if (!mBluetoothAdapter.isEnabled()) {
				return false;
			}

			conectBle(mtbeacon.GetDevice()); // 连接设备

			mHandler.sendEmptyMessageDelayed(0, millsec);
			while (!connect_flag) {
				if (timeout_flag) {
					return false;
				}
			}
			mHandler.removeMessages(0);
			return true;
		}

		// 设置可通知超时判断函数
		private boolean setNotifiTimeout(int millsec) {
			timeout_flag = false;
			notification_flag = false;

			mBluetoothGatt.setCharacteristicNotification(cmdCharacteristic, true);
			return true;
		}

		// 写数据超时判断
		private boolean writeData(BluetoothGattCharacteristic cmdChara,
				String data, int millsec) {
			timeout_flag = false;
			openclock_flag = false;

			if (!mBluetoothAdapter.isEnabled()) {
				return false;
			}

			cmdChara.setValue(data);
			mBluetoothGatt.writeCharacteristic(cmdChara);

			try {
				sleep(millsec);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (!openclock_flag) {
				return false;
			}

			return true;
		}
	}

	//
	private String recive_msg;
	private BluetoothGattCharacteristic cmdCharacteristic;
	@SuppressLint("NewApi")
	private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,
				int newState) {
			super.onConnectionStateChange(gatt, status, newState);
			if (newState == BluetoothProfile.STATE_CONNECTED) {
				System.out.println("CONNECTED");
				mBluetoothGatt.discoverServices();
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				System.out.println("UNCONNECTED");
				connect_flag = false;
			}
		}

		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			super.onServicesDiscovered(gatt, status);
			if (status == BluetoothGatt.GATT_SUCCESS) {
				System.out.println("onServicesDiscovered");
				connect_flag = true;
			} else {
				System.out.println("onServicesDiscovered fail-->" + status);
			}
		}

		@Override
		public void onDescriptorRead(BluetoothGatt gatt,
				BluetoothGattDescriptor descriptor, int status) {
			super.onDescriptorRead(gatt, descriptor, status);
		}

		@Override
		public void onCharacteristicRead(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic, int status) {
			super.onCharacteristicRead(gatt, characteristic, status);

			if (status == BluetoothGatt.GATT_SUCCESS) {
			}
		}

		@Override
		public void onCharacteristicChanged(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic) {
			super.onCharacteristicChanged(gatt, characteristic);
			recive_msg = characteristic.getStringValue(0);
			openclock_flag = true;
			System.out.println("read->" + characteristic.getStringValue(0));
		}

		@Override
		public void onCharacteristicWrite(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				System.out.println("write OK");
			} else {
				System.out.println("write fail");
			}

			super.onCharacteristicWrite(gatt, characteristic, status);
		}

		@Override
		public void onDescriptorWrite(BluetoothGatt gatt,
				BluetoothGattDescriptor descriptor, int status) {
			super.onDescriptorWrite(gatt, descriptor, status);
			notification_flag = true;
		}

	};

	@SuppressLint("NewApi")
	private boolean conectBle(BluetoothDevice mBluetoothDevice) {
		disConectBle();

		BluetoothDevice device_tmp = mBluetoothAdapter
				.getRemoteDevice(mBluetoothDevice.getAddress());
		if (device_tmp == null) {
			System.out.println("device == null");
			return false;
		}

		mBluetoothGatt = device_tmp.connectGatt(getApplicationContext(), false,
				mGattCallback);
		return true;
	}

	// 获取通道号
	@SuppressLint("NewApi")
	private boolean getService() {
		for (BluetoothGattService service : mBluetoothGatt.getServices()) {
			// System.out.println("service_uuid->"+service.getUuid().toString().toUpperCase());
			if (service.getUuid().toString().toUpperCase()
					.equals(MTBeaconUUID.SERVICE_UUID)) {
				for (BluetoothGattCharacteristic gattCharacteristic : service
						.getCharacteristics()) {
					if (gattCharacteristic.getUuid().toString().toUpperCase()
							.equals(MTBeaconUUID.CMD_UUID)) {
						cmdCharacteristic = gattCharacteristic;
						return true;
					}
				}
			}
		}
		return false;
	}

	// 断开连接
	@SuppressLint("NewApi")
	private void disConectBle() {

		if (!mBluetoothAdapter.isEnabled()) {
			return;
		}

		if (mBluetoothGatt != null) {
			mBluetoothGatt.disconnect();
			mBluetoothGatt.close();
			mBluetoothGatt = null;
		}
		connect_flag = false;
	}

	// 发送广播消息
	private void broadcastUpdate(final String action, String value) {
		final Intent intent = new Intent(action);
		intent.putExtra(SERVERSBROADCASTINF_KEY, value);
		sendBroadcast(intent);
	}

	// 初始化广播接收器
	private MyBroadcastReceiver receviver = null;

	private void initBroadcastReceiver() {
		// 创建一个IntentFilter对象，将其action指定为BluetoothDevice.ACTION_FOUND
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(Constant.RELOAD_DATA);
		intentFilter.addAction(Constant.RELOAD_OPEN_DOORS_DISTANCE);
		receviver = new MyBroadcastReceiver();
		// 注册广播接收器
		registerReceiver(receviver, intentFilter);
	}

	private class MyBroadcastReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (action.equals(Constant.RELOAD_DATA)) {
				// 重新加载数据库
				System.out.println("get RELOAD_DATA");
				getDoorInfFromDB();
				return;
			} else if (action.equals(Constant.RELOAD_OPEN_DOORS_DISTANCE)) {
				// 这里得到实际距离，要将实际距离进行转化
				/**
				 * 0========-5
				 * 10=======-85
				 */
				openDistance = getSharedPreferences(Constant.NAME_CONFIG, Context.MODE_PRIVATE).getInt(Constant.KEY_DOOR_DISTANCE, -85);
				if (openDistance > -50) {
					openDistance = -50;
				}
				return;
			} else if (action.equals(Constant.RELOAD_OPEN_DOORS_DISTANCE_DEF)) {
				SharedPreferences preferences = getSharedPreferences(Constant.NAME_CONFIG, Context.MODE_PRIVATE);
				openDistance = preferences.getInt(Constant.KEY_DOOR_DISTANCE_DEFAULT, -75);
				return;
			}
		}
	}

	@Override
	public void onDestroy() {
		LogText.writeStr(" onDestroy");
		super.onDestroy();

		if (receviver != null) {
			unregisterReceiver(receviver);
		}
		// if (receiver != null)
		// unregisterReceiver(receiver);
		// releaseWakeLock();
		releaseWakeLock();
		stopForeground(true);
	}

	public class LocalBinder extends Binder {
		public BLEService getService() {
			return BLEService.this;
		}
	}

	private final IBinder mBinder = new LocalBinder();

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}
}
