class EC2WithPublicIPAccess extends BaseRule {

       @Override
    public RuleResult execute(Map<String, String> ruleParam, Map<String, String> resourceAttributes) {
        logger.debug("========EC2WithPublicIPAccess started=========");
        Annotation annotation = null;
        String ec2SgEsURL = null;
        String routetableAssociationsEsURL = null;
        String routetableRoutesEsURL = null;
        String routetableEsURL = null;
        String sgRulesUrl = null;
        Set<GroupIdentifier> securityGroupsSet = new HashSet<>();
        Boolean isIgwExists = false;
        if (resourceAttributes.get("statename").equals(PacmanRuleConstants.RUNNING_STATE)) {
        	
            String internetGateWay = ruleParam.get(PacmanRuleConstants.INTERNET_GATEWAY);
            String entityId = ruleParam.get(PacmanSdkConstants.RESOURCE_ID);
            String severity = ruleParam.get(PacmanRuleConstants.SEVERITY);
            String category = ruleParam.get(PacmanRuleConstants.CATEGORY);
            String cidrIp = ruleParam.get(PacmanRuleConstants.CIDR_IP);
            String cidrIpv6 = ruleParam.get(PacmanRuleConstants.CIDRIPV6);
            String defaultCidrIp = ruleParam.get(PacmanRuleConstants.DEFAULT_CIDR_IP);
            
            String pacmanHost = PacmanUtils.getPacmanHost(PacmanRuleConstants.ES_URI);
            logger.debug("========pacmanHost {}  =========",pacmanHost);
            if(!StringUtils.isNullOrEmpty(pacmanHost)){
                ec2SgEsURL = ruleParam.get(PacmanRuleConstants.ES_EC2_SG_URL);
                routetableAssociationsEsURL = ruleParam.get(PacmanRuleConstants.ES_ROUTE_TABLE_ASSOCIATIONS_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);
                
                ec2SgEsURL = pacmanHost+ec2SgEsURL;
                routetableAssociationsEsURL = pacmanHost+routetableAssociationsEsURL;
                routetableRoutesEsURL = pacmanHost+routetableRoutesEsURL;
                routetableEsURL = pacmanHost+routetableEsURL;
                sgRulesUrl = pacmanHost+sgRulesUrl;
            }
            
            logger.debug("========ec2SgEsURL URL after concatination param {}  =========",ec2SgEsURL);
            logger.debug("========routetableAssociationsEsURL URL after concatination param {}  =========",routetableAssociationsEsURL);
            logger.debug("========routetableRoutesEsURL URL after concatination param {}  =========",routetableRoutesEsURL);
            logger.debug("========routetableEsURL URL after concatination param {}  =========",routetableEsURL);
            logger.debug("========sgRulesUrl URL after concatination param {}  =========",sgRulesUrl);

            String publicipaddress = resourceAttributes.get("publicipaddress");
            String subnetid = resourceAttributes.get("subnetid");
            String vpcid = resourceAttributes.get("vpcid");

            MDC.put("executionId", ruleParam.get("executionId")); 
            MDC.put("ruleId", ruleParam.get(PacmanSdkConstants.RULE_ID)); 

            List<LinkedHashMap<String, Object>> issueList = new ArrayList<>();
            LinkedHashMap<String, Object> issue = new LinkedHashMap<>();

            if (!PacmanUtils.doesAllHaveValue(defaultCidrIp,cidrIpv6,internetGateWay, severity, category, ec2SgEsURL, routetableAssociationsEsURL, routetableRoutesEsURL, routetableEsURL, sgRulesUrl, cidrIp)) {
                logger.info(PacmanRuleConstants.MISSING_CONFIGURATION);
                throw new InvalidInputException(PacmanRuleConstants.MISSING_CONFIGURATION);
            }

            try {
                if (!StringUtils.isNullOrEmpty(publicipaddress)) {
                    issue.put(PacmanRuleConstants.PUBLICIP, publicipaddress);
                    Set<String> routeTableIdSet = PacmanUtils.getRouteTableId(subnetid, vpcid, routetableAssociationsEsURL, "subnet");
                    if(!routeTableIdSet.isEmpty()){
                    isIgwExists = PacmanUtils.isIgwFound(cidrIp,subnetid, "Subnet", issue, routeTableIdSet, routetableRoutesEsURL, internetGateWay,cidrIpv6);
                    }
                    if (!isIgwExists && routeTableIdSet.isEmpty() && !StringUtils.isNullOrEmpty(vpcid)) {
                        routeTableIdSet = PacmanUtils.getRouteTableId(subnetid, vpcid, routetableEsURL, "vpc");
                        if(!routeTableIdSet.isEmpty()){
                        isIgwExists = PacmanUtils.isIgwFound(cidrIp,vpcid, "VPC", issue, routeTableIdSet, routetableRoutesEsURL, internetGateWay,cidrIpv6);
                        }
                    }

                    if (isIgwExists) {
                        List<GroupIdentifier> listSecurityGroupID = PacmanUtils.getSecurityGroupsByInstanceId(entityId, ec2SgEsURL);
                        securityGroupsSet.addAll(listSecurityGroupID);
                        issue.put(PacmanRuleConstants.SEC_GRP, org.apache.commons.lang3.StringUtils.join(listSecurityGroupID, "/"));
                    } else {
                        logger.info("EC2 is not publicly accessble");
                    }

                    logger.info("calling Global IP method");
                    
                    Map<String, Boolean> openPortsMap =  PacmanUtils.checkAccessibleToAll(securityGroupsSet, "ANY", sgRulesUrl, cidrIp,cidrIpv6,"");
                    List<String> portsSet = new ArrayList<>();
                    for (Map.Entry<String, Boolean> ports : openPortsMap.entrySet()) {
                        portsSet.add(ports.getKey());
                    }

                    if (!openPortsMap.isEmpty()) {
                        annotation = Annotation.buildAnnotation(ruleParam, Annotation.Type.ISSUE);
                        annotation.put(PacmanSdkConstants.DESCRIPTION, "EC2 with publicly accessible ports found");
                        annotation.put("EC2PublicIP", publicipaddress);
                        annotation.put(PacmanRuleConstants.SEVERITY, severity);
                        annotation.put(PacmanRuleConstants.CATEGORY, category);
                        annotation.put(PacmanRuleConstants.VPC_ID,vpcid);
                        annotation.put(PacmanRuleConstants.SUBNETID,subnetid);

                        issue.put(PacmanRuleConstants.VIOLATION_REASON, "EC2 with publicly accessible ports found");
                        issueList.add(issue);
                        annotation.put("issueDetails", issueList.toString());
                        logger.debug("========EC2WithPublicIPAccess ended with an annotation {} : =========",annotation);
                        return new RuleResult(PacmanSdkConstants.STATUS_FAILURE, PacmanRuleConstants.FAILURE_MESSAGE, annotation);
                    }
                
            }
            } catch (Exception exception) {
                logger.error("error: ", exception);
                throw new RuleExecutionFailedExeption(exception.getMessage());
            }
        }
        logger.debug("========EC2WithPublicIPAccess ended=========");
        return new RuleResult(PacmanSdkConstants.STATUS_SUCCESS, PacmanRuleConstants.SUCCESS_MESSAGE);

       }

}