package agents4;

import jade.core.Agent;
import jade.core.ContainerID;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Studentas extends Agent {

    private ArrayList<String> allContainers = new ArrayList<>();
    private ArrayList<String> visited = new ArrayList<>();
    private String currentContainer;
    private Random rng = new Random();

    private void print(String data, String behaviourId) {
        if (behaviourId != null)
            System.out.println("A[" + getLocalName() + "|" + behaviourId + "] " + data);
        else
            System.out.println("A[" + getLocalName() + "] " + data);
    }

    private String chooseNext() {
        List<String> options = new ArrayList<>(allContainers);
        options.remove(currentContainer);

        if (options.isEmpty()) return currentContainer;

        List<String> unvisited = new ArrayList<>(options);
        unvisited.removeAll(visited);

        if (!unvisited.isEmpty())
            return unvisited.get(rng.nextInt(unvisited.size()));

        return options.get(rng.nextInt(options.size()));
    }

    /** Listens for Testas/Egzaminas and migrates to another container. */
    private class MoveBehaviour extends CyclicBehaviour {
        @Override
        public void action() {
            MessageTemplate mt = MessageTemplate.and(
                MessageTemplate.MatchPerformative(ACLMessage.INFORM),
                MessageTemplate.or(
                    MessageTemplate.MatchContent("Testas"),
                    MessageTemplate.MatchContent("Egzaminas")
                )
            );
            ACLMessage msg = myAgent.receive(mt);
            if (msg != null) {
                print("gautas pranešimas: " + msg.getContent(), "MoveBehaviour");
                if (allContainers.size() <= 1) {
                    print("nėra kur bėgti", "MoveBehaviour");
                    return;
                }
                String next = chooseNext();
                print("kraupiuosi į: " + next, "MoveBehaviour");
                myAgent.doMove(new ContainerID(next, null));
            } else {
                block();
            }
        }
    }


    private class ContainerUpdateBehaviour extends CyclicBehaviour {
        @Override
        public void action() {
            MessageTemplate mt = MessageTemplate.MatchConversationId("container-update");
            ACLMessage msg = myAgent.receive(mt);
            if (msg != null) {
                String content = msg.getContent();
                if (content.startsWith("CONTAINER_ADDED:")) {
                    String name = content.substring("CONTAINER_ADDED:".length());
                    if (!allContainers.contains(name)) {
                        allContainers.add(name);
                        print("konteineris pridėtas: " + name, "ContainerUpdateBehaviour");
                    }
                } else if (content.startsWith("CONTAINER_REMOVED:")) {
                    String name = content.substring("CONTAINER_REMOVED:".length());
                    allContainers.remove(name);
                    visited.remove(name);
                    print("konteineris pašalintas: " + name, "ContainerUpdateBehaviour");
                    // If we're currently in the removed container, migrate immediately
                    if (name.equals(currentContainer) && !allContainers.isEmpty()) {
                        String next = chooseNext();
                        print("dabartinis konteineris sunaikinamas – kraupiuosi į: " + next,
                            "ContainerUpdateBehaviour");
                        myAgent.doMove(new ContainerID(next, null));
                    }
                }
            } else {
                block();
            }
        }
    }

    @Override
    protected void setup() {
        Object[] args = getArguments();
        if (args != null) {
            for (Object o : args) allContainers.add((String) o);
        }
        currentContainer = here().getName();
        if (!visited.contains(currentContainer)) visited.add(currentContainer);
        print("Laba diena", null);
        addBehaviour(new MoveBehaviour());
        addBehaviour(new ContainerUpdateBehaviour());
    }

    @Override
    protected void beforeMove() {
        print("Viso", null);
    }

    @Override
    protected void afterMove() {
        currentContainer = here().getName();
        if (!visited.contains(currentContainer)) visited.add(currentContainer);
        print("Laba diena", null);
    }

    @Override
    protected void takeDown() {
        print("terminated", null);
    }
}
