package flow;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import com.avaya.sce.runtime.tracking.ReportInfo;
import com.avaya.sce.runtimecommon.IReportInfo;
import com.avaya.sce.runtimecommon.IVariable;

import flow.constants.SSAConstants;
import flow.utils.Utils;

/**
 * A basic servlet which allows a user to define their code, generate
 * any output, and to select where to transition to next.
 * Last generated by Orchestration Designer at: (timestamp generation disabled)
 */
public class PrepareContext extends com.avaya.sce.runtime.BasicServlet {

	//{{START:CLASS:FIELDS
	//}}END:CLASS:FIELDS

	/**
	 * Default constructor
	 * Last generated by Orchestration Designer at: (timestamp generation disabled)
	 */
	public PrepareContext() {
		//{{START:CLASS:CONSTRUCTOR
		super();
		//}}END:CLASS:CONSTRUCTOR
	}

	/**
	 * This method allows for custom integration with other Java components.
	 * You may use Java for sophisticated logic or to integrate with custom
	 * connectors (i.e. JMS, custom web services, sockets, XML, JAXB, etc.)
	 *
	 * Any custom code added here should work as efficiently as possible to prevent delays.
	 * It's important to design your callflow so that the voice browser (Voice Portal/IR)
	 * is not waiting too long for a response as this can lead to a poor caller experience.
	 * Additionally, if the response to the client voice browser exceeds the configured
	 * timeout, the platform may throw an "error.badfetch". 
	 *
	 * Using this method, you have access to all session variables through the 
	 * SCESession object.
	 *
	 * The code generator will *** NOT *** overwrite this method in the future.
	 * Last generated by Orchestration Designer at: (timestamp generation disabled)
	 */
	public void servletImplementation(com.avaya.sce.runtimecommon.SCESession mySession) {

		try {		
			//Get collected customer ID and other WA values (taken from properties file in this sample)
			String ucid = (String)Utils.getVariableField(IProjectVariables.PROPERTIES, IProjectVariables.PROPERTIES_FIELD_CALL_ID, mySession);
			String locale = (String)Utils.getVariableField(IProjectVariables.PROPERTIES, IProjectVariables.PROPERTIES_FIELD_LOCALE, mySession);
			String dataCenter = (String)Utils.getVariableField(IProjectVariables.SELECTED_DATA_CENTER, IProjectVariables.SELECTED_DATA_CENTER_FIELD_NAME, mySession);
			String accountId = (String)Utils.getVariableField(IProjectVariables.COLLECT_CUSTOMER_ID, IProjectVariables.COLLECT_CUSTOMER_ID_FIELD_VALUE, mySession);
			String specifiedResourcesData = (String)Utils.getVariableField(IProjectVariables.PROPERTIES, IProjectVariables.PROPERTIES_FIELD_SPECIFIED_RESOURCE, mySession);
			String jsonServiceMap = (String)Utils.getVariableField(IProjectVariables.CONTEXT, IProjectVariables.CONTEXT_FIELD_SERVICE_MAP, mySession);
			String strategy = (String)Utils.getVariableField(IProjectVariables.PROPERTIES, IProjectVariables.PROPERTIES_FIELD_STRATEGY, mySession);
			String callingNumber = (String)Utils.getVariableField(IProjectVariables.SESSION, IProjectVariables.SESSION_FIELD_ANI, mySession);
			String custManagementId =  (String)Utils.getVariableField(IProjectVariables.GET_CUSTOMER_RESPONSE, mySession);
			String topic = (String)Utils.getVariableField(IProjectVariables.PROPERTIES, IProjectVariables.PROPERTIES_FIELD_TOPIC, mySession);
	        Integer requiredResource = Integer.valueOf((String)Utils.getVariableField(IProjectVariables.REQUEST_TYPE, IProjectVariables.REQUEST_TYPE_FIELD_REQUIRED_RESOURCE, mySession));       
	        Integer requestTypeSelection = Integer.valueOf((String)Utils.getVariableField(IProjectVariables.SELECT_SPECIFIED_RESOURCE, IProjectVariables.SELECT_SPECIFIED_RESOURCE_FIELD_VALUE, mySession));			
	        String callingLineId = (String)Utils.getVariableField(IProjectVariables.SESSION, IProjectVariables.SESSION_FIELD_ANI, mySession);			
	        
	        Utils.logInfo("Collected Account Number: " + accountId, mySession);
	        
	        if (!Utils.isStringBlank(callingLineId) && (callingLineId.compareToIgnoreCase(SSAConstants.ANONYMOUS_CALLER) == 0)) {	        	
	        	Utils.logInfo("Caller is '" + callingLineId + "!", mySession);
	        }			
			
			if (Utils.isStringBlank(topic) && (requestTypeSelection != requiredResource)){
				//A topic is not configured for this call; create a default sample one
				topic = (String)(Utils.getVariableField(IProjectVariables.MENU_CATEGORIES, IProjectVariables.MENU_CATEGORIES_FIELD_MENU_2SELECTION, mySession) +
						Utils.getVariableField(IProjectVariables.MENU_CATEGORIES, IProjectVariables.MENU_CATEGORIES_FIELD_MENU_1SELECTION, mySession));
				Utils.logInfo("Setting topic to " + topic, mySession);
				Utils.setVariableField(IProjectVariables.PROPERTIES, IProjectVariables.PROPERTIES_FIELD_TOPIC, topic, mySession);
			}			
			
			Map<Integer, JSONObject> resourceMap = new LinkedHashMap<Integer, JSONObject>();
			
			int specifiedResourceCounter = 0;
			String specifiedResources[] = specifiedResourcesData.split(SSAConstants.DELIMITER_COMMA);
			for(String specifiedResource : specifiedResources){
				if(specifiedResourceCounter < SSAConstants.MAX_SPECIFIED_RESOURCES){
                    specifiedResourceCounter++;
                } else{
                    break;
                }
				String nativeResourceId = null;
				String sourceName = null;
				
				String resourceElements[] = specifiedResource.trim().split(SSAConstants.DELIMITER_AMPERSAND);
				if ((resourceElements != null) && (resourceElements.length > 1)) { 
					nativeResourceId = resourceElements[0];
					sourceName = resourceElements[1];
				}
				
				// Create ResourceMap
				if (nativeResourceId != null && !(nativeResourceId.isEmpty()) && sourceName != null && !(sourceName.isEmpty())) {
					JSONObject resource = new JSONObject();		
					resource.put(SSAConstants.CONTEXT_RESOURCEID, nativeResourceId);
					resource.put(SSAConstants.CONTEXT_RESOURCESOURCE, sourceName);		
					resourceMap.put(specifiedResourceCounter, resource);
				}
			}

			//Start building the CS Data structure
			JSONObject context = new JSONObject();
			JSONObject schema = new JSONObject();
			
			schema.put(SSAConstants.CONTEXT_LOCALE, locale);
        	schema.put(SSAConstants.CONTEXT_DATA_CENTER, dataCenter);
        	schema.put(SSAConstants.CONTEXT_STRATEGY, strategy);
        	schema.put(SSAConstants.CONTEXT_RESOURCEMAP, resourceMap);
        	schema.put(SSAConstants.CONTEXT_SERVICEMAP, new JSONObject(jsonServiceMap));     	
        	schema.put(SSAConstants.CONTEXT_XFER_SERVICEMAP, new JSONObject());

        	//If this is a transferred call and pre-existing context has been found, then re-use it; otherwise, clear the context id and have CS generate
        	String existingContextId = (String)Utils.getVariableField(IProjectVariables.CONTEXT, IProjectVariables.CONTEXT_FIELD_CONTEXT_ID, mySession);
        	if (Utils.isStringBlank(existingContextId)) {
        		context.put(SSAConstants.CONTEXT_CONTEXTID, "");
        		context.put(SSAConstants.CONTEXT_PERSIST, "true");

            	//If this is a transferred call, then don't supply a groupId in the context blob        		
            	// Check if lookup of customerId returned value, otherwise use the 'account number' i.e. entered digits.
            	if(StringUtils.isEmpty(custManagementId)){     
            		schema.put(SSAConstants.CONTEXT_CUSTOMERID, accountId);            		
                	context.put(SSAConstants.CONTEXT_GROUPID, accountId);
                	schema.put(SSAConstants.CONTEXT_ACCOUNTID, accountId);                	
            	}
            	else{
                	JSONObject customerIdData = new JSONObject(custManagementId);            		
                	String customerIdValue = customerIdData.getString(SSAConstants.CONTEXT_GET_CUSTOMERID);
                	schema.put(SSAConstants.CONTEXT_CUSTOMERID, customerIdValue);
                	context.put(SSAConstants.CONTEXT_GROUPID, customerIdValue);
                	schema.put(SSAConstants.CONTEXT_ACCOUNTID, accountId);                	
            	}         		
        	}
        	       	
           	// Add the collected digits, including menu selections
        	StringBuffer collectDigits = new StringBuffer("");
        	collectDigits.append(accountId);
        	collectDigits.append("#" + (String)Utils.getVariableField(IProjectVariables.SELECT_SPECIFIED_RESOURCE, IProjectVariables.SELECT_SPECIFIED_RESOURCE_FIELD_VALUE, mySession));
        	
        	if (requestTypeSelection != requiredResource) {
	        	collectDigits.append("#" + (String)Utils.getVariableField(IProjectVariables.SELECT_FIRST_MENU, IProjectVariables.SELECT_FIRST_MENU_FIELD_VALUE, mySession));
	        	collectDigits.append("#" + (String)Utils.getVariableField(IProjectVariables.SELECT_SECOND_MENU, IProjectVariables.SELECT_SECOND_MENU_FIELD_VALUE, mySession));
        	} else {
        		collectDigits.append("#");
        	}
        	schema.put(SSAConstants.CONTEXT_COLLECTED_DIGITS, collectDigits.toString());      
        	
        	context.put(SSAConstants.CONTEXT_SCHEMA, schema);
        	
			//Set data to be used in POST operation to ContextStore
			IVariable invariable = mySession.getVariable(IProjectVariables.CONTEXT_STORE_INPUT);			
			invariable.getComplexVariable().getField(IProjectVariables.CONTEXT_STORE_INPUT_FIELD_DATA).setValue(context.toString());

			//Set the Customer Journey touchpoint
			invariable = mySession.getVariable(IProjectVariables.CONTEXT_STORE_INPUT);
			invariable.getComplexVariable().getField(IProjectVariables.CONTEXT_STORE_INPUT_FIELD_TOUCHPOINT).setValue(SSAConstants.CS_TOUCHPOINT);		
			
			Utils.logInfo("SESSION_FIELD_UCID --> " + ucid, mySession);
			Utils.logInfo("INPUT_FIELD_DATA ----> " + invariable.getComplexVariable().getField(IProjectVariables.CONTEXT_STORE_INPUT_FIELD_DATA).getStringValue(), mySession);
			Utils.logInfo("INPUT_FIELD_TOUCHPOINT ----> " + invariable.getComplexVariable().getField(IProjectVariables.CONTEXT_STORE_INPUT_FIELD_TOUCHPOINT).getStringValue(), mySession);
		} catch (JSONException e) {							
			Utils.logInfo("Exception caught processing Service Map: " + e, mySession);				

			
	        ReportInfo report =  new com.avaya.sce.runtime.tracking.ReportInfo(
	                IReportInfo.REPORT_TYPE_PROGRESS, 
	                IReportInfo.ALARM_LEVEL_MAJOR, 
	                SSAConstants.REPORTING_TAG, 
	                "Error Processing Service Map", 
	                e.getMessage());	        
	        report.trackItems(mySession);
		}
	}	
	/**
	 * Builds the list of branches that are defined for this servlet object.
	 * This list is built automatically by defining Goto nodes in the call flow editor.
	 * It is the programmer's responsibilty to provide at least one enabled Goto.<BR>
	 *
	 * The user should override updateBranches() to determine which Goto that the
	 * framework will activate.  If there is not at least one enabled Goto item, 
	 * the framework will throw a runtime exception.<BR>
	 *
	 * This method is generated automatically and changes to it may
	 * be overwritten next time code is generated.  To modify the list
	 * of branches for the flow item, override:
	 *     <code>updateBranches(Collection branches, SCESession mySession)</code>
	 *
	 * @return a Collection of <code>com.avaya.sce.runtime.Goto</code>
	 * objects that will be evaluated at runtime.  If there are no gotos
	 * defined in the Servlet node, then this returns null.
	 * Last generated by Orchestration Designer at: (timestamp generation disabled)
	 */
	public java.util.Collection getBranches(com.avaya.sce.runtimecommon.SCESession mySession) {
		java.util.List list = null;
		com.avaya.sce.runtime.Goto aGoto = null;
		list = new java.util.ArrayList(1);

		aGoto = new com.avaya.sce.runtime.Goto("StoreContext", 0, true, "Default");
		list.add(aGoto);

		return list;
	}
}
