class EC2PublicAccessForConfiguredPortRule extends BaseRule {

    @Override
    public RuleResult execute(Map<String, String> ruleParam, Map<String, String> resourceAttributes) {
        logger.debug("========EC2PublicAccessForConfiguredPortRule started=========");
        Boolean isIgwExists = false;
        String ec2SgEsURL = null;
        String routetableAssociationsEsURL = null;
        String routetableRoutesEsURL = null;
        String routetableEsURL = null;
        String sgRulesUrl = null;
        Set<GroupIdentifier> securityGroupsSet = new HashSet<>();
        if (resourceAttributes.get("statename").equals(PacmanRuleConstants.RUNNING_STATE)) {
           
            String portToCheck = ruleParam.get(PacmanRuleConstants.PORT_TO_CHECK);
            String internetGateWay = ruleParam.get(PacmanRuleConstants.INTERNET_GATEWAY);
            String resourceId = ruleParam.get(PacmanSdkConstants.RESOURCE_ID);
            String publicipaddress = resourceAttributes.get(PacmanRuleConstants.PUBLIC_IP_ADDR);
            String subnetid = resourceAttributes.get("subnetid");
            String vpcid = resourceAttributes.get("vpcid");

            logger.debug("======publicipaddress : {}", publicipaddress);
            logger.debug("======subnetid : {}", subnetid);
            logger.debug("======vpcid : {}", vpcid);

            String severity = ruleParam.get(PacmanRuleConstants.SEVERITY);
            String category = ruleParam.get(PacmanRuleConstants.CATEGORY);
            String cidrIp = ruleParam.get(PacmanRuleConstants.CIDR_IP);
            String cidrIpv6 = "::/0";

            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);

            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(portToCheck, 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");
                    logger.debug("======routeTableId : {}", routeTableIdSet);
                    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");
                       logger.debug("======routeTableId : {}", routeTableIdSet);
                       if(!routeTableIdSet.isEmpty()){
                       isIgwExists = PacmanUtils.isIgwFound(cidrIp, vpcid, "VPC", issue, routeTableIdSet, routetableRoutesEsURL, internetGateWay,cidrIpv6);
                       }
                    }
                    if (isIgwExists) {
                        logger.debug("======entityId : {}", resourceId);
                        List<GroupIdentifier> listSecurityGroupID = PacmanUtils.getSecurityGroupsByInstanceId(resourceId, ec2SgEsURL);
                        securityGroupsSet.addAll(listSecurityGroupID);
                        issue.put(PacmanRuleConstants.SEC_GRP,org.apache.commons.lang3.StringUtils.join(listSecurityGroupID, "/"));
                    } else {
                        logger.info("EC2 is not publically accessble");
                    }
                    Annotation annotation = createAnnotation(resourceAttributes, securityGroupsSet, ruleParam, issueList, issue, sgRulesUrl);
                    if (null != 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("========EC2PublicAccessForConfiguredPortRule ended=========");
        return new RuleResult(PacmanSdkConstants.STATUS_SUCCESS, PacmanRuleConstants.SUCCESS_MESSAGE);
    }

}