class VulnerabilityService implements Constants {

	@SuppressWarnings({ "unchecked" })
	public Map<String, Object> getVulnerabilitySummary(String assetGroup, String reqSeverity) throws ServiceException {

		List<String> vulnTargetTypes = getVulnTargetTypes(assetGroup);

		Map<String, Object> vulnerabilitySummary = new HashMap<>();
		List<Map<String, Object>> severityInfo = new ArrayList<>();
		if (vulnTargetTypes.isEmpty()) {
			for (int i = 3; i <= 5; i++) {
				Map<String, Object> sevInfo = new HashMap<>();
				sevInfo.put(SEVERITY, "S" + i);
				sevInfo.put(SEVEITY_LEVEL, i);
				sevInfo.put(COUNT, 0);
				sevInfo.put("appCount", 0);
				sevInfo.put("hostCount", 0);
				sevInfo.put(UNIQUE_VULN_COUNT, 0);
				sevInfo.put(VULN_COUNT, 0);
				severityInfo.add(sevInfo);
			}
			vulnerabilitySummary.put(SEV_INFO, severityInfo);
			vulnerabilitySummary.put(VULNEREBILITIES, 0);
			vulnerabilitySummary.put("hosts", 0);
			vulnerabilitySummary.put(TOTAL_VULN_ASSETS, 0);
			vulnerabilitySummary.put("compliantpercent", 100);
			vulnerabilitySummary.put("assetsWithVulns", 0);
			return vulnerabilitySummary;

		} else {

			Map<String, Map<String, Object>> queryResults = new HashMap<>();

			long totalQualysCount = 0;
			long vulnerableAssetCount = 0;
			long totalAssetCount = 0;

			ExecutorService executor = Executors.newFixedThreadPool(3);
			executor.execute(() -> {
				queryResults.put("uniqueHost", vulnerabilityRepository.getUniqueHost(assetGroup, reqSeverity));
			});
			executor.execute(() -> {
				queryResults.put("VulnInfo", vulnerabilityRepository.getVulnInfo(assetGroup, reqSeverity));

			});
			executor.execute(() -> {
				queryResults.put("uniqueApp", vulnerabilityRepository.getUniqueApp(assetGroup));
			});
			executor.shutdown();
			while (!executor.isTerminated()) {
			}

			Map<String, Object> uniqueHost = queryResults.get("uniqueHost");
			Map<String, Object> vulnInfo = queryResults.get("VulnInfo");
			Map<String, Object> uniqueApp = queryResults.get("uniqueApp");

			List<String> sevList = Arrays.asList(reqSeverity.split(","));
			List<String> summarySevList = Arrays.asList(vulnSummarySeverity.split(","));
			Map<String, Object> sevVulnInfo;
			Map<String, Object> vulnInfoMap;

			List<Map<String, Object>> sevVulnfoList = new ArrayList<>();
			vulnerabilitySummary.put(SEV_INFO, sevVulnfoList);

			for (String sev : sevList) {
				sevVulnInfo = new HashMap<>();
				sevVulnInfo.put(SEVEITY_LEVEL, Integer.valueOf(sev));
				sevVulnInfo.put(SEVERITY, "S" + sev);
				sevVulnInfo.put("hostCount", uniqueHost.get(sev) == null ? 0 : uniqueHost.get(sev));
				if (summarySevList.contains(sev)) {
					vulnerableAssetCount += Long.valueOf(sevVulnInfo.get("hostCount").toString());
				}
				vulnInfoMap = (Map<String, Object>) vulnInfo.get(sev);
				if (vulnInfoMap != null) {
					sevVulnInfo.put(COUNT, vulnInfoMap.get(VULN_COUNT));
					sevVulnInfo.put(VULN_COUNT, vulnInfoMap.get(VULN_COUNT));
					sevVulnInfo.put(UNIQUE_VULN_COUNT, vulnInfoMap.get(UNIQUE_VULN_COUNT));
				} else {
					sevVulnInfo.put(COUNT, 0);
					sevVulnInfo.put(VULN_COUNT, 0);
					sevVulnInfo.put(UNIQUE_VULN_COUNT, 0);
				}
				sevVulnInfo.put("appCount", uniqueApp.get(sev) == null ? 0 : uniqueApp.get(sev));
				sevVulnfoList.add(sevVulnInfo);
			}
			vulnerabilitySummary.put(UNIQUE_VULN_COUNT, sevVulnfoList.stream()
					.mapToLong(sevData -> Long.valueOf(sevData.get(UNIQUE_VULN_COUNT).toString())).sum());
			vulnerabilitySummary.put("assetsWithVulns", uniqueHost.get(TOTAL) == null ? 0 : uniqueHost.get(TOTAL));
			vulnerabilitySummary.put(VULNEREBILITIES, vulnInfo.get(TOTAL) == null ? 0 : vulnInfo.get(TOTAL));

			if (sevList.stream().filter(summarySevList::contains).count() != summarySevList.size()) {
				vulnerableAssetCount = Long.valueOf(
						vulnerabilityRepository.getUniqueHost(assetGroup, vulnSummarySeverity).get(TOTAL).toString());
			}

			for (String vulnType : vulnTargetTypes) {
				try {
					if (vulnType.equals(ONPREMSERVER)) {

						AssetCount totalAssets = assetServiceClient.getTotalAssetsCount(assetGroup, vulnType, null);
						AssetCountData data = totalAssets.getData();
						AssetCountByAppEnvDTO[] assetcount = data.getAssetcount();
						Long totalAssetsCount = 0l;
						for (AssetCountByAppEnvDTO assetCount_Count : assetcount) {
							if (assetCount_Count.getType().equalsIgnoreCase(vulnType)) {
								totalAssetsCount = Long.parseLong(assetCount_Count.getCount());
							}
						}
						totalAssetCount += totalAssetsCount;
						totalQualysCount += vulnerabilityRepository.getTotalQualysHostCount(assetGroup, vulnType);

					} else {
						Request request = new Request();
						request.setAg(assetGroup);
						Map<String, String> filter = new HashMap<>();
						filter.put("domain", "Infra & Platforms");
						if (vulnType.equals(EC2)) {
							filter.put("ruleId.keyword", EC2_QUALYS_RULEID);
						}

						if (vulnType.equals(VIRTUALMACHINE)) {
							filter.put("ruleId.keyword", VIRTUALMACHINE_QUALYS_RULEID);
						}

						request.setFilter(filter);
						// Commenting the old code
						// Map<String, Object> response =
						// complianceService.getRulecompliance(request).getResponse().get(0);
						// new code starts

						List<LinkedHashMap<String, Object>> responses = new ArrayList<>();
						Map<String, Object> response = new HashMap<>();
						ResponseEntity<Object> nonCompliancePolicyRuleresponse = complianceServiceClient
								.getNonCompliancePolicyByRule(request);
						if (nonCompliancePolicyRuleresponse != null) {
							Map<String, Object> responseBody = (Map<String, Object>) nonCompliancePolicyRuleresponse
									.getBody();
							Map<String, Object> dataResponseMap = (Map<String, Object>) responseBody.get("data");
							responses = (List<LinkedHashMap<String, Object>>) dataResponseMap.get("response");
							if (responses.size() > 0) {
								response = responses.get(0);
								// new code ends
								totalAssetCount += Long.valueOf(response.get("assetsScanned").toString());
								totalQualysCount += Long.valueOf(response.get("passed").toString());
							}
						}
					}
				}
				// catch(ServiceException | DataException e){
				catch (DataException e) {
					throw new ServiceException();
				}
			}

			try {

				vulnerabilitySummary.put("hosts", totalAssetCount);
				if (totalQualysCount > totalAssetCount) {
					totalQualysCount = totalAssetCount;
				}

				long totalVulnerableAssets = totalAssetCount - totalQualysCount + vulnerableAssetCount;
				if (totalVulnerableAssets > totalAssetCount) {
					totalVulnerableAssets = totalAssetCount;
				}
				vulnerabilitySummary.put(TOTAL_VULN_ASSETS, totalVulnerableAssets);

				float compliantCount = (float) totalAssetCount - totalVulnerableAssets;
				float compliantpercent = 100;
				if (totalAssetCount > 0) {
					compliantpercent = (compliantCount / totalAssetCount) * 100;
				}
				DecimalFormat df = new DecimalFormat("#.00");
				vulnerabilitySummary.put("compliantpercent", Math.floor(Float.valueOf(df.format(compliantpercent))));
				vulnerabilitySummary.put("hostsScanned", totalQualysCount);
				vulnerabilitySummary.put("hostsNotScanned", totalAssetCount - totalQualysCount);
				if (totalAssetCount > 0) {
					vulnerabilitySummary.put("hostsScanCoverage",
							Math.floor((1.0 * totalQualysCount / totalAssetCount) * 100));
				} else {
					vulnerabilitySummary.put("hostsScanCoverage", 0);
				}
			} catch (Exception e) {
				logger.error(e);
				throw new ServiceException(e);
			}
			if (vulnerabilitySummary.isEmpty()) {
				throw new ServiceException(NO_DATA_FOUND);
			}
			return vulnerabilitySummary;
		}

	}

}