package com.liquidnet.service.platform.controller.kylin;


import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.facebody.model.v20191230.DetectPedestrianRequest;
import com.aliyuncs.facebody.model.v20191230.DetectPedestrianResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.KylinCameraDevicesVo;
import com.liquidnet.service.kylin.entity.KylinCamera;
import com.liquidnet.service.kylin.entity.KylinCameraRecord;
import com.liquidnet.service.kylin.mapper.KylinCameraMapper;
import com.liquidnet.service.kylin.mapper.KylinCameraRecordMapper;
import com.liquidnet.service.platform.utils.ViapiFileUtilAdvance;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 人流量排队检测摄像头表 前端控制器
 * </p>
 *
 * @author jiangxiulong
 * @since 2022-01-10
 */
@Api(tags = "视频计算")
@Slf4j
@RestController
@RequestMapping("/camera")
public class KylinCameraController {

    @Value("${liquidnet.aliyun.oss.accessKeyId}")
    private String accessKeyId;
    @Value("${liquidnet.aliyun.oss.accessKeySecret}")
    private String accessKeySecret;

    @Autowired
    private KylinCameraMapper cameraMapper;
    @Autowired
    private KylinCameraRecordMapper recordMapper;

    @PostMapping(value = "callBack", produces = "application/xml;charset=UTF-8")
    @ApiOperation("截图回调")
    public String callBack(
            @RequestBody String requestBody,
            @RequestParam(value = "siteType") Integer siteType,
            @RequestParam(value = "fieldId") String fieldId
    ) {
        try {
            log.info("接收截图回调请求：[siteType=[{}], fieldId=[{}], requestBody=[{}]",
                    siteType, fieldId, requestBody);
            // TODO: 2022/1/10 jxltodo 验签
            return "success";
        } catch (Exception e) {
            log.error("截图回调Exception：[msg={}, e={}]", e.getMessage(), e);
            return "error";
        }
    }

    @GetMapping("describeDevices")
    @ApiOperation("获取设备列表")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "query", dataType = "Integer", name = "pageNum", value = "页码"),
            @ApiImplicitParam(type = "query", dataType = "Integer", name = "pageSize", value = "数量")
    })
    public ResponseDto describeDevices(
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize
    ) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", accessKeyId, accessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("vs.cn-beijing.aliyuncs.com");
        request.setSysVersion("2018-12-12");
        request.setSysAction("DescribeDevices");
        // request.putQueryParameter("GroupId", "410751715516867255-cn-beijing");
        request.putQueryParameter("PageNum", String.valueOf(pageNum));
        request.putQueryParameter("PageSize", String.valueOf(pageSize));
        try {
            CommonResponse response = client.getCommonResponse(request);
            JsonNode devices = JsonUtils.fromJson(response.getData(), JsonNode.class).get("Devices");
            ObjectMapper configure = JsonUtils.OM().configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
            List<KylinCameraDevicesVo> kylinCameraDevicesVos = configure.readValue(JsonUtils.toJson(devices), new TypeReference<List<KylinCameraDevicesVo>>() {
            });

            for (KylinCameraDevicesVo devicesVo : kylinCameraDevicesVos) {
                String gbId = devicesVo.getGbId();
                KylinCamera kylinCamera = cameraMapper.selectOne(
                        Wrappers.lambdaQuery(KylinCamera.class)
                                .eq(KylinCamera::getGbId, gbId)
                );
                KylinCamera camera = KylinCamera.getNew();
                camera.setStatus(devicesVo.getStatus());
                JsonNode jsonNode = JsonUtils.fromJson(devicesVo.getDescription(), JsonNode.class);
                int siteType = jsonNode.get("siteType").asInt();
                String fieldId = jsonNode.get("fieldId").asText();
                camera.setSiteType(siteType);
                camera.setFieldId(fieldId);
                if (null == kylinCamera) {
                    camera.setCameraId(IDGenerator.nextSnowId());
                    camera.setGbId(gbId);
                    camera.setImgUrl("https://camera.zhengzai.tv/camera/live/".concat(gbId).concat(".jpg"));
                    cameraMapper.insert(camera);
                } else {
                    camera.setUpdatedAt(LocalDateTime.now());
                    cameraMapper.update(
                            camera,
                            Wrappers.lambdaUpdate(KylinCamera.class).eq(KylinCamera::getGbId, gbId)
                    );
                }

            }

            return ResponseDto.success();
        } catch (ClientException | JsonProcessingException e) {
            log.error("获取设备列表Exception：[msg={}, e={}]", e.getMessage(), e);
            return ResponseDto.failure();
        }
    }

    @GetMapping(value = "detectPedestrian")
    @ApiOperation("人体识别")
    public ResponseDto detectPedestrian() {
        long startTime1 = System.currentTimeMillis();
        List<KylinCamera> cameraList = cameraMapper.selectList(
                Wrappers.lambdaQuery(KylinCamera.class)
                        .eq(KylinCamera::getStatus, "on")
        );
        long startTime2 = System.currentTimeMillis();
        log.info("人体识别-查询设备列表->耗时:{}",(startTime2 - startTime1)+"毫秒");
        if (!CollectionUtils.isEmpty(cameraList)) {
            for (KylinCamera kylinCamera : cameraList) {
                try {
                    InputStream inputStream = ViapiFileUtilAdvance.buildInputStream(kylinCamera.getImgUrl());
                    ViapiFileUtilAdvance fileUtils = ViapiFileUtilAdvance.getInstance(accessKeyId, accessKeySecret, "cn-beijing");
                    String ossTempFileUrl = fileUtils.upload(inputStream);
                    long startTime3 = System.currentTimeMillis();
                    log.info("人体识别-upload->耗时:{}",(startTime3 - startTime2)+"毫秒");

                    DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKeyId, accessKeySecret);
                    IAcsClient client = new DefaultAcsClient(profile);
                    DetectPedestrianRequest request = new DetectPedestrianRequest();
                    request.setImageURL(ossTempFileUrl);
                    DetectPedestrianResponse response = client.getAcsResponse(request);
                    long startTime4 = System.currentTimeMillis();
                    log.info("人体识别-client->耗时:{}",(startTime4 - startTime3)+"毫秒");

                    List<DetectPedestrianResponse.Data.Element> elementList = response.getData().getElements();
                    if (!CollectionUtils.isEmpty(elementList)) {
                        long count = elementList.stream().filter(r -> r.getScore() > 0.5).count();
                        KylinCameraRecord cameraRecord = KylinCameraRecord.getNew();
                        cameraRecord.setCameraRecordId(IDGenerator.nextSnowId());
                        cameraRecord.setCameraId(kylinCamera.getCameraId());
                        cameraRecord.setPersonNum((int) count);
                        recordMapper.insert(cameraRecord);
                    }
                    long startTime5 = System.currentTimeMillis();
                    log.info("人体识别-MapperInsert->耗时:{}",(startTime5 - startTime4)+"毫秒");
                } catch (Exception e) {
                    log.error("获取设备列表Exception：[msg={}, e={}]", e.getMessage(), e);
                }
            }
        }
        return ResponseDto.success();
    }

}
