package com.freedomoss.requester;

import com.freedomoss.objective.model.CompositeRuleContext;
import com.freedomoss.objective.model.CompositeRuleDataItemContext;
import org.slf4j.Logger;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;

import java.util.LinkedHashMap;
import com.freedomoss.requester.model.AwsHitQuestionItem;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import com.freedomoss.requester.dto.SubmissionResultDTO;
import java.util.UUID;

global CompositeRuleContext source
global Logger log
global Map params

# RuleContext.JOIN_RULE
# RuleContext.USE_ONLY_LAST_RUN_DATA

rule "Rule context initialization"
auto-focus true
dialect "mvel"
no-loop
agenda-group "initialization-group"
	when
		$ctx:CompositeRuleContext(initialized == false);
	then
	    $ctx.properties["DISPLAY_INDEX_MAP"] = new LinkedHashMap();
		# insert processed facts into memory
		$ctx.updateWorkingMemory();
		# move to business rules
		kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup("calculation").setFocus();
end

rule "1. Grouping records"
agenda-group "calculation"
no-loop
dialect "mvel"
salience 200
 when
  $ctx:CompositeRuleContext(initialized == true, $props:properties);
  $rqc:CompositeRuleDataItemContext(this memberOf $ctx.lastStepDataItems);
 then
       log.info("Grouping records ");
       accum($props, $rqc, log); 
end

rule "2. Submitting records to the next step"
agenda-group "calculation"
no-loop
dialect "mvel"
salience 150
 when
  $ctx:CompositeRuleContext(initialized == true);
 then
        log.info("Submitting records to the next step ");
        submit($ctx, log);
        $ctx.logExecutedRule(kcontext.getRule().getName());
end

function void submit(CompositeRuleContext ctx, Logger log) {
  Map map = (Map) ctx.getProperties().get("DISPLAY_INDEX_MAP");
  log.info("Submitting records, " + map.keySet().size());
  for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) {
    String uKey = (String) iterator.next();
    Map data = (Map) ((List) map.get(uKey)).get(0); 
    Object itemId = data.get("original_item_id");
    Long originalItemId = Long.parseLong(itemId.toString());
    log.info("------------------------uKey=" + uKey);
    SubmissionResultDTO nq = new SubmissionResultDTO(UUID.randomUUID().toString(),  originalItemId);
    nq.putData(data);
    Object objValue = map.get(uKey);
    if(objValue instanceof List){
    List valuesList = (List) objValue;
    	for(Iterator valuesListIterator = valuesList.iterator(); valuesListIterator.hasNext();) {
        	Map innerItemsMap = (Map)valuesListIterator.next();
            for(Iterator innerItemsMapIterator = innerItemsMap.keySet().iterator(); innerItemsMapIterator.hasNext();){
            	String innerKey = (String) innerItemsMapIterator.next();
                nq.putData(innerKey,  (String)innerItemsMap.get(innerKey));
            }        	
    	}
    }else{
    	nq.putData((Map) map.get(uKey));
    }
    log.info("-------------- map.get(uKey).getClass().getName() = " + map.get(uKey).getClass().getName());    
    
    ctx.sendResultTo("original", nq);
    }    
}

function void accum(Map props, CompositeRuleDataItemContext item, Logger log) {
   Map map = (Map) props.get("DISPLAY_INDEX_MAP");
   log.info("item::: " + item);
   String GROUPING_FIELD = "group_by_column"; 
   
   Map itemValues = item.getAllValues();
   String grouping_field_value = (String) itemValues.get(GROUPING_FIELD);  
   log.info("!!!!!!accum function!!!!!!" + GROUPING_FIELD + "= " + grouping_field_value);
   
   if (!map.containsKey(grouping_field_value))  {
      log.info("Creating new stored map");
      List listOfMaps = new ArrayList();
      Map newStoredMap = createMapColumnValue(itemValues);
      listOfMaps.add(newStoredMap);
      map.put(grouping_field_value , listOfMaps);
   }else{
      Map newStoredMap = createMapColumnValue(itemValues);
      List curreValuesList = (List)map.get(grouping_field_value);
      curreValuesList.add(newStoredMap); 
   }
 }
   
   function Map createMapColumnValue(Map itemValues) {
   	Map newStoredMap = new LinkedHashMap();
    List columns_ = new ArrayList(itemValues.keySet());
    Collections.sort(columns_);
    for (Iterator listIterator = columns_.iterator(); listIterator.hasNext();) { 
        String key = (String) listIterator.next();
        String storedValue = (String) itemValues.get(key);
        newStoredMap.put(key, storedValue);        
    }
    return newStoredMap;
   }
   