package com.xplora.xpsettings.Activity;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;

import com.xplora.xpsettings.Adapter.BluetoothDevicesAdapter;
import com.xplora.xpsettings.Data.BtManager;
import com.xplora.xpsettings.Observer.Listener;
import com.xplora.xpsettings.Model.BluetoothModel;
import com.xplora.xpsettings.R;
import com.xplora.xpsettings.Utils.Constant;
import com.xplora.xpsettings.Utils.ResUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class BluetoothActivity extends BaseActivity implements Listener.BluetoothInitCompleteListener {
    private final List<BluetoothModel> mDataList = new ArrayList<>();
    private BluetoothDevicesAdapter mListAdapter = null;
    private BtManager mBtManager = null;

    static final int OPERATE_DISCONNECT = 10;
    static final int OPERATE_UNPAIRED = 11;
    static final int OPERATE_CONNECT = 12;

    @RequiresApi(api = Build.VERSION_CODES.S)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);

        initView();
        initPermission();
        initBluetooth();
    }

    private void initView() {
        mListAdapter = new BluetoothDevicesAdapter(BluetoothActivity.this, 0, mDataList, handler);
        ListView listView = findViewById(R.id.activity_listview);
        listView.setAdapter(mListAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (position <= 1)
                    return;
                BluetoothModel model = mDataList.get(position);

                if (model.status == BluetoothModel.STATUS.CONNECTED || model.status == BluetoothModel.STATUS.PAIRED) {
                    Intent intent = new Intent(BluetoothActivity.this, ConnectionsControlActivity.class);
                    intent.putExtra("view_type", 0);
                    intent.putExtra("btname", model.title);
                    intent.putExtra("address", model.adress);
                    intent.putExtra("status", model.status.ordinal());
                    startActivityForResult(intent, 112);
                } else {
                    BluetoothDevice device = mBtManager.getRemoteDevice(model.adress);
                    if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
                        mBtManager.connectDevice(BluetoothActivity.this, device);
                    } else if (device.getBondState() == BluetoothDevice.BOND_NONE) {
                        device.createBond();
                    }
                }
            }
        });
    }

    @RequiresApi(api = Build.VERSION_CODES.S)
    private void initPermission() {
        String[] permissions = new String[]{
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN,
                Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_ADVERTISE,
                Manifest.permission.BLUETOOTH_CONNECT,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION,
        };
        ActivityCompat.requestPermissions(this, permissions, 1001);
    }

    private void initBluetooth() {
        mBtManager = new BtManager(this);
        boolean isOn = mBtManager.isEnabled();
        changeBluetoothStatus(isOn);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void initData(boolean isOn) {
        String[] stringList = ResUtils.getStringArray("connections_title_array_", 4);

        BluetoothModel switchModel = new BluetoothModel();
        switchModel.title = stringList[0];
        switchModel.isOn = isOn;
        switchModel.cellType = Constant.CellType.SWITCH;
        mDataList.add(switchModel);

        if (!isOn) return;

        BluetoothModel refreshModel = new BluetoothModel();
        refreshModel.title = getResources().getString(R.string.available_devices);
        refreshModel.cellType = Constant.CellType.REFRESH;
        mDataList.add(refreshModel);

        Set<BluetoothDevice> bondedDevices = mBtManager.getBondedDevices();
        for (BluetoothDevice device : bondedDevices) {
            addDevice(device, BluetoothModel.STATUS.PAIRED);
        }
    }

    private void addDevice(BluetoothDevice device, BluetoothModel.STATUS status) {
        //只显示耳机设备
        if (!mBtManager.isAudioDevice(device))
            return;

        BluetoothModel newModel = new BluetoothModel();
        newModel.title = device.getName();
        if (device.getBondState() == BluetoothDevice.BOND_NONE)
            newModel.status = BluetoothModel.STATUS.NOTPAIRED;
        if (device.getBondState() == BluetoothDevice.BOND_BONDING)
            newModel.status = BluetoothModel.STATUS.PAIRING;
        else if (device.getBondState() == BluetoothDevice.BOND_BONDED)
            newModel.status = BluetoothModel.STATUS.PAIRED;
        newModel.adress = device.getAddress();
        newModel.device = device;
        newModel.cellType = Constant.CellType.ICON_TITLE_SUBTITLE;

        //屏蔽重复
        for (BluetoothModel model:mDataList) {
            if (model.title.equals(newModel.title) && model.adress.equals(newModel.adress)) {
                model.status = newModel.status;
                return;
            }
        }
        mDataList.add(newModel);
    }

    private void changeBluetoothStatus(boolean isOn) {
        mDataList.clear();
        initData(isOn);
        mListAdapter.notifyDataSetChanged();

        if (isOn)
            mBtManager.startScan();
        else
            mBtManager.stopScan();
    }

    private void changeDeviceStatus(BluetoothDevice device, BluetoothModel.STATUS status) {
        Log.d(TAG, "changeDeviceStatus:  getAddress: " + device.getAddress());
        for (BluetoothModel model:mDataList) {
            Log.d(TAG, "changeDeviceStatus:  model.adress: " + model.adress);
            if (model.adress!= null && model.adress.equals(device.getAddress())) {
                model.status = status;
            }
        }
        mListAdapter.notifyDataSetChanged();
    }

    @Override
    public void onBluetoothInitComplete() {
        for (BluetoothModel model : mDataList) {
            if (model.device == null)
                continue;
            if (model.device.getBondState() != BluetoothDevice.BOND_NONE) {
                int status = mBtManager.getConnectionState(model.device);
                if (status == BluetoothProfile.STATE_CONNECTED) {
                    model.status = BluetoothModel.STATUS.CONNECTED;
                }
            }
        }
        mListAdapter.notifyDataSetChanged();
    }

    private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int rssi = intent.getExtras().getShort(BluetoothDevice.EXTRA_RSSI);
                //Log.d("BlueToothTestActivity", "ACTION_FOUND......");
                if (device.getName() != null && device.getName().length() > 0) {
                    addDevice(device, BluetoothModel.STATUS.NOTPAIRED);
                    mListAdapter.notifyDataSetChanged();
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
                if (mListAdapter != null) {
                    mListAdapter.setIsScan(true);
                    mListAdapter.notifyDataSetChanged();
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
                if (mListAdapter != null) {
                    mListAdapter.setIsScan(false);
                    mListAdapter.notifyDataSetChanged();
                }
            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                switch (state) {
                    case BluetoothAdapter.STATE_TURNING_ON:
                        break;
                    case BluetoothAdapter.STATE_ON:
                        changeBluetoothStatus(true);
                        break;
                    case BluetoothAdapter.STATE_TURNING_OFF:
                        break;
                    case BluetoothAdapter.STATE_OFF:
                        changeBluetoothStatus(false);
                        break;
                    default:
                        break;
                }
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING:
                        //Log.d("BlueToothTestActivity", "正在配对......");
                        changeDeviceStatus(device, BluetoothModel.STATUS.PAIRING);
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        //Log.d("BlueToothTestActivity", "完成配对");
                        changeDeviceStatus(device, BluetoothModel.STATUS.CONNECTED);
                        break;
                    case BluetoothDevice.BOND_NONE:
                        //Log.d("BlueToothTestActivity", "取消配对");
                        changeDeviceStatus(device, BluetoothModel.STATUS.NOTPAIRED);
                    default:
                        break;
                }
            } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(intent.getAction())) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int status = device.getBondState();
                if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
                    changeDeviceStatus(device, BluetoothModel.STATUS.CONNECTED);
                }
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction())) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                changeDeviceStatus(device, BluetoothModel.STATUS.PAIRED);
            }
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode != 112 || resultCode != RESULT_OK || data == null)
            return;

        String address = data.getStringExtra("address");
        for (BluetoothModel model:mDataList) {
            Log.d(TAG, "onActivityResult:  model.adress: " + model.adress);
            if (model.adress!= null && model.adress.equals(address)) {
                model.status = BluetoothModel.STATUS.NOTPAIRED;
                int operation = data.getIntExtra("operation", -1);
                if (operation == OPERATE_DISCONNECT) {
                    mBtManager.disConnectDevice(model.device);
                } else if (operation == OPERATE_UNPAIRED) {
                    mBtManager.removeBondDevice(model.device);
                } else if (operation == OPERATE_CONNECT) {
                    mBtManager.connectDevice(BluetoothActivity.this, model.device);
                }
                break;
            }
        }
        mListAdapter.notifyDataSetChanged();
    }

    Handler handler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case Constant.MSG_SWITCH_CHANGE:
                    boolean isOn = (int) msg.obj == 1;
                    if (isOn) {
                        mBtManager.setEnable(true);
                    } else {
                        mBtManager.setEnable(false);
                    }
                    changeBluetoothStatus(isOn);
                    break;
                case Constant.MSG_REFRESH_CLICK:
                    changeBluetoothStatus(true);
                    break;
                default:
                    break;
            }
        }
    };

    private void registerReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        registerReceiver(mBluetoothReceiver, filter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mBluetoothReceiver != null) {
            unregisterReceiver(mBluetoothReceiver);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBtManager.doDestroy();
    }
}

