package com.tofly.analyse.controller;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.supermap.analyst.networkanalyst.FacilityAnalyst;
import com.supermap.analyst.networkanalyst.TransportationAnalyst;
import com.supermap.analyst.networkanalyst.TransportationAnalystResult;
import com.supermap.data.*;
import com.tofly.analyse.entity.FlowDirAnalysis;
import com.tofly.analyse.entity.FlowDirAnalysisDto;
import com.tofly.analyse.entity.LayerFiledConfig;
import com.tofly.analyse.entity.PathAnalysisDto;
import com.tofly.analyse.entity.analyse.BurstResult;
import com.tofly.analyse.entity.analyse.FlowDirAnalysisResult;
import com.tofly.analyse.entity.analyse.Network;
import com.tofly.analyse.mapper.AnalysisMapper;
import com.tofly.analyse.service.LayerFiledConfigService;
import com.tofly.analyse.util.analysis.*;
import com.tofly.common.core.entity.ResultRespone;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/analysis")
@Api(tags = "管网分析")
public class AnalysisController {

    /**
     * 连通性分析
     */
    @Autowired
    private ConnectionAnalysis connectionAnalysis;

    /**
     * 爆管分析
     */
    @Autowired
    private BurstPipeAnalysis burstPipeAnalysis;

    /**
     * 路径分析
     */
    @Autowired
    private PathAnalysis pathAnalysis;

    /**
     * 追踪分析
     */
    @Autowired
    private FormTraceAnalyst formTraceAnalyst;

    /**
     * 关阀分析
     */
    @Autowired
    private FormShutoffValveAnalyst formShutoffValveAnalyst;

    @Autowired
    private AnalysisMapper analysisMapper;

    @Autowired
    private LayerFiledConfigService layerFiledConfigService;

    @Autowired
    private AnalystConfig facilityAnalystConfig;
    
    @Autowired
    private DatasourceConfig datasourceConfig;

    /**
     * @param dataSetName 分析数据集名称
     * @param sid      分析管线
     * @param useBarrier  是否启用障碍
     */

    @ApiOperation(value = "连通性分析")
    @GetMapping("/connectionAnalysis")
    public ResultRespone connectionAnalysis(
            @ApiParam(value = "分析数据集名称", name = "dataSetName", required = true) String dataSetName,
            @ApiParam(value = "分析管线sid）", name = "sid", required = true) String sid,
            @ApiParam(value = "是否启用障碍", name = "useBarrier") boolean useBarrier
    ) {

        Map<String, Object> resMap = new HashMap<String, Object>();
        try {
            LayerFiledConfig layfiledConfig = layerFiledConfigService.getOne(Wrappers.<LayerFiledConfig>query().lambda().eq(LayerFiledConfig::getLayerName, dataSetName));
            if(layfiledConfig!=null){
                resMap = connectionAnalysis.connectionAnalysis2(sid, dataSetName,layfiledConfig, useBarrier,null);
            }else{
                throw new Exception("未找到匹配的图层配置信息数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultRespone.failed(e.getMessage());
        }
        return ResultRespone.success(resMap);
    }



    @ApiOperation(value = "爆管分析/二次关阀分析")
    @GetMapping("/burstPipeAnalysis")
    public ResultRespone burstPipeAnalysis(
            @ApiParam(value = "分析数据集名称", name = "dataSetName", required = true) String dataSetName,
            @ApiParam(value = "模拟破损的管线SID", name = "sid", required = true) String sid,
            @ApiParam(value = "设置障碍阀门(SID)集合,已逗号隔开",required = false) String  sids
    ) {
        BurstResult burstResult=new BurstResult();
        Workspace workspace = new Workspace();
        Dataset dataset = null;
        Datasource datasource = null;
        try {
            datasource = datasourceConfig.getDatasource(workspace);

            String strLayerCode = dataSetName.substring(dataSetName.indexOf("_") + 1, dataSetName.indexOf("_") + 5);
            String strPNetworkName = "NETWORK_" + strLayerCode + "_2D";

            if (datasource.getDatasets().contains(strPNetworkName) == false) {
                throw new Exception("未找到匹配的管网二维网络数据集。");
            }
            LayerFiledConfig layfiledConfig = layerFiledConfigService.getOne(Wrappers.<LayerFiledConfig>query().lambda().eq(LayerFiledConfig::getLayerName, dataSetName));
            if(layfiledConfig!=null){
                dataset = datasource.getDatasets().get(strPNetworkName);
                DatasetVector vecPNetwork = (DatasetVector) dataset;
                List<Integer> sourceIds = new ArrayList<>();
                //查出所有源点
                DatasetVector childDataset = vecPNetwork.getChildDataset();
                Recordset nodeRecord = childDataset.query("NODETYPE=1", CursorType.STATIC);
                nodeRecord.moveFirst();
                nodeRecord.moveFirst();
                while (nodeRecord.isEOF() == false) {
                    int nodeId = nodeRecord.getInt32("SmNodeID");
                    sourceIds.add(nodeId);
                    nodeRecord.moveNext();
                }
                nodeRecord.close();
                nodeRecord.dispose();
                FacilityAnalyst facilityAnalyst = facilityAnalystConfig.loadModel(vecPNetwork, false,layfiledConfig);

                burstResult = burstPipeAnalysis.BurstPipeAnalysis(sid,facilityAnalyst,layfiledConfig,sourceIds,sids);

            }else{
                throw new Exception("未找到匹配的图层配置信息数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultRespone.failed(e.getMessage());
        } finally {
            if (dataset.isOpen()) {
                dataset.close();
            }
            if (datasource.isOpened())
                datasource.close();
            workspace.close();
        }
        return ResultRespone.success(burstResult);
    }


    @ApiOperation(value = "路径分析")
    @PostMapping("/pathAnalysis")
    public ResultRespone PathAnalysis(
            @RequestBody PathAnalysisDto pathAnalysisDto
    ) {

        Map<String, List<Object>> resMap = new HashMap<String, List<Object>>();
        List<Object> tracedNode = new ArrayList<Object>();
        List<Object> tracedEdges = new ArrayList<Object>();
        Workspace workspace = new Workspace();
        Dataset dataset = null;
        Datasource datasource = null;
        try {
            datasource = datasourceConfig.getDatasource(workspace);

            String dataSetName = pathAnalysisDto.getDatasetName();
            String __strLayerCode = dataSetName.substring(dataSetName.indexOf("_") + 1, dataSetName.indexOf("_") + 5);
            String __strPNetworkName = "NETWORK_" + __strLayerCode + "_2D";
            if (datasource.getDatasets().contains(__strPNetworkName) == false) {
                throw new Exception("未找到匹配的管网二维网络数据集。");
            }
            LayerFiledConfig layfiledConfig = layerFiledConfigService.getOne(Wrappers.<LayerFiledConfig>query().lambda().eq(LayerFiledConfig::getLayerName, dataSetName));
            if(layfiledConfig!=null){
                dataset = datasource.getDatasets().get(__strPNetworkName);
                DatasetVector __vecPNetwork = (DatasetVector) dataset;
                List<String> sids = pathAnalysisDto.getSids();

                StringBuffer stringBuffer = new StringBuffer();
                for (int i = 0; i < sids.size(); i++) {
                    if (i == sids.size() - 1) {
                        stringBuffer.append(" '" + sids.get(i) + "' ");
                    } else {
                        stringBuffer.append(" '" + sids.get(i) + "', ");
                    }
                }
                String paramStr = layfiledConfig.getNo()+" in ( " + stringBuffer.toString() + " )";
                Recordset __recNode = __vecPNetwork.query(paramStr, CursorType.STATIC);
                List<Integer> param = new ArrayList<>();
                __recNode.moveFirst();
                while (__recNode.isEOF() == false) {
                    int __iNode1 = __recNode.getInt32("SmFNode");
                    int __iNode2 = __recNode.getInt32("SmTNode");
                    param.add(__iNode1);
                    param.add(__iNode2);
                    __recNode.moveNext();
                }
                __recNode.close();
                __recNode.dispose();

                TransportationAnalyst m_transAnalyst = facilityAnalystConfig.loadModel(__vecPNetwork);

                TransportationAnalystResult __taResult = pathAnalysis.PathAnalysis(m_transAnalyst, param);
                System.out.println(__taResult);
                int[][] edges = __taResult.getEdges();
                if (edges != null && edges.length > 0) {
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < edges.length; i++) {
                        for (int j = 0; j < edges[i].length; j++) {
                            sb.append(edges[i][j] + ",");
                        }
                    }
                    String strEdgeIds = sb.toString().substring(0, sb.toString().length() - 1);

                    String params = "(" + m_transAnalyst.getAnalystSetting().getEdgeIDField() +
                            " in (" + strEdgeIds + ")" + " )";
                    List<Network> networkData = analysisMapper.getNetworkData(m_transAnalyst.getAnalystSetting().getNetworkDataset().getName(), m_transAnalyst.getAnalystSetting().getNetworkDataset().getName() + "_NODE", params);
                    for (Network d : networkData) {
                        tracedEdges.add(d.getSId());
                        if (tracedNode.contains(d.getFSid()) == false) {
                            tracedNode.add(d.getFSid());
                        }
                        if (tracedNode.contains(d.getTSid()) == false) {
                            tracedNode.add(d.getTSid());
                        }
                    }
                    resMap.put("tracedEdges", tracedEdges);
                    resMap.put("tracedNode", tracedNode);
                    return ResultRespone.success(resMap);
                } else {
                    return ResultRespone.failed();
                }
            }else{
                throw new Exception("未找到匹配的图层配置信息数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultRespone.failed(e.getMessage());
        } finally {
            if (dataset.isOpen()) {
                dataset.close();
            }
            if (datasource.isOpened())
                datasource.close();
            workspace.close();
        }
    }

    @ApiOperation(value = "关阀分析")
    @GetMapping("/formShutoffAnalysis")
    public ResultRespone formShutAnalysis(
            @ApiParam(value = "分析数据集名称", name = "dataSetName", required = true) String dataSetName,
            @ApiParam(value = "阀门(SID)集合,已逗号隔开", name = "sid", required = true) String sid
    ) {
        BurstResult burstResult=new BurstResult();
        Workspace workspace = new Workspace();
        Dataset dataset = null;
        Datasource datasource = null;
        try {
            datasource = datasourceConfig.getDatasource(workspace);
            String strLayerCode = dataSetName.substring(dataSetName.indexOf("_") + 1, dataSetName.indexOf("_") + 5);
            String strPNetworkName = "NETWORK_" + strLayerCode + "_2D";

            if (datasource.getDatasets().contains(strPNetworkName) == false) {
                throw new Exception("未找到匹配的管网二维网络数据集。");
            }
            LayerFiledConfig layfiledConfig = layerFiledConfigService.getOne(Wrappers.<LayerFiledConfig>query().lambda().eq(LayerFiledConfig::getLayerName, dataSetName));
            if(layfiledConfig!=null){
                dataset = datasource.getDatasets().get(strPNetworkName);
                DatasetVector vecPNetwork = (DatasetVector) dataset;
                List<Integer> sourceIds = new ArrayList<>();
                //查出所有源点
                DatasetVector childDataset = vecPNetwork.getChildDataset();
                Recordset nodeRecord = childDataset.query("NODETYPE=1", CursorType.STATIC);
                nodeRecord.moveFirst();
                nodeRecord.moveFirst();
                while (nodeRecord.isEOF() == false) {
                    int nodeId = nodeRecord.getInt32("SmNodeID");
                    sourceIds.add(nodeId);
                    nodeRecord.moveNext();
                }
                nodeRecord.close();
                nodeRecord.dispose();
                FacilityAnalyst facilityAnalyst = facilityAnalystConfig.loadModel(vecPNetwork, false,layfiledConfig);
                burstResult = formShutoffValveAnalyst.formShutoffValveAnalyst(facilityAnalyst, layfiledConfig, sid, sourceIds);
            }else{
                throw new Exception("未找到匹配的图层配置信息数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultRespone.failed(e.getMessage());
        } finally {
            if (dataset.isOpen()) {
                dataset.close();
            }
            if (datasource.isOpened())
                datasource.close();
            workspace.close();
        }
        return ResultRespone.success(burstResult);
    }


    @ApiOperation(value = "流向分析")
    @PostMapping("/flowDirAnalysis")
    public ResultRespone flowDirAnalysis(@RequestBody FlowDirAnalysisDto flowDirAnalysisDto) {
        List<FlowDirAnalysisResult> flowDirAnalysisResults = new ArrayList<>();
        Workspace workspace = new Workspace();
        Datasource datasource = null;
        try {
            datasource = datasourceConfig.getDatasource(workspace);
            List<FlowDirAnalysis> flowDirAnalyses = flowDirAnalysisDto.getFlowDirAnalyses();
            if (CollUtil.isNotEmpty(flowDirAnalyses)) {
                //按数据集分类
                Map<String, List<FlowDirAnalysis>> collect = flowDirAnalyses.stream().collect(Collectors.groupingBy(FlowDirAnalysis::getDatasetName));
                Datasource finalDatasource = datasource;
                collect.forEach((k, v) -> {
                    LayerFiledConfig layfiledConfig = layerFiledConfigService.getOne(Wrappers.<LayerFiledConfig>query().lambda().eq(LayerFiledConfig::getLayerName, k));
                    if(layfiledConfig!=null){
                        StringBuffer stringBuffer = new StringBuffer();
                        for (int i = 0; i < v.size(); i++) {
                            if (i == v.size() - 1) {
                                stringBuffer.append(" '" + v.get(i).getSid() + "' ");
                            } else {
                                stringBuffer.append(" '" + v.get(i).getSid() + "', ");
                            }
                        }
                        String __strLayerCode = k.substring(k.indexOf("_") + 1, k.indexOf("_") + 5);

                        String networkName = "NETWORK_" + __strLayerCode + "_2D";
                        if (finalDatasource.getDatasets().contains(networkName) == false) {
                            try {
                                throw new Exception("未找到匹配的管网二维网络数据集");
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }
                        Dataset dataset = finalDatasource.getDatasets().get(networkName);
                        DatasetVector datasetVector = (DatasetVector) dataset;
                        Recordset recordset = datasetVector.query(layfiledConfig.getNo()+" in (" + stringBuffer.toString() + ")", CursorType.STATIC);
                        recordset.moveFirst();
                        while (recordset.isEOF() == false) {
                            FlowDirAnalysisResult flowDirAnalysisResult = new FlowDirAnalysisResult();
                            flowDirAnalysisResult.setSid(recordset.getString(layfiledConfig.getNo()));
                            flowDirAnalysisResult.setDatasetName(k);
                            flowDirAnalysisResult.setFlowDir(recordset.getString(layfiledConfig.getDir()));
                            flowDirAnalysisResults.add(flowDirAnalysisResult);
                            recordset.moveNext();
                        }
                        recordset.close();
                        recordset.dispose();

                        if (dataset.isOpen()) {
                            dataset.close();
                        }
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultRespone.failed(e.getMessage());
        } finally {
            if (datasource.isOpened())
                datasource.close();
            workspace.close();
        }
        return ResultRespone.success(flowDirAnalysisResults);
    }








}