package com.imdroid.beidou.controller;

import com.imdroid.beidou.common.Role;
import com.imdroid.beidou.entity.TenantMapper;
import com.imdroid.beidou.entity.Tenant;
import com.imdroid.common.util.NumberUtils;
import com.imdroid.secapi.client.RtcmClient;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imdroid.beidou.common.HttpResult;
import com.imdroid.beidou.data.vo.device.DeviceInstallVO;
import com.imdroid.beidou.data.vo.device.DeviceListVO;
import com.imdroid.beidou.data.vo.device.DeviceStatusVO;
import com.imdroid.secapi.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Controller
public class GnssDeviceController extends BasicController{
    @Autowired
    GnssGroupMapper gnssGroupMapper;
    @Autowired
    GnssGroupCalcMapper gnssGroupCalcMapper;
    @Autowired
    GnssGroupFwdMapper gnssGroupFwdMapper;
    @Autowired
    GnssDeviceMapper gnssDeviceMapper;
    @Autowired
    TenantMapper tenantMapper;
    @Autowired
    private GnssStatusMapper gnssStatusMapper;
    @Autowired
    GnssCalcDataMapper gnssCalcDataMapper;

    @Autowired
    RtcmClient rtcmClient;

    /**** 推送页面  *****/
    @RequestMapping("/page/gnss_dev_cfg")
    public String gnssDevCfg(Model m, HttpSession session) {
        initModel(m, session);
        List<Tenant> tenants;
        if(loginRole.equals(Role.SUPER_ADMIN) || loginRole.equals(Role.ADMIN)) {
            tenants = tenantMapper.selectList(null);
        }
        else{
            QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", tenantId);
            tenants = tenantMapper.selectList(queryWrapper);
        }
        m.addAttribute("tenant_list", tenants);

        return "/page/gnss_dev_cfg";
    }

    @RequestMapping("/page/table/gnss_add_dev")
    public String gnssUpdateDev(Model m, HttpSession session) {
        initModel(m, session);
        //以下用于下拉框数据
        List<GnssGroup> gnssGroups = gnssGroupMapper.selectList(null);
        List<GnssGroupCalc> gnssGroupCalcs = gnssGroupCalcMapper.selectList(null);
        List<GnssGroupFwd> gnssGroupFwds = gnssGroupFwdMapper.selectList(null);

        List<Tenant> tenants;
        if(loginRole.equals(Role.SUPER_ADMIN) || loginRole.equals(Role.ADMIN)) {
            tenants = tenantMapper.selectList(null);
        }
        else{
            QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", tenantId);
            tenants = tenantMapper.selectList(queryWrapper);
        }
        m.addAttribute("tenant_list", tenants);
        m.addAttribute("gnss_group_list", gnssGroups);
        m.addAttribute("gnss_group_calc_list", gnssGroupCalcs);
        m.addAttribute("gnss_group_fwd_list", gnssGroupFwds);

        return "/page/table/gnss_add_dev";
    }

    /**** 推送数据  *****/
    @RequestMapping("/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<>();
        Integer tenantId = getTenantId(session);
        if(tenantId != null && tenantId != Tenant.SAAS_PROVIDER_ID) {
            queryWrapper.eq("tenantid", tenantId);
        }
        queryWrapper.orderByAsc("deviceid");

        // 条件查询
        if(searchParams != null) {
            JSONObject search = (JSONObject) JSONObject.parse(searchParams);
            //设备号
            String deviceid = search.getString("deviceid");
            if (!StringUtils.isEmpty(deviceid)) {
                queryWrapper.like("deviceid", deviceid);
            }
            //父设备号
            String parentid = search.getString("parentid");
            if (!StringUtils.isEmpty(parentid)) {
                queryWrapper.like("parentid", parentid);
            }
            //项目号
            String project_id = search.getString("project_id");
            if (!StringUtils.isEmpty(project_id)) {
                queryWrapper.like("project_id", project_id);
            }
            //所属组织
            String tenantname = search.getString("tenantname");
            if (!StringUtils.isEmpty(tenantname)) {
                queryWrapper.like("tenantname", tenantname);
            }
            //设备类型
            Integer devicetype = search.getInteger("devicetype");
            if (devicetype != null && devicetype != QUERY_ALL) {
                queryWrapper.eq("devicetype", devicetype);
            }
        }

        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("/gnss/device/update")
    @ResponseBody
    public String update(HttpSession session, @RequestBody JSONObject object) throws Exception {
        // 从请求参数中创建对象
        GnssDevice device = JSONObject.toJavaObject(object,GnssDevice.class);
        QueryWrapper<Tenant> tenantQueryWrapper = new QueryWrapper<>();
        tenantQueryWrapper.eq("name", device.getTenantname());
        Tenant tenant = tenantMapper.selectOne(tenantQueryWrapper);
        if(tenant==null) return HttpResult.result(2, "invalid tenant");
        device.setTenantid(tenant.getId());
        device.setUpdatetime(LocalDateTime.now());
        device.setUpdateuser((String) session.getAttribute("login_user"));

        // 检测该对象是否已存在
        QueryWrapper<GnssDevice> wrapper = new QueryWrapper<>();
        wrapper.eq("deviceid",device.getDeviceid());
        GnssDevice old_device = gnssDeviceMapper.selectOne(wrapper);
        //新增或更新
        int num = 0;
        if(null != old_device) {
            if(!old_device.getGroup_id().equals(device.getGroup_id())){
                device.setSyn(false);
            }
            device.setId(old_device.getId());
            device.setCreateuser(old_device.getCreateuser());
            device.setCreatetime(old_device.getCreatetime());
            num = gnssDeviceMapper.updateById(device);
        }
        else{
            device.setCreatetime(LocalDateTime.now());
            device.setCreateuser((String) session.getAttribute("login_user"));
            device.setSyn(false);
            num = gnssDeviceMapper.insert(device); //id自增
        }
        if (num == 0) {
            return HttpResult.failed();
        } else {
            // 更新组参数的关联个数
            updateBasicGroupAssociatedNum(device,old_device);
            rtcmClient.deviceParamChanged(device.getDeviceid());
            return HttpResult.ok();
        }
    }

    @PostMapping("/gnss/device/init_loc")
    @ResponseBody
    public JSONObject initLoc(@RequestParam String deviceid){
        QueryWrapper<GnssCalcData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deviceid",deviceid);
        queryWrapper.eq("enabled",1);
        queryWrapper.orderByDesc("createtime");
        queryWrapper.last("limit 1");
        queryWrapper.isNotNull("rpose");
        GnssCalcData calcData = gnssCalcDataMapper.selectOne(queryWrapper);
        if(calcData != null){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ipose", NumberUtils.scaleTwo(calcData.getRpose()));
            jsonObject.put("iposn",NumberUtils.scaleTwo(calcData.getRposn()));
            jsonObject.put("iposd",NumberUtils.scaleTwo(calcData.getRposd()));
            return jsonObject;
        }
        return null;
    }

    void updateBasicGroupAssociatedNum(GnssDevice newCfg, GnssDevice oldCfg){
        updateBasicGroupAssociatedNum(newCfg.getGroup_id());
        updateCalcGroupAssociatedNum(newCfg.getCalc_group_id());
        updateFwdGroupAssociatedNum(newCfg.getFwd_group_id());

        if(oldCfg!=null){
            if(!oldCfg.getGroup_id().equals(newCfg.getGroup_id())){
                updateBasicGroupAssociatedNum(oldCfg.getGroup_id());
            }
            if(!oldCfg.getCalc_group_id().equals(newCfg.getCalc_group_id())){
                updateCalcGroupAssociatedNum(oldCfg.getCalc_group_id());
            }
            if(!oldCfg.getFwd_group_id().equals(newCfg.getFwd_group_id())){
                updateFwdGroupAssociatedNum(oldCfg.getFwd_group_id());
            }
        }
    }

    void updateBasicGroupAssociatedNum(int groupId) {
        // 更新基本参数组
        QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("group_id", groupId);
        Long groupAssociatedNum = gnssDeviceMapper.selectCount(queryWrapper);
        GnssGroup group = gnssGroupMapper.selectById(groupId);
        if (group != null) {
            group.setDevice_num(groupAssociatedNum.intValue());
            gnssGroupMapper.updateById(group);
        }
    }

    void updateCalcGroupAssociatedNum(int groupId) {
        // 更新解算参数组
        QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("calc_group_id", groupId);
        Long groupAssociatedNum = gnssDeviceMapper.selectCount(queryWrapper);
        GnssGroupCalc group = gnssGroupCalcMapper.selectById(groupId);
        if (group != null) {
            group.setDevice_num(groupAssociatedNum.intValue());
            gnssGroupCalcMapper.updateById(group);
        }
    }

    void updateFwdGroupAssociatedNum(String groupId) {
        // 更新推送参数组
        QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fwd_group_id", groupId);
        Long groupAssociatedNum = gnssDeviceMapper.selectCount(queryWrapper);
        GnssGroupFwd group = gnssGroupFwdMapper.selectById(groupId);
        if(group!=null) {
            group.setDevice_num(groupAssociatedNum.intValue());
            gnssGroupFwdMapper.updateById(group);
        }
    }

    @PostMapping("/gnss/device/delete")
    @ResponseBody
    public String delete(@RequestParam String del_id) throws Exception {
        QueryWrapper<GnssDevice> wrapper = new QueryWrapper<>();
        wrapper.eq("deviceid",del_id);
        int num = gnssDeviceMapper.delete(wrapper);
        if (num == 0) {
            return HttpResult.failed();
        } else{
            rtcmClient.deviceParamChanged(del_id);
            return HttpResult.ok();
        }
    }

    /**
     * 设备现场安装
     *
     * @param deviceInstallVO 设备安装信息
     * @return HttpResult
     */
    @PostMapping("/gnss/device/install")
    @ResponseBody
    public HttpResult install(@Validated DeviceInstallVO deviceInstallVO) {
        QueryWrapper<GnssDevice> wrapper = new QueryWrapper<>();
        wrapper.eq("deviceid",deviceInstallVO.getDeviceId());
        GnssDevice gnssDevice = gnssDeviceMapper.selectOne(wrapper);
        if (gnssDevice == null) {
            return HttpResult.fail("设备不存在");
        }
        GnssDevice tempDevice = new GnssDevice();
        tempDevice.setId(gnssDevice.getId());
        //安装位置通过GNSS坐标自动获取
        tempDevice.setPictures(deviceInstallVO.getPictures());
        gnssDeviceMapper.updateById(tempDevice);

        return HttpResult.success(new DeviceListVO(gnssDevice.getId(), gnssDevice.getDeviceid(), gnssDevice.getName()));
    }

    /**
     * 根据主键id查找设备信息
     *
     * @param id 主键id
     * @return 设备信息 DeviceStatusVO
     */
    @GetMapping("/gnss/device/status")
    @ResponseBody
    public HttpResult findById(Long id) {
        GnssDevice gnssDevice = gnssDeviceMapper.selectById(id);
        if (gnssDevice == null) {
            return HttpResult.fail("设备不存在");
        }
        GnssStatusJoin gnssStatus = gnssStatusMapper.queryByDeviceId(gnssDevice.getDeviceid());
        DeviceStatusVO deviceStatusVO = new DeviceStatusVO(gnssDevice, gnssStatus);
        return HttpResult.success(deviceStatusVO);
    }

    /**
     *  获取设备列表
     *
     * @param session HttpSession
     * @param page page
     * @param limit limit
     * @param searchParams searchParams
     * @return JSONObject
     */
    @GetMapping("/gnss/device/simple-list")
    @ResponseBody
    public JSONObject simpleList(HttpSession session, Integer page, Integer limit, String searchParams) {
        System.out.println(page + "," + limit);
        Page<GnssDevice> pageable = new Page<>(page, limit);
        QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
        System.out.println("searchParams:" + searchParams);
        // 条件查询
        if(searchParams != null) {
            JSONObject search = (JSONObject) JSONObject.parse(searchParams);
            //设备号
            String deviceid = search.getString("deviceid");
            if (!StringUtils.isEmpty(deviceid)) {
                queryWrapper.like("deviceid", deviceid);
            }
            //父设备号
            String parentid = search.getString("parentid");
            if (!StringUtils.isEmpty(parentid)) {
                queryWrapper.like("parentid", parentid);
            }
            //设备类型
            Integer devicetype = search.getInteger("devicetype");
            if (devicetype != null && devicetype != QUERY_ALL) {
                queryWrapper.eq("devicetype", devicetype);
            }
        }

        IPage<GnssDevice> cs = gnssDeviceMapper.selectPage(pageable, queryWrapper);
        List<DeviceListVO> deviceListVOList = new ArrayList<>(cs.getRecords().size());
        for (GnssDevice device : cs.getRecords()) {
            DeviceListVO deviceListVO = new DeviceListVO(device.getId(), device.getDeviceid(), device.getName());
            deviceListVOList.add(deviceListVO);
        }

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

}
