/**
  * 应用客户端统计首页
  *
  * @param appId 应用id
  */
 @RequestMapping("/index")
 public ModelAndView doIndex(
     HttpServletRequest request, HttpServletResponse response, Model model) {
   Long appId = NumberUtils.toLong(request.getParameter("appId"));
   if (appId == null || appId <= 0) {
     return new ModelAndView("");
   }
   AppDesc appDesc = appService.getByAppId(appId);
   model.addAttribute("appId", appId);
   model.addAttribute("appDesc", appDesc);
   model.addAttribute("tabTag", request.getParameter("tabTag"));
   model.addAttribute("type", request.getParameter("type"));
   model.addAttribute("startDate", request.getParameter("startDate"));
   model.addAttribute("endDate", request.getParameter("endDate"));
   model.addAttribute("exceptionStartDate", request.getParameter("exceptionStartDate"));
   model.addAttribute("exceptionEndDate", request.getParameter("exceptionEndDate"));
   model.addAttribute("valueDistriStartDate", request.getParameter("valueDistriStartDate"));
   model.addAttribute("valueDistriEndDate", request.getParameter("valueDistriEndDate"));
   model.addAttribute("costDistriStartDate", request.getParameter("costDistriStartDate"));
   model.addAttribute("costDistriEndDate", request.getParameter("costDistriEndDate"));
   model.addAttribute("clientIp", request.getParameter("clientIp"));
   model.addAttribute("pageNo", request.getParameter("pageNo"));
   model.addAttribute("firstCommand", request.getParameter("firstCommand"));
   model.addAttribute("timeDimensionality", request.getParameter("timeDimensionality"));
   return new ModelAndView("client/appClientIndex");
 }
  /** 应用客户端值分布相关 */
  @RequestMapping("/valueDistribute")
  public ModelAndView doValueDistribute(
      HttpServletRequest request, HttpServletResponse response, Model model) throws ParseException {
    // 1.1 应用信息
    Long appId = NumberUtils.toLong(request.getParameter("appId"));
    if (appId <= 0) {
      return new ModelAndView("");
    }
    AppDesc appDesc = appService.getByAppId(appId);
    model.addAttribute("appDesc", appDesc);

    // 1.2 时间格式转换
    TimeBetween timeBetween = new TimeBetween();
    try {
      timeBetween = fillWithValueDistriTime(request, model);
    } catch (ParseException e) {
      logger.error(e.getMessage(), e);
    }
    long startTime = timeBetween.getStartTime();
    long endTime = timeBetween.getEndTime();

    // 值分布列表
    List<AppClientValueDistriSimple> appClientValueDistriSimpleList =
        clientReportValueDistriServiceV2.getAppValueDistriList(appId, startTime, endTime);
    model.addAttribute("appClientValueDistriSimpleList", appClientValueDistriSimpleList);

    // 值分布json
    model.addAttribute(
        "appClientValueDistriSimpleListJson",
        JSONObject.toJSONString(appClientValueDistriSimpleList));

    return new ModelAndView("client/clientValueDistribute");
  }
  /** 客户端异常查询 */
  @RequestMapping("/exception")
  public ModelAndView doException(
      HttpServletRequest request, HttpServletResponse response, Model model) {
    // 1.1 应用信息
    Long appId = NumberUtils.toLong(request.getParameter("appId"));
    if (appId <= 0) {
      return new ModelAndView("");
    }
    AppDesc appDesc = appService.getByAppId(appId);
    model.addAttribute("appDesc", appDesc);

    // 1.2 异常类型
    int type = NumberUtil.toInt(request.getParameter("type"));
    model.addAttribute("type", type);

    // 1.3 客户端ip
    String clientIp = request.getParameter("clientIp");
    model.addAttribute("clientIp", clientIp);

    // 1.4 日期格式转换
    TimeBetween timeBetween = new TimeBetween();
    try {
      timeBetween = fillWithClientExceptionTime(request, model);
    } catch (ParseException e) {
      logger.error(e.getMessage(), e);
    }

    // 2. 分页查询异常
    int totalCount =
        clientReportExceptionService.getAppExceptionCount(
            appId, timeBetween.getStartTime(), timeBetween.getEndTime(), type, clientIp);
    int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1);
    int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 10);
    Page page = new Page(pageNo, pageSize, totalCount);
    model.addAttribute("page", page);

    List<AppClientExceptionStat> appClientExceptionList =
        clientReportExceptionService.getAppExceptionList(
            appId, timeBetween.getStartTime(), timeBetween.getEndTime(), type, clientIp, page);
    model.addAttribute("appClientExceptionList", appClientExceptionList);

    return new ModelAndView("client/clientException");
  }
  /** 应用客户端耗时统计 */
  @RequestMapping("/costDistribute")
  public ModelAndView doCostDistribute(
      HttpServletRequest request, HttpServletResponse response, Model model) {
    // 1.应用信息
    Long appId = NumberUtils.toLong(request.getParameter("appId"));
    if (appId <= 0) {
      return new ModelAndView("");
    }
    AppDesc appDesc = appService.getByAppId(appId);
    model.addAttribute("appDesc", appDesc);
    model.addAttribute("appId", appId);

    // 2.获取时间区间
    TimeBetween timeBetween = new TimeBetween();
    try {
      timeBetween = fillWithCostDateFormat(request, model);
    } catch (ParseException e) {
      logger.error(e.getMessage(), e);
    }
    long startTime = timeBetween.getStartTime();
    long endTime = timeBetween.getEndTime();
    Date startDate = timeBetween.getStartDate();

    // 3.所有命令和第一个命令
    List<String> allCommands =
        clientReportCostDistriService.getAppDistinctCommand(appId, startTime, endTime);
    model.addAttribute("allCommands", allCommands);

    // 4.所有客户端和实例对应关系
    List<AppInstanceClientRelation> appInstanceClientRelationList =
        appInstanceClientRelationService.getAppInstanceClientRelationList(appId, startDate);
    model.addAttribute("appInstanceClientRelationList", appInstanceClientRelationList);

    String firstCommand = request.getParameter("firstCommand");
    if (StringUtils.isBlank(firstCommand) && CollectionUtils.isNotEmpty(allCommands)) {
      firstCommand = allCommands.get(0);
      model.addAttribute("firstCommand", firstCommand);
    } else {
      model.addAttribute("firstCommand", firstCommand);
    }

    // 5.1 应用下客户端和实例的全局耗时统计列表
    List<AppClientCostTimeTotalStat> appChartStatList =
        clientReportCostDistriService.getAppClientCommandTotalStat(
            appId, firstCommand, startTime, endTime);
    Map<String, Object> resultMap = new HashMap<String, Object>();

    // 5.2 简化字段
    List<Map<String, Object>> app = new ArrayList<Map<String, Object>>();
    for (AppClientCostTimeTotalStat appClientCostTimeTotalStat : appChartStatList) {
      Map<String, Object> map = new HashMap<String, Object>();
      map.put("timeStamp", appClientCostTimeTotalStat.getTimeStamp());
      map.put("count", appClientCostTimeTotalStat.getTotalCount());
      map.put("mean", appClientCostTimeTotalStat.getMean());
      map.put("median", appClientCostTimeTotalStat.getMedian());
      map.put("max90", appClientCostTimeTotalStat.getNinetyPercentMax());
      map.put("max99", appClientCostTimeTotalStat.getNinetyNinePercentMax());
      map.put("max100", appClientCostTimeTotalStat.getHundredMax());
      map.put(
          "maxInst",
          appClientCostTimeTotalStat.getMaxInstanceHost()
              + ":"
              + appClientCostTimeTotalStat.getMaxInstancePort());
      map.put("maxClient", appClientCostTimeTotalStat.getMaxClientIp());
      app.add(map);
    }

    resultMap.put("app", app);
    model.addAttribute("appChartStatListJson", JSONObject.toJSONString(resultMap));

    return new ModelAndView("client/clientCostDistribute");
  }