package com.multictrl.modules.business.service.impl;

import cn.hutool.json.JSONObject;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.constant.ExposureValue;
import com.multictrl.common.exception.ErrorCode;
import com.multictrl.common.exception.RenException;
import com.multictrl.common.utils.CacheUtils;
import com.multictrl.modules.business.dto.camera.*;
import com.multictrl.modules.business.service.CameraService;
import com.multictrl.modules.business.service.DJIBaseService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 云台相机控制
 *
 * @author Sdy
 * @since 1.0.0 2026/4/28
 */
@Service
@RequiredArgsConstructor
public class CameraServiceImpl implements CameraService {
    private final DJIBaseService djiBaseService;

    @Override
    public String frameZoom(String dockSn, FrameZoom frameZoom) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("height", frameZoom.getHeight());
        data.set("width", frameZoom.getWidth());
        data.set("x", frameZoom.getX());
        data.set("y", frameZoom.getY());
        data.set("locked", false);

        return djiBaseService.executeAndReturnResult(dockSn, "camera_frame_zoom", data);
    }

    @Override
    public String modeSwitch(String dockSn, Integer mode) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("camera_mode", mode);
        return djiBaseService.executeAndReturnResult(dockSn, "camera_mode_switch", data);
    }

    @Override
    public String photoVideo(String dockSn, String method) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        return djiBaseService.executeAndReturnResult(dockSn, method, data);
    }

    @Override
    public String screenDrag(String dockSn, ScreenDrag screenDrag) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("locked", false);
        data.set("pitch_speed", screenDrag.getPitchSpeed());
        data.set("yaw_speed", screenDrag.getYawSpeed());
        return djiBaseService.executeAndReturnResult(dockSn, "camera_screen_drag", data);
    }

    @Override
    public String aim(String dockSn, AimParam aimParam) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("locked", false);
        data.set("x", aimParam.getX());
        data.set("y", aimParam.getY());
        return djiBaseService.executeAndReturnResult(dockSn, "camera_aim", data);
    }

    @Override
    public String focalLengthSet(String dockSn, FocalLengthSet focalLengthSet) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("camera_type", focalLengthSet.getCameraType());
        data.set("zoom_factor", focalLengthSet.getZoomFactor());
        return djiBaseService.executeAndReturnResult(dockSn, "camera_focal_length_set", data);
    }

    @Override
    public String gimbalReset(String dockSn, Integer mode) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("reset_mode", mode);
        return djiBaseService.executeAndReturnResult(dockSn, "gimbal_reset", data);
    }

    @Override
    public String lookAt(String dockSn, LookAt lookAt) {
        Double dockEllipsoidHeight = djiBaseService.getDockEllipsoidHeight(dockSn);
        if (dockEllipsoidHeight == null) {
            throw new RenException(ErrorCode.DOCK_OSD_NOT_EXIST, "未获取机场椭球高");
        }
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("locked", true);
        data.set("latitude", lookAt.getLatitude());
        data.set("longitude", lookAt.getLongitude());
        float targetHeight = (float) (dockEllipsoidHeight + lookAt.getHeight());
        BigDecimal bd = new BigDecimal(String.valueOf(targetHeight));
        data.set("height", bd.setScale(1, RoundingMode.HALF_UP).floatValue());
        return djiBaseService.executeAndReturnResult(dockSn, "camera_look_at", data);
    }

    @Override
    public String screenSplit(String dockSn, Integer enable) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("enable", enable == 1);
        return djiBaseService.executeAndReturnResult(dockSn, "camera_screen_split", data);
    }

    @Override
    public String storageSet(String dockSn, StorageSet storageSet) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        if ("photo_storage_set".equals(storageSet.getType())) {
            data.set("photo_storage_settings", storageSet.getSetList());
        } else {
            data.set("video_storage_settings", storageSet.getSetList());
        }
        return djiBaseService.executeAndReturnResult(dockSn, storageSet.getType(), data);
    }

    @Override
    public String exposureModeSet(String dockSn, Integer mode) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("exposure_mode", mode);
        return djiBaseService.executeAndReturnResult(dockSn, "camera_exposure_mode_set", data);
    }

    @Override
    public String exposureSet(String dockSn, String value) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("exposure_value", value);
        return djiBaseService.executeAndReturnResult(dockSn, "camera_exposure_set", data);
    }

    @Override
    public String focusModeSet(String dockSn, Integer mode) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("focus_mode", mode);
        return djiBaseService.executeAndReturnResult(dockSn, "camera_focus_mode_set", data);
    }

    @Override
    public String focusSet(String dockSn, Integer value) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("focus_value", value);
        return djiBaseService.executeAndReturnResult(dockSn, "camera_focus_value_set", data);
    }

    @Override
    public String pointFocusAction(String dockSn, PointFocusAction pointFocusAction) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        Object videoType = CacheUtils.get(BusinessConstant.UAV_VIDEO_TYPE + dockSn);
        data.set("camera_type", Objects.requireNonNullElse(videoType, "wide"));
        data.set("x", pointFocusAction.getX());
        data.set("y", pointFocusAction.getY());
        return djiBaseService.executeAndReturnResult(dockSn, "camera_point_focus_action", data);
    }

    @Override
    public String irMeteringPointSet(String dockSn, IrMeteringPointSet irMeteringPointSet) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("x", irMeteringPointSet.getX());
        data.set("y", irMeteringPointSet.getY());
        return djiBaseService.executeAndReturnResult(dockSn, "ir_metering_point_set", data);
    }

    @Override
    public String irMeteringAreaSet(String dockSn, IrMeteringAreaSet irMeteringAreaSet) {
        JSONObject data = getDataIncludePayloadIndex(dockSn);
        data.set("x", irMeteringAreaSet.getX());
        data.set("y", irMeteringAreaSet.getY());
        data.set("width", irMeteringAreaSet.getWidth());
        data.set("height", irMeteringAreaSet.getHeight());
        return djiBaseService.executeAndReturnResult(dockSn, "ir_metering_area_set", data);
    }

    @Override
    public List<JSONObject> getExposureValue() {
        List<JSONObject> list = new ArrayList<>();
        for (ExposureValue value : ExposureValue.values()) {
            JSONObject object = new JSONObject();
            object.set("code", value.getCode());
            object.set("desc", value.getDesc());
            list.add(object);
        }
        return list;
    }

    //获取包含payload_index的data
    private JSONObject getDataIncludePayloadIndex(String dockSn) {
        JSONObject data = new JSONObject();
        Object cameraIndex = CacheUtils.get(BusinessConstant.UAV_CAMERA_INDEX + dockSn);
        if (cameraIndex != null) {
            data.set("payload_index", cameraIndex);
        } else {
            throw new RenException(ErrorCode.UAV_CAMERA_INDEX_NOT_EXIST);
        }
        return data;
    }
}
