package com.multictrl.common.utils.kmz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.constant.SetActionParams;
import com.multictrl.common.exception.RenException;
import com.multictrl.modules.business.dto.RouteDTO;
import com.multictrl.modules.business.dto.RouteWaypointDTO;
import com.multictrl.modules.business.dto.WaypointActionDTO;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * kml解析
 *
 * @author Sdy
 * @since 1.0.0 2026/6/18
 */
public class WpmlKmlParser {

    public static RouteDTO parseKmlFile(byte[] bytes, Boolean accurateImport) throws DocumentException {
        RouteDTO dto = new RouteDTO();
        SAXReader reader = new SAXReader();
        Document document = reader.read(new ByteArrayInputStream(bytes));
        Element root = document.getRootElement();

        Element doc = root.element("Document");
        if (doc == null) {
            throw new RenException("kml文件有误，无法解析");
        }
        Element folder = doc.element("Folder");
        if (folder == null) {
            throw new RenException("模板信息不存在，无法解析");
        }
        //解析高度模式
        Element waylineCoordinateSysParam = folder.element("waylineCoordinateSysParam");
        if (waylineCoordinateSysParam == null) {
            if (!accurateImport) {
                throw new RenException("坐标系参数有误，无法解析");
            }
        } else {
            String heightMode = filedValid(waylineCoordinateSysParam.elementText("heightMode"), accurateImport);
            dto.setHeightModel(heightMode);
        }

        // 解析
        String templateType = folder.elementText("templateType");
        if (StringUtils.isEmpty(templateType) && accurateImport) {
            return dto;
        }
        if (StringUtils.isEmpty(templateType) && !accurateImport) {
            throw new RenException("模板类型不存在，解析失败");
        }
        dto.setTemplateType(templateType);
        String autoFlightSpeed = filedValid(folder.elementText("autoFlightSpeed"), accurateImport);
        dto.setFlightSpeed(autoFlightSpeed == null ? null : Double.parseDouble(autoFlightSpeed));
        String globalHeight = filedValid(folder.elementText("globalHeight"), accurateImport);
        dto.setFlightHeight(globalHeight == null ? null : Double.parseDouble(globalHeight));

        List<RouteWaypointDTO> waypointList = new ArrayList<>();
        List<Element> placemarks = folder.elements("Placemark");
        if (CollectionUtil.isEmpty(placemarks)) {
            if (accurateImport) {
                dto.setRouteWaypointList(waypointList);
            } else {
                throw new RenException("航点信息不存在，解析失败");
            }
        } else {
            for (Element placemark : placemarks) {
                RouteWaypointDTO waypoint = new RouteWaypointDTO();
                String useGlobalSpeed = placemark.elementText("useGlobalSpeed");
                String useGlobalHeight = placemark.elementText("useGlobalHeight");
                waypoint.setFollowRouteSpeed(filedValid(useGlobalSpeed, accurateImport) == null ? null : "1".equals(useGlobalSpeed));
                waypoint.setFollowRouteHeight(filedValid(useGlobalHeight, accurateImport) == null ? null : "1".equals(useGlobalHeight));
                waypointList.add(waypoint);
            }
            dto.setRouteWaypointList(waypointList);
        }
        return dto;
    }

    public static void parseWpmlFile(byte[] bytes, RouteDTO dto, Boolean accurateImport) throws DocumentException, IOException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new ByteArrayInputStream(bytes));
        Element root = document.getRootElement();

        Element doc = root.element("Document");
        if (doc == null) {
            throw new RenException("wpml文件有误，无法解析");
        }
        Element missionConfig = doc.element("missionConfig");
        if (missionConfig == null) {
            throw new RenException("任务信息不存在，无法解析");
        }
        dto.setFlyToWaylineMode(filedValid(missionConfig.elementText("flyToWaylineMode"), accurateImport));
        dto.setFinishAction(filedValid(missionConfig.elementText("finishAction"), accurateImport));
        String exitOnRCLost = filedValid(missionConfig.elementText("exitOnRCLost"), accurateImport);
        dto.setExitOnRcLost(exitOnRCLost);
        if ("executeLostAction".equals(exitOnRCLost)) {
            dto.setExecuteRcLostAction(filedValid(missionConfig.elementText("executeRCLostAction"), accurateImport));
        }
        String takeOffSecurityHeight = filedValid(missionConfig.elementText("takeOffSecurityHeight"), accurateImport);
        dto.setTakeoffSecurityHeight(StringUtils.isBlank(takeOffSecurityHeight) ? null : Double.parseDouble(missionConfig.elementText("takeOffSecurityHeight")));
        String globalTransitionalSpeed = filedValid(missionConfig.elementText("globalTransitionalSpeed"), accurateImport);
        dto.setGlobalTransitionalSpeed(StringUtils.isBlank(globalTransitionalSpeed) ? null : Double.parseDouble(globalTransitionalSpeed));
        String globalRTHHeight = filedValid(missionConfig.elementText("globalRTHHeight"), accurateImport);
        dto.setGlobalRthHeight(StringUtils.isBlank(globalRTHHeight) ? null : Double.parseDouble(globalRTHHeight));
        /*Element droneInfo = missionConfig.element("droneInfo");
        if (droneInfo == null) {
            if (!accurateImport) {
                throw new RenException("飞行器机型信息不存在，无法解析");
            }
        } else {
            String droneEnumValue = filedValid(droneInfo.elementText("droneEnumValue"), accurateImport);
            String droneSubEnumValue = filedValid(droneInfo.elementText("droneSubEnumValue"), accurateImport);
        }*/
        /*Element payloadInfo = missionConfig.element("payloadInfo");
        if (payloadInfo == null) {
            if (!accurateImport) {
                throw new RenException("负载机型信息不存在，无法解析");
            }
        } else {
            String payloadEnumValue = filedValid(payloadInfo.elementText("payloadEnumValue"), accurateImport);
            String cameraName = CameraModel.getNameByType(payloadEnumValue);
            dto.setCameraType(cameraName);
        }*/

        Element folder = doc.element("Folder");
        if (folder == null) {
            if (!accurateImport) {
                throw new RenException("航线信息不存在，无法解析");
            }
        } else {
            String autoFlightSpeed = filedValid(folder.elementText("autoFlightSpeed"), accurateImport);
            dto.setFlightSpeed(StringUtils.isBlank(autoFlightSpeed) ? null : Double.parseDouble(autoFlightSpeed));

            List<Element> placemarks = folder.elements("Placemark");
            if (CollectionUtil.isEmpty(placemarks)) {
                if (!accurateImport) {
                    throw new RenException("航点信息不存在，无法解析");
                }
            } else {
                List<RouteWaypointDTO> waypointList = dto.getRouteWaypointList();
                if (waypointList == null || waypointList.isEmpty()) {
                    return;
                }

                for (int i = 0; i < waypointList.size(); i++) {
                    RouteWaypointDTO waypoint = waypointList.get(i);
                    Element placemark = placemarks.get(i);
                    Element point = placemark.element("Point");
                    if (point == null) {
                        if (!accurateImport) {
                            throw new RenException("航点经纬度不存在，无法解析");
                        }
                    } else {
                        String coordinates = point.elementText("coordinates");
                        String[] split = coordinates.split(",");
                        waypoint.setLongitude(Double.valueOf(split[0]));
                        waypoint.setLatitude(Double.valueOf(split[1]));
                    }
                    String index = filedValid(placemark.elementText("index"), accurateImport);
                    waypoint.setWaypointSort(StringUtils.isBlank(index) ? null : Integer.valueOf(index));
                    String executeHeight = filedValid(placemark.elementText("executeHeight"), accurateImport);
                    waypoint.setFlightHeight(StringUtils.isBlank(executeHeight) ? null : Double.parseDouble(executeHeight));
                    String waypointSpeed = filedValid(placemark.elementText("waypointSpeed"), accurateImport);
                    waypoint.setFlightSpeed(StringUtils.isBlank(waypointSpeed) ? null : Double.parseDouble(waypointSpeed));
                    Element waypointHeadingParam = placemark.element("waypointHeadingParam");
                    if (waypointHeadingParam == null) {
                        if (!accurateImport) {
                            throw new RenException("偏航角模式参数不存在，无法解析");
                        }
                    } else {
                        waypoint.setWaypointHeadingMode(filedValid(waypointHeadingParam.elementText("waypointHeadingMode"), accurateImport));
                        String waypointHeadingAngle = filedValid(waypointHeadingParam.elementText("waypointHeadingAngle"), accurateImport);
                        if (StrUtil.isNotBlank(waypointHeadingAngle)) {
                            waypoint.setWaypointHeadingAngle(waypointHeadingAngle);
                        }
                        String waypointPoiPoint = waypointHeadingParam.elementText("waypointPoiPoint");
                        if (StrUtil.isNotBlank(waypointPoiPoint)) {
                            waypoint.setWaypointPoiPoint(waypointPoiPoint);
                        }
                        String waypointHeadingPathMode = filedValid(waypointHeadingParam.elementText("waypointHeadingPathMode"), accurateImport);
                        waypoint.setWaypointHeadingPathMode(StringUtils.isBlank(waypointHeadingPathMode) ? "" : waypointHeadingPathMode);
                    }

                    Element waypointTurnParam = placemark.element("waypointTurnParam");
                    if (waypointTurnParam == null) {
                        if (!accurateImport) {
                            throw new RenException("航点转弯模式不存在，无法解析");
                        }
                    } else {
                        waypoint.setWaypointTruningMode(filedValid(waypointTurnParam.elementText("waypointTurnMode"), accurateImport));
                        String waypointTurnDampingDist = filedValid(waypointTurnParam.elementText("waypointTurnDampingDist"), accurateImport);
                        if (StrUtil.isNotBlank(waypointTurnDampingDist)) {
                            waypoint.setWaypointTurnDampingDist(waypointTurnDampingDist);
                        }
                    }

                    List<WaypointActionDTO> actionList = waypoint.getWaypointActionList();
                    if (CollectionUtil.isEmpty(actionList)) {
                        actionList = new ArrayList<>();
                    }
                    List<Element> actionGroups = placemark.elements("actionGroup");
                    for (Element actionGroup : actionGroups) {
                        Element actionTrigger = actionGroup.element("actionTrigger");
                        String actionTriggerType = actionTrigger.elementText("actionTriggerType");
                        if ("multipleTiming".equals(actionTriggerType) || "multipleDistance".equals(actionTriggerType)) {
                            String actionGroupId = actionGroup.elementText("actionGroupId");
                            String actionTriggerParam = actionTrigger.elementText("actionTriggerParam");
                            WaypointActionDTO action = new WaypointActionDTO();
                            action.setActionType(actionTriggerType);
                            action.setActionValue(actionTriggerParam);
                            action.setActionSort(Integer.parseInt(actionGroupId));
                            actionList.add(action);

                            String actionGroupEndIndex = actionGroup.elementText("actionGroupEndIndex");
                            RouteWaypointDTO uavWaypointDTO = waypointList.get(Integer.parseInt(actionGroupEndIndex));
                            List<WaypointActionDTO> actionList1 = uavWaypointDTO.getWaypointActionList();
                            if (CollectionUtil.isEmpty(actionList1)) {
                                actionList1 = new ArrayList<>();
                            }
                            WaypointActionDTO action2 = new WaypointActionDTO();
                            action2.setActionType(BusinessConstant.FINISH_TAKE_PHOTO_FLAG);
                            action2.setActionValue(actionGroupEndIndex);
                            action.setActionSort(Integer.parseInt(actionGroupId));
                            actionList1.add(action2);
                            uavWaypointDTO.setWaypointActionList(actionList1);
                        } else {
                            List<Element> actions = actionGroup.elements("action");
                            for (Element act : actions) {
                                WaypointActionDTO action = new WaypointActionDTO();
                                String actionActuatorFunc = act.elementText("actionActuatorFunc");
                                Element actionActuatorFuncParam = act.element("actionActuatorFuncParam");
                                if ("gimbalRotate".equals(actionActuatorFunc)) {
                                    String gimbalYawRotateEnable = actionActuatorFuncParam.elementText("gimbalYawRotateEnable");
                                    if ("1".equals(gimbalYawRotateEnable)) {
                                        action.setActionType(actionActuatorFunc + "_yaw");
                                    } else {
                                        action.setActionType(actionActuatorFunc);
                                    }
                                } else {
                                    action.setActionType(actionActuatorFunc);
                                }
                                SetActionParams.getAction(action, actionActuatorFuncParam);
                                actionList.add(action);
                            }
                        }
                    }
                    waypoint.setWaypointActionList(actionList);
                }
            }
        }
    }

    //赋值器
    public static String filedValid(String value, Boolean accurateImport) {
        if (StringUtils.isBlank(value)) {
            if (accurateImport) {
                return null;
            } else {
                throw new RenException("字段缺失，无法解析");
            }
        } else {
            return value;
        }
    }
}
