package pt.up.fe.aiad.scheduler.agentbehaviours;

import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import pt.up.fe.aiad.scheduler.ScheduleEvent;
import pt.up.fe.aiad.scheduler.SchedulerAgent;
import pt.up.fe.aiad.utils.TimeInterval;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;

public class ADOPTBehaviour extends SimpleBehaviour {

    private boolean allFinished = false;
    private SchedulerAgent _agent;

    public HashMap<String, VirtualAgent> _virtualAgents = new HashMap<>();

    public static class VirtualAgent {

        ScheduleEvent _event;
        SchedulerAgent _masterAgent;
        private final ADOPTBehaviour _masterInstance;

        private TreeSet<String> _children = new TreeSet<>();
        private TreeSet<String> _pseudoChildren = new TreeSet<>();
        private TreeSet<String> _pseudoParents = new TreeSet<>();
        private String _parentX;
        private String _leader;

        HashMap<String, VirtualAgent> _agents;
        int threshold;
        TimeInterval di;
        HashMap<String, TimeInterval> CurrentContext; // agent -> time
        HashMap<TimeInterval, HashMap<String, Integer>> lb;
        HashMap<TimeInterval, HashMap<String, Integer>> ub;
        HashMap<TimeInterval, HashMap<String, Integer>> t;
        HashMap<TimeInterval, HashMap<String, HashMap<String, TimeInterval>>> context; // D -> child -> context (agent -> timeInterval)

        public VirtualAgent(ScheduleEvent scheduleEvent, SchedulerAgent schedulerAgent, ADOPTBehaviour masterInstance,
                            DFSBehaviour.VirtualAgent va, String leader) {
            _event = scheduleEvent;
            _masterAgent = schedulerAgent;
            _masterInstance = masterInstance;

            _leader = leader;
            _parentX = va._parentX;
            _children = va._children;
            _pseudoChildren = va._pseudoChildren;
            _pseudoParents = va._pseudoParents;

            System.err.println("ADOPT(" + _masterAgent.getLocalName() + "-" + _event.getName() + "): leader: " + _leader);
            System.err.println("ADOPT(" + _masterAgent.getLocalName() + "-" + _event.getName() + "): parent: " + _parentX);
            System.err.println("ADOPT(" + _masterAgent.getLocalName() + "-" + _event.getName() + "): children: " +  Arrays.toString(_children.toArray()));
            System.err.println("ADOPT(" + _masterAgent.getLocalName() + "-" + _event.getName() + "): pchildren: " +  Arrays.toString(_pseudoChildren.toArray()));
            System.err.println("ADOPT(" + _masterAgent.getLocalName() + "-" + _event.getName() + "): pparent: " + Arrays.toString(_pseudoParents.toArray()));
        }

        int delta(TimeInterval v) {
            int d = _event.getCost(v);

            for (Map.Entry<String, TimeInterval> xj : CurrentContext.entrySet()) {
                if (!xj.getValue().equals(v))
                    d += 1000;
            }

            for (Map.Entry<String, VirtualAgent> others : _agents.entrySet()) {
                if (others.getKey().compareTo(_event.getName()) < 0 && others.getValue().di != null &&
                        others.getValue().di.overlaps(v))
                    d += 1000;
            }

            return d;
        }

        int LB(TimeInterval v) {
            int c = delta(v);

            // for (String xl : )
            return c;
        }
    }

    public ADOPTBehaviour(String leader, HashMap<String, DFSBehaviour.VirtualAgent> agents) {

        for (Map.Entry<String, DFSBehaviour.VirtualAgent> a : agents.entrySet()) {
            _virtualAgents.put(a.getKey(), new VirtualAgent(a.getValue()._event, _agent,
                    this, a.getValue(), leader));
        }
    }

    @Override
    public void onStart() {
        _agent = (SchedulerAgent) myAgent;


        if (_agent._events.isEmpty()) {
            allFinished = true;
            _agent.finishedAlgorithm();
            return;
        }

        // TODO
    }

    @Override
    public void action() {
        if (allFinished)
            return;

        MessageTemplate mt = MessageTemplate.MatchConversationId("ADOPT");
        ACLMessage msg = myAgent.receive(mt);
        if (msg != null) {
            int separatorIndex = msg.getContent().indexOf('-');
            if (separatorIndex != -1) {
                String str = msg.getContent();
                String[] strs = str.split("-", 3 /*?*/);
                switch (strs[0]) {
                    default:
                        System.err.println("Received an invalid message type.");
                        break;
                }
            }
            else {
                System.err.println("Received an invalid message");
            }
        } else {
            block();
        }
    }

    @Override
    public boolean done() {
        return allFinished;
    }
}

@@ -3479,96 +3479,339 @@
    p
-ublic ADOPTBehaviour(String leader, HashMap%3CString, DFSBehaviour.VirtualAgent%3E agents) %7B
+rivate String _leader;%0A    private HashMap%3CString, DFSBehaviour.VirtualAgent%3E _agentsDFS;%0A%0A    public ADOPTBehaviour(String leader, HashMap%3CString, DFSBehaviour.VirtualAgent%3E agents) %7B%0A        _leader = leader;%0A        _agentsDFS = agents;%0A    %7D%0A%0A    @Override%0A    public void onStart() %7B%0A        _agent = (SchedulerAgent) myAgent;
 %0A%0A  
@@ -3870,22 +3870,26 @@
 nt%3E a : 
+_
 agents
+DFS
 .entrySe
@@ -4024,16 +4024,17 @@
 alue(), 
+_
 leader))
@@ -4049,101 +4049,8 @@
   %7D%0A
-    %7D%0A%0A    @Override%0A    public void onStart() %7B%0A        _agent = (SchedulerAgent) myAgent;%0A%0A
 %0A   

Change ADOPTBehaviour initialization