class RDSDBPublicAcessRule extends BaseRule {

	public RuleResult execute(Map<String, String> ruleParam, Map<String, String> resourceAttributes) {
		logger.debug("========RDSDBPublicAcessRule started=========");Annotation annotation = null;
		String subnet = null;
		String routetableAssociationsEsURL = null;
		String rdsdbSgEsURL = null;
		String routetableRoutesEsURL = null;
		String routetableEsURL = null;
		String sgRulesUrl = null;
		
		Boolean isIgwExists = false;
		Set<String> routeTableIdSet = new HashSet<>();
		Map<String, Boolean> openPortsMap = new HashMap<>();
		Set<GroupIdentifier> securityGroupsSet = new HashSet<>();
		LinkedHashMap<String, Object> issue = new LinkedHashMap<>();
		
		String resourceId = ruleParam.get(PacmanSdkConstants.RESOURCE_ID);
		String severity = ruleParam.get(PacmanRuleConstants.SEVERITY);
		String category = ruleParam.get(PacmanRuleConstants.CATEGORY);
		String vpcId = resourceAttributes.get("vpcid");
		String cidrIp = ruleParam.get(PacmanRuleConstants.CIDR_IP);
		String cidrIpv6 = ruleParam.get(PacmanRuleConstants.CIDRIPV6);
		String internetGateWay = ruleParam.get(PacmanRuleConstants.INTERNET_GATEWAY);
		String securityGroups = resourceAttributes.get(PacmanRuleConstants.SECURITY_GROUPS);
		String dbInstanceIdentifier = resourceAttributes.get(PacmanRuleConstants.DB_INSTANCE_IDENTIFIER);
		String endPointPort = resourceAttributes.get(PacmanRuleConstants.ENDPOINT_PORT);
		
		if(!resourceAttributes.containsKey(PacmanRuleConstants.ENDPOINT_PORT) && StringUtils.isNullOrEmpty(endPointPort)){
			endPointPort = "0";
		}
		
		String description ="RdsDb has publicly accessible ports" + endPointPort;
		MDC.put("executionId", ruleParam.get("executionId"));
		MDC.put("ruleId", ruleParam.get(PacmanSdkConstants.RULE_ID));

		String pacmanHost = PacmanUtils.getPacmanHost(PacmanRuleConstants.ES_URI);
		logger.debug("========pacmanHost {}  =========", pacmanHost);

		if (!StringUtils.isNullOrEmpty(pacmanHost)) {
			routetableAssociationsEsURL = ruleParam.get(PacmanRuleConstants.ES_ROUTE_TABLE_ASSOCIATIONS_URL);
			rdsdbSgEsURL = ruleParam.get(PacmanRuleConstants.ES_RDSDB_SG_URL);
			routetableRoutesEsURL = ruleParam.get(PacmanRuleConstants.ES_ROUTE_TABLE_ROUTES_URL);
			routetableEsURL = ruleParam.get(PacmanRuleConstants.ES_ROUTE_TABLE_URL);
			sgRulesUrl = ruleParam.get(PacmanRuleConstants.ES_SG_RULES_URL);

			routetableAssociationsEsURL = pacmanHost + routetableAssociationsEsURL;
			rdsdbSgEsURL = pacmanHost + rdsdbSgEsURL;
			routetableRoutesEsURL = pacmanHost + routetableRoutesEsURL;
			routetableEsURL = pacmanHost + routetableEsURL;
			sgRulesUrl = pacmanHost + sgRulesUrl;
		}
		
		if (!PacmanUtils.doesAllHaveValue(cidrIpv6,internetGateWay, severity, category, rdsdbSgEsURL,routetableAssociationsEsURL, routetableRoutesEsURL, routetableEsURL, sgRulesUrl, cidrIp)) {
			logger.info(PacmanRuleConstants.MISSING_CONFIGURATION);
			throw new InvalidInputException(PacmanRuleConstants.MISSING_CONFIGURATION);
		}
		
		try {
			if (!StringUtils.isNullOrEmpty(resourceAttributes.get(PacmanRuleConstants.PUBLIC_ACCESS)) && Boolean.parseBoolean(resourceAttributes.get(PacmanRuleConstants.PUBLIC_ACCESS))) {	
				String subnets = resourceAttributes.get(PacmanRuleConstants.SUBNETS_LIST);
				if(!StringUtils.isNullOrEmpty(subnets)){
				List<String> subnetsList = new ArrayList(Arrays.asList(subnets.split(",")));
				for (String subnetId : subnetsList) {
					routeTableIdSet = PacmanUtils.getRouteTableId(subnetId,null, routetableAssociationsEsURL, "subnet");
					logger.debug("======routeTableId : {}", routeTableIdSet);
					if(!routeTableIdSet.isEmpty()){
					isIgwExists = PacmanUtils.isIgwFound(cidrIp, subnetId, "Subnet", issue, routeTableIdSet, routetableRoutesEsURL, internetGateWay,cidrIpv6);
					}
					if (isIgwExists) {
						subnet = subnetId;
						break;
					}
				}
			}

				if (!isIgwExists && routeTableIdSet.isEmpty() && (!StringUtils.isNullOrEmpty(vpcId))) {
					routeTableIdSet = PacmanUtils.getRouteTableId(null, vpcId, routetableEsURL, "vpc");
					logger.debug("======routeTableId : {}", routeTableIdSet);
					if(!routeTableIdSet.isEmpty()){
					isIgwExists = PacmanUtils.isIgwFound(cidrIp, vpcId, "VPC", issue, routeTableIdSet,routetableRoutesEsURL, internetGateWay,cidrIpv6);
					}
				}

				if(isIgwExists) {
					logger.debug("======Redshiftcluster id : {}", resourceId);
					List<GroupIdentifier> listSecurityGroupID = new ArrayList<>();
					listSecurityGroupID =  PacmanUtils.getSecurityGrouplist(securityGroups.replace(":active", ""), ",",listSecurityGroupID);
					securityGroupsSet.addAll(listSecurityGroupID);
					logger.info("calling Global IP method");
					if(!securityGroupsSet.isEmpty()){
						openPortsMap =  PacmanUtils.checkAccessibleToAll(securityGroupsSet,endPointPort, sgRulesUrl, cidrIp,cidrIpv6,"");
					}else{
						logger.error("sg not associated to the resource");
						throw new RuleExecutionFailedExeption("sg not associated to the resource");
					}
					
					issue.put(PacmanRuleConstants.SEC_GRP,org.apache.commons.lang3.StringUtils.join(listSecurityGroupID, "/"));
				} else {
					logger.info("not a publicly accessible rdsdb");
				}
			
				if (!openPortsMap.isEmpty()) {
					annotation = PacmanUtils.setAnnotation(openPortsMap, ruleParam,subnet,description, issue);
					if (null != annotation) {
						annotation.put(PacmanRuleConstants.RESOURCE_DISPLAY_ID, dbInstanceIdentifier);
						return new RuleResult(PacmanSdkConstants.STATUS_FAILURE,PacmanRuleConstants.FAILURE_MESSAGE, annotation);
					}
				}
			}
		} catch (Exception exception) {
			logger.error("error: ", exception);
			throw new RuleExecutionFailedExeption(exception.getMessage());
		}
		logger.debug("========RDSDBPublicAcessRule ended=========");
		return new RuleResult(PacmanSdkConstants.STATUS_SUCCESS, PacmanRuleConstants.SUCCESS_MESSAGE);
		
	}

}