package net.floodlightcontroller.hand;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.map.MappingJsonFactory;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HANDRulesResource extends ServerResource {
public static Logger logger = LoggerFactory.getLogger(HANDGangliaHostsResource.class);
	
	
	@Get("json")
	public Object handleRequest(){
		IHANDService hand = 
				(IHANDService)getContext().getAttributes().
				get(IHANDService.class.getCanonicalName());
		
		String status = null;
		
		if(hand.isHANDEnabled()){
			return hand.getRules();
		}
		else{
			status = "Please enable Host Aware Networking Decisions";
			return ("{\"status\" : \"" + status + "\"}");
		}
	}
	
	/**
	 * 
	 * @param ruleJson
	 * @return
	 */
	@Post
	public String addRule(String ruleJson){
		IHANDService hand = 
					(IHANDService)getContext().getAttributes().
					get(IHANDService.class.getCanonicalName());
			
		HANDRule rule;
		String status = null;
			
		try{
			rule = jsonToGangliaRule(ruleJson);
		}
		catch(IOException e){
			logger.error("Error parsing rule to JSON: {}, Error: {}", ruleJson, e);
    		e.printStackTrace();
    		return "{\"status\" : \"Error! Could not parse rule, see log for details.\"}";
		}
		if(ruleExists(rule, hand.getRules())){
			status = "Error!, This rule already exists!";
			logger.error(status);
		}
		else{
			if(hand.isHANDEnabled()){
				
				/**
				 * Add Code to handle checks
				 * e.g 
				 * 
				 * is firewall rule, is the firewall enabled?
				 * is a qos rule, is QoS enabled?
				 * is the polling time good? make sense?
				 * 
				 * *Host Assoc is check in json parse
				 * *ActionType is checked in json parse
				 * *Metrics are parsed in json parse
				 * 
				 * 
				 * Then add the rule
				 * 
				 * TODO !!!!!!**************
				 */
			}
		}
		return "{\"status\" : "+ status +"}";
	 
	 }
	 
	/**
	 * 
	 * @param ruleJson
	 * @return
	 */
	 @Delete
	 public String deleteRule(String ruleJson){
		 
		//TODO
		 /**
		  * 
		  *  !!!!!!!!!!!!!!!!!!!!
		  * 
		  * 
		  */
		 
		return null;
		 
	 }

	private static HANDRule jsonToGangliaRule(String ruleJson) throws IOException{
		HANDRule rule = new HANDRule();
		
		MappingJsonFactory jsonFactory = new MappingJsonFactory();
		JsonParser parser;
		
		
		try{
			parser = jsonFactory.createJsonParser(ruleJson);
		}catch(JsonParseException e){
			throw new IOException (e);
		}
		
		JsonToken token = parser.getCurrentToken();
		if(token != JsonToken.START_OBJECT){
			parser.nextToken();
			if(parser.getCurrentToken() != JsonToken.START_OBJECT){
				logger.error("did not recieve json start token, current token is: {}"
						+ parser.getCurrentToken());
			}
		}
		//Start parsing
		while(parser.nextToken() != JsonToken.END_OBJECT){
			if(parser.getCurrentToken() != JsonToken.FIELD_NAME){
    			throw new IOException("FIELD_NAME expected");
    		}
    		
    		try{
    			String name = parser.getCurrentName();
    			parser.nextToken();
    			
    			//current text in parser
    			String jsonText = parser.getText();
    			
    			logger.info("JSON Parser text is: {}", jsonText); //DEBUG
    			
    			if(jsonText.equals("")){
    				//ignore empty string, return to loop
    				continue;
    			}
    			else if(name == "rule_name"){
    				rule.name = jsonText;
    			}
    			else if(name == "priority"){
    				//TODO
    			}
    			else if(name == "polling_time"){
    				//TODO
    			}
    			else if(name == "active"){
    				//TODO
    			}
    			else if(name == "check_limit"){
    				//TODO
    			}
    			else if(name == "attached_to"){
    				//TODO given host X, get the ID from the list of
    				//hosts known by HAND
    			}
    			else if(name == "metrics"){
    			//metrics:{<m1>:"<threshold>}....(list assumes and )
    		    //TODO store key value pars in a json string.
    			//Call parseMetrics
    			//Return HashMap<String, HANDThreshold>
    			//e.g a {"load_one":"gt-5"} should result in a 
    			// rule that tracks Load of 1 Min that triggers when it is >5 Load/Procs
    			//Also, make sure ganglia can see this metric
    			//TODO checkGangliaMetrics(HashMap<String, HANDThreshold> metrics)
    				
    			}
    			else if(name == "action_type"){
    				//TODO
    				/** Can be one of the following from
    				 * net.floodlightcontroller.hand.HandRule.java
    				 *  RPRT,	//Report threshold is reported
						AFR, 	//Add Firewall Rule
						DFW, 	//Delete Firewall Rule
						LB, 	//LoadBalance (placeholder for now //TODO )
						PSF, 	//Push Static Flow
						AQOS, 	//Add QoS Rule
						DQOS,	//Delete QoS Rule
						KR,		//Kill Route
    				 */
    				//TODO call boolean checkActionType from HandRule
    				// change the string to ALL CAPS.
    			}
    			else if(name == "action_string"){
    				//TODO
    				/**
    				 * This is an odd one, depending on the
    				 * ActionType, we will need different information from
    				 * the actionString. I.E a Adding a Firewall Rule needs
    				 * specific info rather than Pushing a Static Flow
    				 */
    				//TODO Call parseActionString(rule.action, rule.actionString)
    				//parsing the action string first looks at the ActionType,
    				//depending on the ActionType, the functions will determine 
    				//what information it needs to call to the correct
    				//controller API and checl the action_string if has given the
    				//correct information via key:value pairs.
    				rule.actionString = jsonText;
    			}
    			
    			
    		}catch(JsonParseException e){
    			logger.debug("Error getting current FIELD_NAME {}", e);
    		}catch(IOException e){
    			logger.debug("Error procession Json {}", e);
    		}
		}
		//Return the HANDGangliaHost Object to the GangliaHostResource
		return rule;
	}
	
	/**
	 * 
	 * @param rule
	 * @param ruleList
	 * @return
	 */
	public static boolean ruleExists(HANDRule rule,
			ArrayList<HANDRule> ruleList){
		
		Iterator<HANDRule> ruleIter = ruleList.iterator();
		while(ruleIter.hasNext()){
			HANDRule r = ruleIter.next();
			if(rule.isSameAs(r) || rule.name == r.name ||
					rule.equals(r)){
				return true;
			}
		}
		
		return false;
	}

}

@@ -4075,21 +4075,25 @@
 %09%09//
+%22
 metrics
+%22
 :%7B
+%22
 %3Cm1%3E
+%22
 :%22%3Ct
@@ -4101,16 +4101,17 @@
 reshold%3E
+%22
 %7D....(li
@@ -4121,19 +4121,21 @@
 assumes 
+%22
 and
+%22
  )%0A    %09

fix UTF8 ant build errors