package hf.lskj.com.carstockcount.fragment;


import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.widget.AppCompatSpinner;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.google.gson.Gson;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import butterknife.Bind;
import butterknife.ButterKnife;
import hf.lskj.com.carstockcount.MyApplication;
import hf.lskj.com.carstockcount.R;
import hf.lskj.com.carstockcount.RequestUtils;
import hf.lskj.com.carstockcount.activity.CarListActivity;
import hf.lskj.com.carstockcount.db.MyDao;
import hf.lskj.com.carstockcount.db.CarInfo;
import hf.lskj.com.carstockcount.db.CarInfoDao;
import hf.lskj.com.carstockcount.db.Record;
import hf.lskj.com.carstockcount.event.BindEvent;
import hf.lskj.com.carstockcount.utils.DateUtils;
import hf.lskj.com.carstockcount.utils.LogUtils;
import hf.lskj.com.carstockcount.utils.ToastUtils;
import hf.lskj.com.carstockcount.utils.UHF.UHFClient;
import hf.lskj.com.carstockcount.utils.UHF.UHFUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.ResponseBody;
import uhf.api.CommandType;
import uhf.api.MultiLableCallBack;
import uhf.api.Multi_query_epc;
import uhf.api.ShareData;

import static hf.lskj.com.carstockcount.db.CarInfo.STATUS_MOVE;
import static hf.lskj.com.carstockcount.db.CarInfo.STATUS_WEIPANDAO;


public class StockCountFragment extends BaseFragment implements MultiLableCallBack, OnKeyDownInterface {
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    @Bind(R.id.tv_vin)
    TextView tvVin;
    @Bind(R.id.tv_rfid)
    TextView tvRfid;
    @Bind(R.id.tv_type)
    TextView tvType;
    @Bind(R.id.tv_color)
    TextView tvColor;
    @Bind(R.id.tv_status)
    TextView tvStatus;
    @Bind(R.id.spi_status)
    AppCompatSpinner spiStatus;
    @Bind(R.id.tv_time)
    TextView tvTime;
    @Bind(R.id.bt_scan)
    ToggleButton btScan;
    @Bind(R.id.bt_save)
    Button btSave;
    @Bind(R.id.tv_time_title)
    TextView tvTimeTitle;
    private CarInfo mCarInfo;
    private Record mRecord;
    private String[] statuses = new String[]{"移动", "未盘到"};
    private Set<String> tags = new HashSet<>();

    private final MyApplication.MyHandler mHandler = new MyApplication.MyHandler();
    private boolean stopped = true;
    private CarInfoDao mCarInfoDao;

    public StockCountFragment() {
    }

    public static StockCountFragment newInstance(CarInfo param1) {
        StockCountFragment fragment = new StockCountFragment();
        Bundle args = new Bundle();
        args.putSerializable(ARG_PARAM1, param1);
        fragment.setArguments(args);
        return fragment;
    }

    public static StockCountFragment newInstance(Record param1) {
        StockCountFragment fragment = new StockCountFragment();
        Bundle args = new Bundle();
        args.putSerializable(ARG_PARAM2, param1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mCarInfo = (CarInfo) getArguments().getSerializable(ARG_PARAM1);
            mRecord = (Record) getArguments().getSerializable(ARG_PARAM2);
        }
        mCarInfoDao = MyApplication.getInstances().getDaoSession().getCarInfoDao();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_stock_count, container, false);
        ButterKnife.bind(this, rootView);
        bindData();
        initListener();
        EventBus.getDefault().register(this);
        return rootView;
    }

    /**
     * 用于异常处理
     **/
    public void setCarInfo(CarInfo carInfo) {
        mCarInfo = carInfo;
        mRecord = null;
        bindData();
    }

    /**
     * 用于查看盘点几率
     **/
    public void setCountRecord(Record record) {
        mRecord = record;
        mCarInfo = null;
        bindData();
    }

    private void queryTags() {

        Multi_query_epc mMulti_query_epc = new Multi_query_epc();
        mMulti_query_epc.query_total = 0;

        UHFClient info = UHFClient.getInstance();
        if (info != null) {
            UHFClient.mUHF.setCallBack(StockCountFragment.this);
            UHFClient.mUHF.command(CommandType.MULTI_QUERY_TAGS_EPC, mMulti_query_epc);
            stopped = false;
        }
    }

    private void bindData() {
        if (mCarInfo != null) {
            //不再提供手动盘点 改为查看车辆详情
            tvVin.setText(mCarInfo.getVin());
            tvRfid.setText(mCarInfo.getRfid());
            tvColor.setText(mCarInfo.getColor());
            tvType.setText(mCarInfo.getType());
            tvTime.setVisibility(View.GONE);
            tvTimeTitle.setVisibility(View.GONE);
            spiStatus.setVisibility(View.GONE);
            spiStatus.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, statuses));
            tvStatus.setVisibility(View.VISIBLE);
            tvStatus.setText(mCarInfo.getStatus());
            switch (mCarInfo.getStatus()) {
                case STATUS_MOVE:
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_move));
                    break;
                case STATUS_WEIPANDAO:
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_out));
                    break;
                default:
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_in));
                    break;
            }
            btScan.setVisibility(View.GONE);
            btSave.setVisibility(View.GONE);
        } else if (mRecord != null) {
            //查看盘点记录
            tvVin.setText(mRecord.getVin());
            tvRfid.setText(mRecord.getRfid());
            tvType.setText(mRecord.getType());
            tvColor.setText(mRecord.getColor());
            tvStatus.setText(mRecord.getStatus());
            switch (mRecord.getStatus()) {
                case STATUS_MOVE:
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_move));
                    break;
                case STATUS_WEIPANDAO:
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_out));
                    break;
                default:
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_in));
                    break;
            }
            tvTimeTitle.setVisibility(View.VISIBLE);
            tvTime.setVisibility(View.VISIBLE);
            tvTime.setText(DateUtils.format(mRecord.getCreateTime()));
            switch (mRecord.getType()) {
                case Record.TYPE_BANGDING:
                    tvTimeTitle.setText("绑定时间:");
                    break;
                case Record.TYPE_JIEBANG:
                    tvTimeTitle.setText("解绑时间:");
                    break;
                default:
                    tvTimeTitle.setText("盘点时间:");
                    break;
            }
            spiStatus.setVisibility(View.GONE);
            btScan.setVisibility(View.GONE);
            btSave.setVisibility(View.GONE);
        } else {
            tvStatus.setVisibility(View.VISIBLE);
            spiStatus.setVisibility(View.GONE);
            btScan.setVisibility(View.VISIBLE);
            btSave.setVisibility(View.GONE);
            tvTimeTitle.setVisibility(View.VISIBLE);
            tvTime.setVisibility(View.VISIBLE);
            tvVin.setText("");
            tvRfid.setText("");
            tvType.setText("");
            tvColor.setText("");
            tvStatus.setText("");
            tvTime.setText("");
        }

    }

    private void initListener() {
        spiStatus.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                tvStatus.setText(statuses[i]);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
        btSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                save(mCarInfo, true);
            }
        });
        btScan.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    queryTags();
                } else {
                    stopQueryTags();
                }
            }
        });
    }

    private void save(final CarInfo carInfo, boolean manual) {
        final String tag = tvRfid.getText().toString();
        final Record entity = new Record();
        entity.setRfid(tag);
        entity.setVin(tvVin.getText().toString());
        entity.setStatus(tvStatus.getText().toString());
        entity.setRemark("");
        entity.setCreateTime(System.currentTimeMillis() + "");
        entity.setOperatorId(MyApplication.currentUser.getLoginId());
        entity.setStoreId(carInfo.getStoreId());
        entity.setColor(carInfo.getColor());
        entity.setCarType(carInfo.getType());
        entity.setType(Record.TYPE_PANDIAN);
        //todo 检查网络是否可用
        boolean networkAvailable = false;
        if (networkAvailable) {
            RequestUtils.post("", new Gson().toJson(entity), new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try (ResponseBody responseBody = response.body()) {
                        if (!response.isSuccessful()) {
                            throw new IOException("网络请求错误");
                        } else {
                            System.out.println(responseBody.string());
                            boolean success = MyDao.saveToDb(getActivity(),carInfo, entity);
                            Toast.makeText(getActivity(), success ? "vin:" + entity.getVin() + "盘点成功" : "盘点失败:数据保存失败", Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });
        } else {
            boolean success = MyDao.saveToDb(getActivity(),carInfo, entity);
            Toast.makeText(getActivity(), success ? "vin:" + entity.getVin() + "盘点成功" : "盘点失败:数据保存失败", Toast.LENGTH_SHORT).show();
            Log.i("StockCount", entity.getId() + "");
        }
        if (manual) {
            startActivity(new Intent(getActivity(), CarListActivity.class));
        }
    }



    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
        EventBus.getDefault().unregister(this);
        if (handlerThread != null) {
            handlerThread.quit();
            handlerThread.interrupt();
        }
        handlerThread = null;
    }

    @Override
    protected void onInvisible() {
        super.onInvisible();
        if (btScan != null) {
            btScan.setChecked(false);
        }
    }

    private void stopQueryTags() {
        UHFClient info = UHFClient.getInstance();
        if (info != null) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    stopped = UHFClient.mUHF.command(CommandType.STOP_MULTI_QUERY_TAGS_EPC, null);
                    handlerThread.quit();
                    handlerThread.interrupt();
                    if (stopped) {
                        Log.i("rfid", "Stop Ok");
                    } else {
                        Log.w("rfid", "Stop Fail");
                    }
                    UHFClient.mUHF.setCallBack(null);
                }
            }).run();
        }
    }

    HandlerThread handlerThread;
    Handler handler;

    @Override
    public void method(final char[] data) {
        //当前在子线程内
        //可改为Executors.newFixedThreadPool(5)线程池方式
        if (data.length <= 0) {
            return;
        }
        if (handlerThread == null) {
            handlerThread = new HandlerThread("HandlerThread");
        }
        try {
            handlerThread.start();
        } catch (Exception e) {
        }
        if (handler == null) {
            handler = new Handler(handlerThread.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    char[] data = (char[]) msg.obj;
                    doWork(data);
                    super.handleMessage(msg);
                }
            };
        }
        Message msg = new Message();
        msg.obj = data;
        handler.sendMessage(msg);

    }

    void doWork(char[] data) {
        //把EPC拷贝出来显示
        char msb = data[0];
        char lsb = data[1];
        int pc = (msb & 0x00ff) << 8 | (lsb & 0x00ff);
        pc = (pc & 0xf800) >> 11;

        char[] tmp = new char[pc * 2];
        System.arraycopy(data, 2, tmp, 0, tmp.length);
        String str_tmp = ShareData.CharToString(tmp, tmp.length);
        str_tmp = str_tmp.replace(" ", "");
        final String finalStr_tmp = str_tmp;
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (stopped) {
                    LogUtils.i("tags.clear");
                    tags.clear();
                    mHandler.removeCallbacksAndMessages(null);
                    return;
                }
                if (!tags.contains(finalStr_tmp)) {
                    tags.add(finalStr_tmp);
                    Log.i("rfid", "str_tmp=" + finalStr_tmp);
                    //todo 后续优化 预先把数据库车辆数据读取到内存集合中 从集合中查找
                    CarInfo carInfo = mCarInfoDao.queryBuilder().where(CarInfoDao.Properties.Rfid.eq(finalStr_tmp)).unique();
                    if (carInfo == null) {
                        LogUtils.i(finalStr_tmp + "尚未绑定车辆");
                        ToastUtils.showShort("盘点失败:" + finalStr_tmp + "尚未绑定车辆");
                        return;
                    }
                    tvRfid.setText(finalStr_tmp);
                    tvVin.setText(carInfo.getVin());
                    tvType.setText(carInfo.getType());
                    tvColor.setText(carInfo.getColor());
                    tvStatus.setText("在库");
                    tvStatus.setTextColor(getActivity().getResources().getColor(R.color.car_in));
                    tvTime.setText(DateUtils.format(System.currentTimeMillis()));
                    save(carInfo, false);
                }
            }
        });
    }

    @Override
    protected void lazyLoad() {
        if (!isVisible) {
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                UHFUtils uhfUtils = new UHFUtils(getActivity());
                uhfUtils.handleSetPower(30);
            }
        }).run();
        if (btScan != null) {
            btScan.setChecked(false);
        }
    }

    @Override
    public void onKeyDown(int keyCode, KeyEvent event) {
        Log.i("StockCountFragment", "onkeyDown");
        if (btScan.getVisibility() == View.VISIBLE) {
            btScan.setChecked(!btScan.isChecked());
        }
    }

    @Subscribe()
    public void onMessageEvent(BindEvent bindEvent) {
        //对于先盘点发现未绑定然后绑定的tag,应从tags里移除,避免再次进入"尚未绑定车辆"代码块
        String tag = bindEvent.tag;
        if (!TextUtils.isEmpty(tag)) {
            if (tags.contains(tag)) {
                tags.remove(tag);
            }
        }
    }
}
