package com.wandersnail.bledemo;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import org.jetbrains.annotations.NotNull;

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

import cn.wandersnail.ble.Device;
import cn.wandersnail.ble.EasyBLE;
import cn.wandersnail.ble.callback.ScanListener;
import cn.wandersnail.commons.helper.PermissionsRequester;
import cn.wandersnail.commons.util.ToastUtils;
import cn.wandersnail.widget.listview.BaseListAdapter;
import cn.wandersnail.widget.listview.BaseViewHolder;
import cn.wandersnail.widget.listview.PullRefreshLayout;

/**
 * date: 2019/8/4 15:13
 * author: zengfansheng
 */
public class ScanActivity extends AppCompatActivity {
    private ListAdapter listAdapter;
    private PullRefreshLayout refreshLayout;
    private LinearLayout layoutEmpty;
    private List<Device> devList = new ArrayList<>();
    private PermissionsRequester permissionsRequester;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan);
        initViews();
        EasyBLE.getInstance().addScanListener(scanListener);        
        initialize();
    }

    private void initViews() {
        refreshLayout = findViewById(R.id.refreshLayout);
        ListView lv = findViewById(R.id.lv);
        layoutEmpty = findViewById(R.id.layoutEmpty);
        refreshLayout.setColorSchemeColors(ContextCompat.getColor(this, R.color.colorAccent));
        listAdapter = new ListAdapter(this, devList);
        lv.setAdapter(listAdapter);
        lv.setOnItemClickListener((parent, view, position, id) -> {
            Intent intent = new Intent(ScanActivity.this, MainActivity.class);
            intent.putExtra("device", devList.get(position));
            startActivity(intent);
        });
        refreshLayout.setOnRefreshListener(() -> {
            if (EasyBLE.getInstance().isInitialized()) {
                EasyBLE.getInstance().stopScan();
                doStartScan();
            }
            refreshLayout.postDelayed(() -> refreshLayout.setRefreshing(false), 500);
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();        
        EasyBLE.getInstance().release();
        System.exit(0);
    }

    private ScanListener scanListener = new ScanListener() {
        @Override
        public void onScanStart() {
            invalidateOptionsMenu();
        }

        @Override
        public void onScanStop() {
            invalidateOptionsMenu();
        }

        @Override
        public void onScanResult(@NonNull Device device, boolean isConnectedBySys) {
            layoutEmpty.setVisibility(View.INVISIBLE);
            listAdapter.add(device);
        }

        @Override
        public void onScanError(int errorCode, @NotNull String errorMsg) {
            switch(errorCode) {
                case ScanListener.ERROR_LACK_LOCATION_PERMISSION://缺少定位权限		
            		break;
                case ScanListener.ERROR_LOCATION_SERVICE_CLOSED://位置服务未开启		
            		break;
                case ScanListener.ERROR_SCAN_FAILED://搜索失败
                    ToastUtils.showShort("搜索出错:" + errorCode);
                    break;
            }
        }
    };
    
    //需要进行检测的权限
    private List<String> getNeedPermissions() {
        List<String> list = new ArrayList<>();
        if (getApplicationInfo().targetSdkVersion >= 29) {//target sdk版本在29以上的需要精确定位权限才能搜索到蓝牙设备
            list.add(Manifest.permission.ACCESS_FINE_LOCATION);
        } else {
            list.add(Manifest.permission.ACCESS_COARSE_LOCATION);            
        }
        return list;
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("Main", "onResume");
        if (EasyBLE.getInstance().isInitialized()) {
            if (EasyBLE.getInstance().isBluetoothOn()) {
                doStartScan();
            } else {
                startActivity(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (EasyBLE.getInstance().isInitialized()) {
            EasyBLE.getInstance().stopScan();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.scan, menu);
        MenuItem item = menu.findItem(R.id.menuProgress);
        item.setActionView(R.layout.toolbar_indeterminate_progress);
        item.setVisible(EasyBLE.getInstance().isScanning());
        return super.onCreateOptionsMenu(menu);
    }

    private void initialize() {
        //动态申请权限
        permissionsRequester = new PermissionsRequester(this);
        permissionsRequester.setCallback(list -> {
            
        });
        permissionsRequester.checkAndRequest(getNeedPermissions());
    }

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

    private void doStartScan() {
        listAdapter.clear();
        layoutEmpty.setVisibility(View.VISIBLE);
        EasyBLE.getInstance().stopScanQuietly();
        EasyBLE.getInstance().startScan();
    }

    private class ListAdapter extends BaseListAdapter<Device> {
        private HashMap<String, Long> updateTimeMap = new HashMap<>();
        private HashMap<String, TextView> rssiViews = new HashMap<>();

        ListAdapter(@NotNull Context context, @NotNull List<Device> list) {
            super(context, list);
        }

        @NotNull
        @Override
        protected BaseViewHolder<Device> createViewHolder(int i) {
            return new BaseViewHolder<Device>() {
                TextView tvName;
                TextView tvAddr;
                TextView tvRssi;

                @Override
                public void onBind(Device device, int i) {
                    rssiViews.put(device.getAddress(), tvRssi);
                    tvName.setText(device.getName().isEmpty() ? "N/A" : device.getName());
                    tvAddr.setText(device.getAddress());
                    tvRssi.setText("" + device.getRssi());
                }

                @NotNull
                @Override
                public View createView() {
                    View view = View.inflate(context, R.layout.item_scan, null);
                    tvName = view.findViewById(R.id.tvName);
                    tvAddr = view.findViewById(R.id.tvAddr);
                    tvRssi = view.findViewById(R.id.tvRssi);
                    return view;
                }
            };
        }

        void clear() {
            getItems().clear();
            notifyDataSetChanged();
        }

        void add(Device device) {
            Device dev = null;
            for (Device item : getItems()) {
                if (item.equals(device)) {
                    dev = item;
                    break;
                }
            }
            if (dev == null) {
                updateTimeMap.put(device.getAddress(), System.currentTimeMillis());
                getItems().add(device);
                notifyDataSetChanged();
            } else {
                Long time = updateTimeMap.get(device.getAddress());
                if (time == null || System.currentTimeMillis() - time > 2000) {
                    updateTimeMap.put(device.getAddress(), System.currentTimeMillis());
                    if (dev.getRssi() != device.getRssi()) {
                        dev.setRssi(device.getRssi());
                        final TextView tvRssi = rssiViews.get(device.getAddress());
                        if (tvRssi != null) {
                            tvRssi.setText("" + device.getRssi());
                            tvRssi.setTextColor(Color.BLACK);
                            tvRssi.postDelayed(() -> tvRssi.setTextColor(0xFF909090), 800);
                        }
                    }
                }
            }
        }
    }
}