package com.imdroid.beidou.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imdroid.beidou.common.HttpResult;
import com.imdroid.common.util.HexUtil;
import com.imdroid.secapi.client.HttpResp;
import com.imdroid.secapi.client.RtcmClient;
import com.imdroid.secapi.client.VersionClient;
import com.imdroid.secapi.dto.*;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Controller
public class VersionController extends BasicController{
    @Value("${version.path}")
    private String version_path;
    @Autowired
    GnssDeviceMapper gnssDeviceMapper;
    @Autowired
    private GnssStatusMapper gnssStatusMapper;

    @Autowired
    RtcmClient rtcmClient;
    @Autowired
    OpLogManager opLogManager;
    @Autowired
    TenantMapper tenantMapper;
    @Autowired
    VersionClient versionClient;
    @Value("${ver_server.connect.cmd}")
    String verServerConnectCmd;

    @Data
    public class FirmwareInfo{
        String name;
        long length;
        long create_time;

        public FirmwareInfo(String n, long l, long t){
            name = n;
            length = l;
            create_time = t;
        }
    }

    // 正在升级的设备map，deviceId <-> UpgradeInfo(高字节：升级结果；低字节：进度)
    final Map<String, Short> upgradingDeviceList = new ConcurrentHashMap<>();
    final Map<String, String> deviceSNtoFirmwareMap=new HashMap<>();

    @PostConstruct
    public void init(){
        deviceSNtoFirmwareMap.put("2353","2353");
        deviceSNtoFirmwareMap.put("2410","2410");
        deviceSNtoFirmwareMap.put("2412","2410");
        deviceSNtoFirmwareMap.put("2415","2415");
        deviceSNtoFirmwareMap.put("2419","2415");
        deviceSNtoFirmwareMap.put("2421","2421");
        deviceSNtoFirmwareMap.put("2435","2421");
        deviceSNtoFirmwareMap.put("2439","2439");
        deviceSNtoFirmwareMap.put("2445","2439");
        deviceSNtoFirmwareMap.put("8450","8450");
        deviceSNtoFirmwareMap.put("8507","8450");
        deviceSNtoFirmwareMap.put("8512","8450");
        deviceSNtoFirmwareMap.put("8513","8450");
        deviceSNtoFirmwareMap.put("8516","8515");
        deviceSNtoFirmwareMap.put("8522","8515");
        deviceSNtoFirmwareMap.put("9450","9450");
        deviceSNtoFirmwareMap.put("9513","9450");
        deviceSNtoFirmwareMap.put("9522","9515");
        deviceSNtoFirmwareMap.put("6516","6515");
        deviceSNtoFirmwareMap.put("6521","6515");
        deviceSNtoFirmwareMap.put("6522","6515");
    }
    /**** 推送页面  *****/
    @RequestMapping("/sys/ver_mgr")
    public String gnssDevCfg(Model m, HttpSession session) {
        initModel(m, session);
        List<Tenant> tenants = tenantMapper.selectList(null);
        m.addAttribute("tenant_list", tenants);

        return "/page/gnss_ver_mgr";
    }

    /**** 推送数据  *****/
    @RequestMapping("/sys/ver_mgr/firmware_list")
    @ResponseBody
    public JSONObject listFirmware(int page, int limit) {
        List<FirmwareInfo> firmwareInfoList = new ArrayList();
        int total = getFirmwareList(page, limit,firmwareInfoList);
        //用PageInfo对结果进行包装,传入连续显示的页数
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 0);
        jsonObject.put("msg", "");
        jsonObject.put("count", total);
        jsonObject.put("data", firmwareInfoList);
        return jsonObject;
    }

    @RequestMapping("/sys/ver_mgr/gnss_device_list")
    @ResponseBody
    public JSONObject list(HttpSession session, int page, int limit, String searchParams) {
        Page<GnssDevice> pageable = new Page<>(page, limit);
        QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("deviceid");

        // 条件查询
        if(searchParams != null) {
            JSONObject search = (JSONObject) JSONObject.parse(searchParams);
            //设备号
            String deviceid = search.getString("deviceid");
            if (StringUtils.hasText(deviceid)) {
                queryWrapper.like("deviceid", deviceid);
            }
            //项目号
            String project_id = search.getString("project_id");
            if (StringUtils.hasText(project_id)) {
                queryWrapper.like("project_id", project_id);
            }
            //所属组织
            String tenantname = search.getString("tenantname");
            if (StringUtils.hasText(tenantname)) {
                if(tenantname.startsWith("非SAAS"))
                    queryWrapper.ne("tenantname",Tenant.SAAS_PROVIDER_NAME);
                else queryWrapper.like("tenantname", tenantname);
            }
            //桩号
            String sector = search.getString("sector");
            if (StringUtils.hasText(sector)) {
                queryWrapper.like("sector", sector);
            }
            //设备类型
            Integer devicetype = search.getInteger("devicetype");
            if (devicetype != null && devicetype != QUERY_ALL) {
                queryWrapper.eq("devicetype", devicetype);
            }
            //版本
            String appver = search.getString("appver");
            if (StringUtils.hasText(appver)) {
                queryWrapper.like("appver", appver);
            }
            //备注
            String remark = search.getString("remark");
            if (StringUtils.hasText(remark)) {
                queryWrapper.like("remark", remark);
            }
            //使用状态
            Integer opmode = search.getInteger("opmode");
            if (opmode != null && opmode != QUERY_ALL) {
                queryWrapper.eq("opmode", opmode);
            }
        }

        IPage<GnssDevice> cs = gnssDeviceMapper.selectPage(pageable, queryWrapper);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 0);
        jsonObject.put("msg", "");
        jsonObject.put("count", cs.getTotal());
        jsonObject.put("data", cs.getRecords());
        return jsonObject;
    }

    @PostMapping("/sys/ver_mgr/upgrade")
    @ResponseBody
    public HttpResult upgradeApp(@RequestParam String firmware, @RequestParam String id_list) throws Exception {
        HttpResp rsp;
        if(firmware!=null && !firmware.equals("undefined")) {
            String[] deviceList = id_list.split(";");
            //请求版本服务升级
            try {
                String invalidId = checkUpgradeList(deviceList, firmware);
                if(invalidId==null) {
                    rsp = versionClient.upgrade(id_list, firmware);
                }
                else return HttpResult.fail("设备型号和固件不匹配:"+invalidId);
                //System.out.println(id_list);
            }
            catch (Exception e){
                return HttpResult.fail("版本服务未启动");
            }
            if(rsp.getCode() == HttpResp.HTTP_RSP_OK){
                //设置设备的使用状态为升级，下发连接版本服务器指令
                startUpgrade(deviceList);
                return HttpResult.success("开始升级");
            }
            else{
                return HttpResult.fail(rsp.getResponseMessage());
            }
        }

        return HttpResult.fail("非法固件");
    }

    int getFirmwareList(int page, int limit, List firmwareInfo){
        File folder = new File(version_path);
        File[] files = folder.listFiles((file) -> file.getName().endsWith(".bin"));
        if(files==null) return 0;

        Arrays.sort(files, new Comparator<File>() {
            public int compare(File f1, File f2) {
                long diff = f1.lastModified() - f2.lastModified();
                if (diff > 0)
                    return -1;
                else if (diff == 0)
                    return 0;
                else
                    return 1;//如果 if 中修改为 返回-1 同时此处修改为返回 1  排序就会是递减
            }

            public boolean equals(Object obj) {
                return true;
            }

        });

        int count = 0;
        for(File file:files){
            if((int)count/limit+1 == page) {
                firmwareInfo.add(new FirmwareInfo(file.getName(), file.length(), file.lastModified()));
            }
            count++;
        }

        return files.length;
    }

    String checkUpgradeList(String[] deviceList, String firmware){
        for(String deviceId:deviceList){
            String snHigh = deviceId.substring(0,4);
            if(!firmware.contains(deviceSNtoFirmwareMap.get(snHigh))){
                return deviceId;
            }
        }
        return null;
    }
    void startUpgrade(String[] deviceList){
        for(String deviceId:deviceList){
            UpdateWrapper<GnssDevice> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("deviceid",deviceId).set("opmode",GnssDevice.OP_MODE_UPGRADING);
            gnssDeviceMapper.update(null, updateWrapper);
            rtcmClient.config(deviceId,getConnectVerServerCmd(deviceId));
        }
    }

    String getConnectVerServerCmd(String deviceId){
        short len = (short) (verServerConnectCmd.length() + 5);
        return "d31a" + HexUtil.Short2HexString(len)+
                HexUtil.Int2HexString(Integer.parseInt(deviceId))+
                "01"+HexUtil.String2HexString(verServerConnectCmd);
    }

}
