package com.ruoyi.dataprocess.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.HwDictConstants;
import com.ruoyi.common.core.constant.TdEngineConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.ResultEnums;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.dataprocess.amap.LocationVo;
import com.ruoyi.dataprocess.amap.PositionUtils;
import com.ruoyi.dataprocess.amap.PositionVo;
import com.ruoyi.dataprocess.common.ImageUtils;
import com.ruoyi.dataprocess.domain.HwAlarmInfo;
import com.ruoyi.dataprocess.domain.HwDevice;
import com.ruoyi.dataprocess.domain.HwElectronicFence;
import com.ruoyi.dataprocess.mapper.HwAlarmInfoMapper;
import com.ruoyi.dataprocess.mapper.HwDeviceMapper;
import com.ruoyi.dataprocess.mapper.HwElectronicFenceMapper;
import com.ruoyi.dataprocess.service.IDataProcessService;
import com.ruoyi.tdengine.api.RemoteTdEngineService;
import com.ruoyi.tdengine.api.domain.TdField;
import com.ruoyi.tdengine.api.domain.TdTableVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Description: 数据处理业务类
 * @ClassName: DataProcessServiceImpl
 * @Author : xins
 * @Date :2023-09-04  8:58
 * @Version :1.0
 */
@Service
public class DataProcessServiceImpl implements IDataProcessService {

    private static final Logger logger = LoggerFactory.getLogger(DataProcessServiceImpl.class);
    @Resource
    private RemoteTdEngineService remoteTdEngineService;

    @Autowired
    private HwDeviceMapper hwDeviceMapper;

    @Autowired
    private HwElectronicFenceMapper hwElectronicFenceMapper;

    @Autowired
    private HwAlarmInfoMapper hwAlarmInfoMapper;

    /**
     * @param imagePath
     * @param imagePatterns
     * @param: jsonData
     * @description 处理业务数据
     * @author xins
     * @date 2023-08-31 16:16
     */
    @Override
    public void processBusinessData(String jsonData, String imagePath, String imagePatterns) {
        JSONObject json = JSON.parseObject(jsonData);
        Long ts = json.getLong(TdEngineConstants.PAYLOAD_TS);
        String tsStr = String.valueOf(ts);
        if (tsStr.length() == 10) {
            ts = ts * 1000;
        }
        JSONArray paramArr = json.getJSONArray(TdEngineConstants.PAYLOAD_PARAM);
//        System.out.println(this.hwDeviceMapper);
//        System.out.println(this.remoteTdEngineService);
        for (int i = 0; i < paramArr.size(); i++) {
            JSONObject paramJson = paramArr.getJSONObject(i);
            JSONObject dataValueJson = paramJson.getJSONObject(TdEngineConstants.PAYLOAD_DATAVALUE);
            String deviceCode = dataValueJson.getString(TdEngineConstants.PAYLOAD_DEVICE_CODE);
            HwDevice hwDevice = hwDeviceMapper.selectHwDeviceByDeviceCode(deviceCode);
            Long sceneId = hwDevice.getSceneId();
            Long deviceId = hwDevice.getDeviceId();
            Long monitorUnitId = hwDevice.getMonitorUnitId();
            Long tenantId = hwDevice.getTenantId();
            String databaseName = TdEngineConstants.DEFAULT_DB_NAME_PREFIX + sceneId;
            String tableName = TdEngineConstants.DEFAULT_TABLE_NAME_PREFIX + deviceId;

            dataValueJson.remove(TdEngineConstants.PAYLOAD_DEVICE_CODE);
            TdTableVo tdTableVo = new TdTableVo();
            List<TdField> schemaFields = new ArrayList<>();

            //添加timestamp字段，默认字段名称是ts，协议上传的key是timestamp
            TdField firstTdField = new TdField();
            firstTdField.setFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME);
            firstTdField.setFieldValue(ts);
            schemaFields.add(firstTdField);

            Object longitude = null;
            Object latitude = null;

            for (Map.Entry<String, Object> entry : dataValueJson.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();

                /**
                 * 先对key进行转换，例如对于key是value的需要转换成value1；
                 */
                key = TdEngineConstants.TDENGINE_KEY_TRANSFER_MAP.get(key) == null ? key
                        : TdEngineConstants.TDENGINE_KEY_TRANSFER_MAP.get(key);
                System.out.println(key + "---" + value);

                if (value instanceof String) {
                    String valueStr = (String) value;
                    if (StringUtils.isNotBlank(valueStr)) {
                        /**
                         * 先判读是否是图片,并获取图片名称， 获取到证明是图片
                         */
                        String[] imagePatternArr = imagePatterns.split(",");
                        String imageType = ImageUtils.getImageType(valueStr, imagePatternArr);
                        if (StringUtils.isNotBlank(imageType)) {
                            //保存图片，并返回图片详细地址进行赋值保存
                            String imageFileName = ImageUtils.convertBase64ToImage(valueStr, imagePath, imageType, deviceId);
                            if (StringUtils.isNotBlank(imageFileName)) {
                                value = imageFileName;
                            } else {
                                continue;
                            }
                        }

                        TdField tdField = new TdField();
                        tdField.setFieldName(key);
                        tdField.setFieldValue(value);
                        schemaFields.add(tdField);
                    }
                } else {
                    TdField tdField = new TdField();
                    tdField.setFieldName(key);
                    tdField.setFieldValue(value);
                    schemaFields.add(tdField);

                    //经纬度判断
                    if (key.equalsIgnoreCase(HwDictConstants.DEFAULT_FUNCTION_LONGITUDE_IDENTIFIER)) {
                        longitude = value;
                    } else if (key.equalsIgnoreCase(HwDictConstants.DEFAULT_FUNCTION_LATITUDE_IDENTIFIER)) {
                        latitude = value;
                    }
                }
            }

            System.out.println(databaseName + "---" + tableName);
            tdTableVo.setDatabaseName(databaseName);
            tdTableVo.setTableName(tableName);
            tdTableVo.setSchemaFields(schemaFields);

            System.out.println("longtitude:" + longitude + "latit:" + latitude);

            final R<?> insertResult = this.remoteTdEngineService.insertTable(tdTableVo);
            if (insertResult.getCode() == ResultEnums.SUCCESS.getCode()) {
                logger.info("Insert data result: {}", insertResult.getMsg());
            } else {
                logger.error("Insert data Exception: {},data:{}", insertResult.getMsg(), jsonData);
            }

            if (longitude != null && latitude != null) {
                checkElectronicFence(deviceId, tenantId, monitorUnitId, sceneId, longitude, latitude, ts);
            }
        }
    }

    /**
     * @param: deviceId
     * @param: monitorUnitId
     * @param: sceneId
     * @param: longitude
     * @param: latitude
     * @param: ts
     * @description 校验此设备电子围栏
     * @author xins
     * @date 2023-09-04 14:04
     */
    private void checkElectronicFence(Long deviceId, Long tenantId, Long monitorUnitId, Long sceneId, Object longitude, Object latitude, Long ts) {
        List<HwElectronicFence> hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesByDeviceId(deviceId);
        if (StringUtils.isEmpty(hwElectronicFences)) {
            System.out.println("---------");
            hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesByMonitorUnitId(monitorUnitId);
        }
        if (StringUtils.isEmpty(hwElectronicFences)) {
            hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesBySceneId(sceneId);
            System.out.println("---------33333");
        }

        if (StringUtils.isNotEmpty(hwElectronicFences)) {
            hwElectronicFences.forEach(hwElectronicFence -> {
                String effectiveTimeFlag = hwElectronicFence.getEffectiveTimeFlag();
                String triggerStatus = hwElectronicFence.getTriggerStatus();
                boolean isAlarmed = false;//是否报警
                if (effectiveTimeFlag.equals(HwDictConstants.EFFECTIVE_TIME_FLAG_LONG)) {
                    String areaShapeFlag = hwElectronicFence.getAreaShapeFlag();
                    String areaRange = hwElectronicFence.getAreaRange();
                    if (areaShapeFlag.equals(HwDictConstants.AREA_SHAPE_FLAG_POLYGN)) {
                        LocationVo polygonVo = new LocationVo();
                        polygonVo.setMarkerType(LocationVo.MARKER_TYPE_POLYGON);
                        List<List<PositionVo>> polygonList = new ArrayList<>();
                        List<PositionVo> postionList = new ArrayList<>();
                        String[] areaRangeArr = areaRange.split("_");//多个点，每个点的经纬度信息（经度_纬度）
                        for (String areaRange1 : areaRangeArr) {
                            String[] areaRange1Arr = areaRange1.split(",");
                            String longitudeStr = areaRange1Arr[0];
                            String latitudeStr = areaRange1Arr[1];
                            postionList.add(new PositionVo(new BigDecimal(longitudeStr), new BigDecimal(latitudeStr)));
                            polygonList.add(postionList);
                        }

                        polygonVo.setPolygonList(polygonList);

                        /**
                         * 传入的longitude和latitude是object类型，本身有可能是BigDecimal，Double，Long和Integer，先转成String再转成Double
                         */
                        boolean isWithin = PositionUtils.checkAddressInLocation(polygonVo, Double.valueOf(String.valueOf(longitude)), Double.valueOf(String.valueOf(latitude)));
                        if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT) && !isWithin) {//如果电子围栏配置是出界，而此设备出界则报警
                            isAlarmed = true;
                        } else if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY) && isWithin) {//如果电子围栏配置是入界，而此设备入界则报警
                            isAlarmed = true;
                        }
                        System.out.println("iswithin" + isWithin);

                    } else if (areaShapeFlag.equals(HwDictConstants.AREA_SHAPE_FLAG_CIRCULA)) {
                        String[] areaRangeArr = areaRange.split(",");
                        String longitudeStr = areaRangeArr[0];
                        String latitudeStr = areaRangeArr[1];
                        String radiusStr = areaRangeArr[2];
                        LocationVo circulrVo = new LocationVo();
                        circulrVo.setRadius(Double.valueOf(radiusStr));
                        circulrVo.setLongitude(Double.valueOf(longitudeStr));
                        circulrVo.setLatitude(Double.valueOf(latitudeStr));
                        circulrVo.setMarkerType(LocationVo.MARKER_TYPE_CIRCULAR);
                        boolean isWithin = PositionUtils.checkAddressInLocation(circulrVo, Double.valueOf(String.valueOf(longitude)), Double.valueOf(String.valueOf(latitude)));
                        System.out.println("iswithin:" + isWithin);
                        if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT) && !isWithin) {//如果电子围栏配置是出界，而此设备出界则报警
                            isAlarmed = true;
                        } else if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY) && isWithin) {//如果电子围栏配置是入界，而此设备入界则报警
                            isAlarmed = true;
                        }
                    }
                }

                if (isAlarmed) {
                    HwAlarmInfo hwAralmInfo = new HwAlarmInfo();
                    hwAralmInfo.setAlarmInfoType(HwDictConstants.ALARM_INFO_TYPE_ELECTRONIC_FENCE);
                    hwAralmInfo.setAlarmReleatedId(hwElectronicFence.getElectronicFenceId());
                    hwAralmInfo.setDeviceId(deviceId);
                    hwAralmInfo.setMonitorUnitId(monitorUnitId);
                    hwAralmInfo.setTenantId(tenantId);
                    hwAralmInfo.setSceneId(sceneId);
                    hwAralmInfo.setFunctionValue(longitude + "_" + latitude);
                    hwAralmInfo.setTriggerStatus(triggerStatus);
                    hwAralmInfo.setAlarmTime(new Date(ts));
                    hwAralmInfo.setCreateTime(new Date());
                    hwAlarmInfoMapper.insertHwAlarmInfo(hwAralmInfo);
                }
            });
        }
    }

    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date();
        System.out.println(format.format(date));
        Object jsonData = "{\n" +
                "\n" +
                "  \"timestamp\": 1689814424,\"type\": \"CMD_REPORTDATA\",\n" +
                "  \"param\": [\n{\n" +
                "      \"datatype\": \"cttemperature\",\n" +
                "\"datavalue\": {\n" +
                "        \"uid\": \"0009340109040126\",  \"alias\": \"\",\n" +
                "        \"value\": 25.6,\n" +
                " \"voltage\": 3.76,\n" +
                "        \"rssi\": -80\n" +
                " }  },\n" +
                "    {\"datatype\": \"cttemperature\",\n" +
                "      \"datavalue\": {\n" +
                "        \"uid1\": \"00093440109040924\",\n" +
                "        \"alias\": \"\",\n" +
                "        \"value\": 25.6,\n" +
                "        \"voltage\": 3.64,\n" +
                "        \"rssi\": -87\n" +
                "      }\n" +
                "    }]}";

    }
}
