package org.owasp.appsensor.analysis.impl;

import java.util.Collection;
import java.util.Observable;

import org.owasp.appsensor.AnalysisEngine;
import org.owasp.appsensor.Attack;
import org.owasp.appsensor.DetectionPoint;
import org.owasp.appsensor.Logger;
import org.owasp.appsensor.Response;
import org.owasp.appsensor.ServerObjectFactory;

public class ReferenceAttackAnalysisEngine implements AnalysisEngine {

	private static Logger logger = ServerObjectFactory.getLogger().setLoggerClass(ReferenceAttackAnalysisEngine.class);
	
	@Override
	public void update(Observable observable, Object observedObject) {
		if (observedObject instanceof Attack) {
			Attack attack = (Attack)observedObject;
			
			DetectionPoint triggeringDetectionPoint = attack.getDetectionPoint();
			
			//grab any existing responses
			Collection<Response> existingResponses = 
					ServerObjectFactory.getResponseStore().findResponses(
							attack.getUser(), 
							triggeringDetectionPoint,
							ServerObjectFactory.getConfiguration().getRelatedDetectionSystems(attack.getDetectionSystemId())
							);

			Response response = findAppropriateResponse(triggeringDetectionPoint, existingResponses);
			
			if (response != null) {
				logger.info("Response set for user <" + attack.getUser().getUsername() + "> - storing response action " + response.getAction());
				ServerObjectFactory.getResponseStore().addResponse(response);
			}
		} 
	}
	
	protected Response findAppropriateResponse(DetectionPoint triggeringDetectionPoint, Collection<Response> existingResponses) {
		Response response = null;
		
		if (existingResponses == null) {
			//no responses yet, just grab first configured response from detection point
			response = triggeringDetectionPoint.getResponses().iterator().next();
		} else {
			for (Response configuredResponse : triggeringDetectionPoint.getResponses()) {
				response = configuredResponse;
				
				if (! isPreviousResponse(response, existingResponses)) {
					//if we find that this response doesn't already exist, use it
					break;
				}
				
				//if we reach here, we will just use the last configured response (repeat last response)
			}
		}
		
		return response;
	}
	
	protected boolean isPreviousResponse(Response response, Collection<Response> existingResponses) {
		boolean previousResponse = false;
		
		for (Response existingResponse : existingResponses) {
			if (response.getAction().equals(existingResponse.getAction())) {
				previousResponse = true;
			}
		}
		
		return previousResponse;
	}
}

@@ -37,16 +37,44 @@
 .impl;%0A%0A
+import java.util.ArrayList;%0A
 import j
@@ -1203,16 +1203,24 @@
 esponses
+, attack
 );%0A%09%09%09%0A%09
@@ -1578,24 +1578,39 @@
 ingResponses
+, Attack attack
 ) %7B%0A%09%09Respon
@@ -1632,16 +1632,111 @@
 ull;%0A%09%09%0A
+%09%09Collection%3CResponse%3E possibleResponses = findPossibleResponses(triggeringDetectionPoint);%0A%09%09%0A
 %09%09if (ex
@@ -1860,36 +1860,16 @@
 e = 
-triggeringDetectionPoint.get
+possible
 Resp
@@ -1873,18 +1873,16 @@
 esponses
-()
 .iterato
@@ -1946,36 +1946,16 @@
 e : 
-triggeringDetectionPoint.get
+possible
 Resp
@@ -1959,18 +1959,16 @@
 esponses
-()
 ) %7B%0A%09%09%09%09
@@ -2265,23 +2265,915 @@
 %09%0A%09%09
-return response
+if(response == null) %7B%0A%09%09%09throw new IllegalArgumentException(%22No appropriate response was configured for this detection point: %22 + triggeringDetectionPoint.getId());%0A%09%09%7D%0A%09%09%0A%09%09//set extra fields%0A%09%09response.setUser(attack.getUser());%0A%09%09response.setDetectionPoint(triggeringDetectionPoint);%0A%09%09response.setTimestamp(attack.getTimestamp());%0A%09%09response.setDetectionSystemId(attack.getDetectionSystemId());%0A%09%09%0A%09%09return response;%0A%09%7D%0A%09%0A%09protected Collection%3CResponse%3E findPossibleResponses(DetectionPoint triggeringDetectionPoint) %7B%0A%09%09Collection%3CResponse%3E possibleResponses = new ArrayList%3CResponse%3E();%0A%09%09%0A%09%09for (DetectionPoint configuredDetectionPoint : ServerObjectFactory.getConfiguration().getDetectionPoints()) %7B%0A%09%09%09if (configuredDetectionPoint.getId().equals(triggeringDetectionPoint.getId())) %7B%0A%09%09%09%09possibleResponses = configuredDetectionPoint.getResponses();%0A%09%09%09%09break;%0A%09%09%09%7D%0A%09%09%7D%0A%09%09%0A%09%09return possibleResponses
 ;%0A%09%7D

Update attack analysis engine to pull appropriate responses from server-side config instead of client passed responses - this was a bug.