package com.zhou.android.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.zhou.android.R;
import com.zhou.android.common.Tools;

import java.util.HashMap;
import java.util.Set;

/**
 * Bluetooth 蓝牙列表
 * Created by ZhOu on 2017/6/15.
 */

public class BluetoothListFragment extends Fragment {

    /**
     * 开启蓝牙请求码
     */
    private final static int RequestBluetoothCode = 10001;
    /**
     * 开放搜索请求码
     */
    private final static int RequestBluetoothDiscoverable = 10002;

    private Switch sw_bluetooth, sw_discoverable;
    private LinearLayout ll_match, ll_usable;
    private LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    private int padding = 6;

    private BluetoothAdapter bluetoothAdapter;
    private Handler handler;

    private HashMap<String, BluetoothDevice> matchData = new HashMap<>();
    private HashMap<String, BluetoothDevice> usableData = new HashMap<>();

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_bluetooth_list, container, false);
        initView(view);
        init();
        addListener();
        return view;
    }

    private void initView(View view) {
        sw_bluetooth = (Switch) view.findViewById(R.id.sw_bluetooth);
        sw_discoverable = (Switch) view.findViewById(R.id.sw_discoverable);
        ll_match = (LinearLayout) view.findViewById(R.id.ll_match);
        ll_usable = (LinearLayout) view.findViewById(R.id.ll_use);

        padding = Tools.dip2px(getActivity(), padding);
    }

    private void init() {
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Toast.makeText(getActivity(), "Your device do not support Bluetooth.", Toast.LENGTH_SHORT).show();
            return;
        }
        sw_bluetooth.setChecked(bluetoothAdapter.isEnabled());
        sw_discoverable.setChecked(bluetoothAdapter.getScanMode() == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
        if (!bluetoothAdapter.isEnabled())
            requestBluetoothEnable();
        else {
            loadMatch();
            bluetoothAdapter.startDiscovery();
        }

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        getActivity().registerReceiver(bluetoothReceiver, intentFilter);
    }

    private void addListener() {
        sw_bluetooth.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    requestBluetoothEnable();
                } else {
                    bluetoothAdapter.disable();
                }
            }
        });

        sw_discoverable.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) requestBluetoothDiscoverable();
            }
        });
    }

    private void loadMatch() {
        Set<BluetoothDevice> set = bluetoothAdapter.getBondedDevices();
        if (set.size() == 0)
            return;
        if (ll_match.getVisibility() == View.GONE)
            ll_match.setVisibility(View.VISIBLE);
        if (matchData.size() > set.size()) {
            View title = ll_match.getChildAt(0);
            ll_match.removeAllViews();
            ll_match.addView(title);
        }
        for (BluetoothDevice device : set) {
            String key = device.getAddress();
            if (!matchData.containsKey(key)) {
                matchData.put(key, device);
            }
            View v = ll_match.findViewWithTag(key);
            if (v == null) {
                ll_match.addView(createItem(device));
            }
        }
    }

    private void refreshUsableList() {
        View title = ll_usable.getChildAt(0);
        ll_usable.removeAllViews();
        ll_usable.addView(title);
    }

    private TextView createItem(BluetoothDevice device) {
        String key = device.getAddress();
        TextView tv_item = new TextView(getActivity());
        tv_item.setLayoutParams(params);
        tv_item.setBackgroundResource(R.drawable.bg_white);
        tv_item.setPadding(padding, padding, padding, padding);
        tv_item.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
        tv_item.setTextColor(getActivity().getResources().getColor(R.color.black));
        String value = device.getName();
        if (TextUtils.isEmpty(value))
            value = key;
        tv_item.setText(value);
        tv_item.setTag(key);
        tv_item.setOnClickListener(onClickListener);
        return tv_item;
    }

    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String tag = (String) v.getTag();

            if (onBluetoothClickListener != null) {
                BluetoothDevice device = null;
                if (matchData.containsKey(tag))
                    device = matchData.get(tag);
                else if (usableData.containsKey(tag))
                    device = usableData.get(tag);
                onBluetoothClickListener.onBluetoothClick(device);
            }
        }
    };

    private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {

                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                if (state == BluetoothAdapter.STATE_OFF) {
                    sw_bluetooth.setChecked(false);
                    matchData.clear();
                    usableData.clear();
                    ll_match.setVisibility(View.GONE);
                    ll_usable.setVisibility(View.GONE);

                } else if (state == BluetoothAdapter.STATE_ON) {
                    sw_bluetooth.setChecked(true);
                    loadMatch();
                    if (ll_usable.getVisibility() == View.GONE)
                        ll_usable.setVisibility(View.VISIBLE);
                    refreshUsableList();
                    bluetoothAdapter.startDiscovery();
                }
            } else if (action.equals(BluetoothDevice.ACTION_FOUND)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                usableData.put(device.getAddress(), device);
                ll_usable.addView(createItem(device));
            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
                usableData.clear();
                if (handler != null) {
                    handler.obtainMessage(MessageType.MESSAGE_REFRESH_STARTED).sendToTarget();
                }
            } else if (action.equals(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)) {
                int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, 0);
                if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                    sw_discoverable.setChecked(true);
                } else {
                    sw_discoverable.setChecked(false);
                }
            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                if (handler != null) {
                    handler.obtainMessage(MessageType.MESSAGE_REFRESH_FINISHED).sendToTarget();
                }
            }
        }
    };

    /**
     * 蓝牙是否可用
     */
    private void requestBluetoothEnable() {
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(intent, RequestBluetoothCode);
    }

    /**
     * 蓝牙开放搜索
     */
    private void requestBluetoothDiscoverable() {
        if (bluetoothAdapter.getScanMode() !=
                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivityForResult(intent, RequestBluetoothDiscoverable);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (RequestBluetoothCode == requestCode) {
            if (bluetoothAdapter.isDiscovering())
                bluetoothAdapter.cancelDiscovery();
            bluetoothAdapter.startDiscovery();
            sw_bluetooth.setChecked(-1 == resultCode);
            if (-1 != resultCode) {
                Toast.makeText(getActivity(), "Open Bluetooth is failed,please open in Setting.",
                        Toast.LENGTH_SHORT).show();
            }
        } else if (RequestBluetoothDiscoverable == requestCode) {
            sw_discoverable.setChecked(300 == resultCode);
        }
    }

    public void refresh(Handler handler) {
        this.handler = handler;
        bluetoothAdapter.startDiscovery();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        getActivity().unregisterReceiver(bluetoothReceiver);
    }

    private OnBluetoothClickListener onBluetoothClickListener = null;

    public void setOnBluetoothClickListener(OnBluetoothClickListener onBluetoothClickListener) {
        this.onBluetoothClickListener = onBluetoothClickListener;
    }

    public interface OnBluetoothClickListener {
        void onBluetoothClick(BluetoothDevice device);
    }
}