/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package myagent.modules;

import edu.memphis.ccrg.lida.attentioncodelets.AttentionCodeletModule;
import edu.memphis.ccrg.lida.framework.FrameworkModule;
import edu.memphis.ccrg.lida.framework.ModuleName;
import edu.memphis.ccrg.lida.framework.shared.ElementFactory;
import edu.memphis.ccrg.lida.framework.shared.Link;
import edu.memphis.ccrg.lida.framework.shared.Linkable;
import edu.memphis.ccrg.lida.framework.shared.Node;
import edu.memphis.ccrg.lida.framework.shared.NodeStructure;
import edu.memphis.ccrg.lida.framework.shared.NodeStructureImpl;
import edu.memphis.ccrg.lida.framework.tasks.Codelet;
import edu.memphis.ccrg.lida.globalworkspace.BroadcastContent;
import edu.memphis.ccrg.lida.globalworkspace.GlobalWorkspace;
import edu.memphis.ccrg.lida.globalworkspace.GlobalWorkspaceImpl;
import edu.memphis.ccrg.lida.workspace.Workspace;
import edu.memphis.ccrg.lida.workspace.workspacebuffers.WorkspaceBufferImpl;
import java.util.HashMap;
import java.util.HashSet;
import myagent.attentioncodelets.GenericAttentionCodelet;

/**
 *
 * @author Marcel
 */
public class AttentionCodeletModuleImpl extends AttentionCodeletModule{
    
    protected HashSet<Codelet> addedCodelets = new HashSet<Codelet>();
    protected WorkspaceBufferImpl currentSituationalModel = null;
    protected GlobalWorkspaceImpl globalWorkspace = null;
    protected ImprovedBroadcastQueueImpl broadcastQueue = null;
    protected final double DEFAULT_MINIMUN_BROADCAST_FREQUENCY = 0.25f;
    protected double minimunBroadcastFrequency;
    
    @Override
    public void addCodelet(Codelet codelet) {
        this.addedCodelets.add(codelet);
    }
    
    @Override
    public void init() {
        super.init();
        minimunBroadcastFrequency = (Double) getParam(
                "attentionModule.minimunBroadcastFrequency", 
                DEFAULT_MINIMUN_BROADCAST_FREQUENCY);
    }
    
    public boolean hasCodeletSeekingFor(NodeStructure ns){
        for(Codelet codelet: addedCodelets){
            boolean found = true;
            for(Linkable linkable : ns.getLinkables()){
                if(!codelet.getSoughtContent().containsLinkable(linkable)){
                    found = false;
                    break;
                }
            }
            if(found) return true;
        }
        
        return false;
    }
    
    public boolean hasCodeletSeekingFor(Linkable linkable){
        NodeStructureImpl ns = new NodeStructureImpl();
        
        if(linkable instanceof Node) ns.addDefaultNode((Node)linkable);
        else if(linkable instanceof Link) ns.addDefaultLink((Link) linkable);
        else System.out.println("ERROOOOOOOOOR INVALID LINKABLE " + linkable );
        
        return hasCodeletSeekingFor(ns);
    }

    @Override
    public void learn(BroadcastContent content) {
        NodeStructure ns = (NodeStructure) content;
        if(this.isValidNewFeature(ns)){
            GenericAttentionCodelet codelet = createNodeAttentionCodelet(ns);
            this.addCodelet(codelet);
            this.taskSpawner.addTask(codelet);
        }
    }   
    
    private GenericAttentionCodelet createNodeAttentionCodelet(NodeStructure ns){
       
        HashMap<String, Object> params = new HashMap<String, Object>();

        
        params.put("nodes", new HashSet<Node>(ns.getNodes()));
        params.put("initialActivation", 0.5);
        params.put("refractoryPeriod", 50);
        
        HashMap<ModuleName, FrameworkModule> modules = new HashMap<ModuleName, FrameworkModule>();
        modules.put(ModuleName.GlobalWorkspace, globalWorkspace);
        modules.put(ModuleName.CurrentSituationalModel, this.currentSituationalModel);
        
        GenericAttentionCodelet attentionCodelet = (GenericAttentionCodelet) ElementFactory.getInstance().getFrameworkTask("GenericAttentionCodelet", params, modules);
        
        return attentionCodelet;
    }
   
    protected boolean isValidNewFeature(NodeStructure ns){
        
        float frequency = broadcastQueue.getBroadcastFrequencyForStructure(ns);
        
        if(!hasCodeletSeekingFor(ns) && frequency >= minimunBroadcastFrequency){
            return true;
        }
        else{
            return false;
        }
    }
    
    @Override
    public void setAssociatedModule(FrameworkModule module, String moduleUsage) {
            
        super.setAssociatedModule(module, moduleUsage);
        if (module instanceof Workspace) {
            FrameworkModule m = module.getSubmodule(ModuleName.CurrentSituationalModel);
            this.currentSituationalModel = (WorkspaceBufferImpl) m;
            
            m = module.getSubmodule(ModuleName.BroadcastQueue);
            this.broadcastQueue = (ImprovedBroadcastQueueImpl) m;
        }
        else if (module instanceof GlobalWorkspace) {
            this.globalWorkspace = (GlobalWorkspaceImpl) module;
        }
    }
}
