package org.zalando.stups.fullstop.plugin.unapproved;

import com.amazonaws.services.cloudtrail.processinglibrary.model.CloudTrailEvent;
import com.amazonaws.services.cloudtrail.processinglibrary.model.CloudTrailEventData;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.JsonPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.zalando.stups.fullstop.plugin.AbstractFullstopPlugin;
import org.zalando.stups.fullstop.plugin.unapproved.config.UnapprovedServicesAndRoleProperties;
import org.zalando.stups.fullstop.violation.ViolationSink;

import java.io.IOException;

import static com.google.common.collect.Lists.newArrayList;
import static org.zalando.stups.fullstop.events.CloudTrailEventSupport.*;
import static org.zalando.stups.fullstop.violation.ViolationType.MODIFIED_ROLE_OR_SERVICE;

/**
 * @author mrandi
 */
@Component
public class UnapprovedServicesAndRolePlugin extends AbstractFullstopPlugin {

    private static final Logger LOG = LoggerFactory.getLogger(UnapprovedServicesAndRolePlugin.class);

    private static final String EVENT_SOURCE = "iam.amazonaws.com";

    private final PolicyProvider policyProvider;

    private final ViolationSink violationSink;

    private final UnapprovedServicesAndRoleProperties unapprovedServicesAndRoleProperties;

    private final PolicyTemplatesProvider policyTemplatesProvider;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    public UnapprovedServicesAndRolePlugin(final PolicyProvider policyProvider, final ViolationSink violationSink,
            final PolicyTemplatesProvider policyTemplatesProvider,
            final UnapprovedServicesAndRoleProperties unapprovedServicesAndRoleProperties) {
        this.policyProvider = policyProvider;
        this.violationSink = violationSink;
        this.policyTemplatesProvider = policyTemplatesProvider;
        this.unapprovedServicesAndRoleProperties = unapprovedServicesAndRoleProperties;
    }

    @Override
    public boolean supports(final CloudTrailEvent event) {
        CloudTrailEventData cloudTrailEventData = event.getEventData();
        String eventSource = cloudTrailEventData.getEventSource();

        return eventSource.equals(EVENT_SOURCE)
                && (unapprovedServicesAndRoleProperties.getEventNames().contains(cloudTrailEventData.getEventName()))
                && (policyTemplatesProvider.getPolicyTemplateNames().contains(getRoleName(event)));
    }

    @Override
    public void processEvent(final CloudTrailEvent event) {

        String roleName = getRoleName(event);

        String policy = policyProvider.getPolicy(roleName, getRegion(event), getAccountId(event));

        String policyTemplate = policyTemplatesProvider.getPolicyTemplate(roleName);

        JsonNode policyJson;
        JsonNode templatePolicyJson;

        try {
            policyJson = objectMapper.readTree(policy);
            templatePolicyJson = objectMapper.readTree(policyTemplate);
        }
        catch (IOException e) {
            LOG.warn("Could not read policy tree! For policy: {} and policy template:  {}", policy, policyTemplate);
            return;
        }

        if (!policyJson.equals(templatePolicyJson)) {
            violationSink.put(
                    violationFor(event)
                            .withPluginFullyQualifiedClassName(UnapprovedServicesAndRolePlugin.class)
                            .withType(MODIFIED_ROLE_OR_SERVICE)
                            .withMetaInfo(roleName)
                            .build());

        }

    }

    private String getRoleName(final CloudTrailEvent event) {
        return JsonPath.read(event.getEventData().getRequestParameters(), "$.roleName");
    }

}

@@ -776,68 +776,8 @@
 n;%0A%0A
-import static com.google.common.collect.Lists.newArrayList;%0A
 impo
@@ -846,16 +846,16 @@
 port.*;%0A
+
 import s
@@ -1675,16 +1675,47 @@
 onSink,%0A
+                               
         
@@ -1773,16 +1773,47 @@
 ovider,%0A
+                               
         
@@ -2750,24 +2750,411 @@
 me(event);%0A%0A
+        if (roleName == null) %7B%0A            LOG.info(%22Could not find roleName for event: %7B%7D, %7B%7D for account: %7B%7D and region: %7B%7D%22,%0A                    event.getEventData().getEventId(),%0A                    event.getEventData().getEventName(),%0A                    event.getEventData().getAccountId(),%0A                    event.getEventData().getAwsRegion());%0A            return;%0A        %7D%0A%0A
         Stri
@@ -3545,24 +3545,16 @@
        %7D
-%0A       
  catch (
@@ -4173,32 +4173,227 @@
 lEvent event) %7B%0A
+%0A        if (event.getEventData() != null%0A                && event.getEventData().getRequestParameters() != null%0A                && !event.getEventData().getRequestParameters().isEmpty()) %7B%0A%0A    
         return J
@@ -4465,16 +4465,78 @@
 Name%22);%0A
+        %0A        %7D else %7B%0A            return null;%0A        %7D%0A%0A
     %7D%0A%0A%7D

fix exception