package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;

import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;

import java.util.*;

/**
 * This {@link ITransitionStrategy} works with manual assignments. Initially components will be assigned
 * one of the attraction points, but at any further point, the set list of attraction points doesn't really matter.
 * New target can be assigned by using the {@link #updateTargetAttractionPoint(SimLocationActuator, AttractionPoint)} method,
 * otherwise the components will stop moving upon reaching their target.
 *
 * @author Clemens Krug
 */
public class ManualAssignmentStrategy implements ITransitionStrategy
{
    private LinkedHashSet<AttractionPoint> aPoints = new LinkedHashSet<>();

    private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<>();

    private List<AttractionAssignmentListener> listeners = new LinkedList<>();


    @Override
    public AttractionPoint getAssignment(SimLocationActuator comp)
    {
        return assignments.get(comp);
    }

    @Override
    public void addAttractionAssignmentListener(AttractionAssignmentListener listener)
    {
        listeners.add(listener);
    }

    @Override
    public void removeAttractionAssignmentListener(AttractionAssignmentListener listener)
    {
        listeners.remove(listener);
    }

    @Override
    public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
        aPoints.addAll(attractionPoints);
    }

    @Override
    public Set<AttractionPoint> getAllAttractionPoints() {
        return aPoints;
    }

    @Override
    public void addComponent(SimLocationActuator ms) {
        if(!assignments.containsKey(ms))
        {
            AttractionPoint aPoint = aPoints.iterator().next();
            assignments.put(ms, aPoint);
        }
        listeners.forEach(listener -> listener.updatedAttractionAssignment(ms, assignments.get(ms)));
    }

    @Override
    public void reachedAttractionPoint(SimLocationActuator ms) {
        //Nothing to do.
    }

    @Override
    public void updateTargetAttractionPoint(SimLocationActuator comp, AttractionPoint attractionPoint) {
        assignments.put(comp, attractionPoint);
        listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint));
    }
}
