content: package com.genersoft.iot.vmp.streamPush.enent;
  
  import com.alibaba.excel.context.AnalysisContext;
  import com.alibaba.excel.event.AnalysisEventListener;
  import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
  import com.genersoft.iot.vmp.streamPush.bean.StreamPushExcelDto;
  import com.genersoft.iot.vmp.streamPush.service.IStreamPushService;
  import com.genersoft.iot.vmp.utils.DateUtil;
  import com.google.common.collect.BiMap;
  import com.google.common.collect.HashBiMap;
  import org.springframework.util.ObjectUtils;
  
  import java.util.*;
  
  public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPushExcelDto> {
  
      /**
       * 错误数据的回调，用于将错误数据发送给页面
       */
      private final ErrorDataHandler errorDataHandler;
  
      /**
       * 推流的业务类用于存储数据
       */
      private final IStreamPushService pushService;
  
      /**
       * 默认流媒体节点ID
       */
      private final String defaultMediaServerId;
  
      /**
       * 用于存储更具APP+Stream过滤后的数据，可以直接存入stream_push表与gb_stream表
       */
      private final Map<String, StreamPush> streamPushItemForSave = new HashMap<>();
  
      /**
       * 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应，全局判断APP+Stream->国标ID是否存在不对应
       */
      private final BiMap<String,String> gBMap = HashBiMap.create();
  
      /**
       * 用于存储APP+Stream-> 在数据库中的数据
       */
      private final BiMap<String,String> pushMapInDb = HashBiMap.create();
  
      /**
       * 记录错误的APP+Stream
       */
      private final List<String> errorStreamList = new ArrayList<>();
  
  
      /**
       * 记录错误的国标ID
       */
      private final List<String> errorInfoList = new ArrayList<>();
  
      /**
       * 读取数量计数器
       */
      private int loadedSize = 0;
  
      public StreamPushUploadFileHandler(IStreamPushService pushService, String defaultMediaServerId, ErrorDataHandler errorDataHandler) {
          this.pushService = pushService;
          this.defaultMediaServerId = defaultMediaServerId;
          this.errorDataHandler = errorDataHandler;
          // 获取数据库已有的数据，已经存在的则忽略
          List<String> allAppAndStreams = pushService.getAllAppAndStream();
          if (!allAppAndStreams.isEmpty()) {
              for (String allAppAndStream : allAppAndStreams) {
                  pushMapInDb.put(allAppAndStream, allAppAndStream);
              }
          }
      }
  
      public interface ErrorDataHandler{
          void handle(List<String> streams, List<String> gbId);
      }
  
      @Override
      public void invoke(StreamPushExcelDto streamPushExcelDto, AnalysisContext analysisContext) {
          if (ObjectUtils.isEmpty(streamPushExcelDto.getApp())
                  || ObjectUtils.isEmpty(streamPushExcelDto.getStream())
                  || ObjectUtils.isEmpty(streamPushExcelDto.getGbDeviceId())) {
              return;
          }
          Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
  
          if (gBMap.get(streamPushExcelDto.getApp() + streamPushExcelDto.getStream()) == null) {
              try {
                  gBMap.put(streamPushExcelDto.getApp() + streamPushExcelDto.getStream(), streamPushExcelDto.getGbDeviceId());
              }catch (IllegalArgumentException e) {
                  errorInfoList.add("行：" + rowIndex + ", " + streamPushExcelDto.getGbDeviceId() + " 国标ID重复使用");
                  return;
              }
          }else {
              if (!gBMap.get(streamPushExcelDto.getApp() + streamPushExcelDto.getStream()).equals(streamPushExcelDto.getGbDeviceId())) {
                  errorInfoList.add("行：" + rowIndex + ", " + streamPushExcelDto.getGbDeviceId() + " 同样的应用名和流ID使用了不同的国标ID");
                  return;
              }
          }
  
          StreamPush streamPush = new StreamPush();
          streamPush.setApp(streamPushExcelDto.getApp());
          streamPush.setStream(streamPushExcelDto.getStream());
          streamPush.setGbDeviceId(streamPushExcelDto.getGbDeviceId());
          streamPush.setGbStatus(streamPushExcelDto.isStatus()?"ON":"OFF");
          streamPush.setCreateTime(DateUtil.getNow());
          streamPush.setMediaServerId(defaultMediaServerId);
          streamPush.setGbName(streamPushExcelDto.getName());
          streamPush.setGbLongitude(streamPushExcelDto.getLongitude());
          streamPush.setGbLatitude(streamPushExcelDto.getLatitude());
          streamPush.setUpdateTime(DateUtil.getNow());
          streamPushItemForSave.put(streamPush.getApp() + streamPush.getStream(), streamPush);
  
          loadedSize ++;
          if (loadedSize > 1000) {
              saveData();
              streamPushItemForSave.clear();
              loadedSize = 0;
          }
  
      }
  
      @Override
      public void doAfterAllAnalysed(AnalysisContext analysisContext) {
          // 这里也要保存数据，确保最后遗留的数据也存储到数据库
          saveData();
          streamPushItemForSave.clear();
          gBMap.clear();
          errorDataHandler.handle(errorStreamList, errorInfoList);
      }
  
      private void saveData(){
          if (!streamPushItemForSave.isEmpty()) {
              // 向数据库查询是否存在重复的app
              pushService.batchAdd(new ArrayList<>(streamPushItemForSave.values()));
          }
      }
  }
  