package de.renew.simulatorontology.shadow;

import java.io.Serial;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/** An abstract class representing a shadow net element that can have
 * associated inscriptions, such as textual annotations or arcs.
 * <p>
 * This class maintains a collection of related {@code ShadowNetElement}
 * instances which serve as inscriptions on the element. The inscriptions
 * are not serialized to avoid recursive serialization cycles; instead,
 * they must be re-established after deserialization.
 */
public abstract class ShadowInscribable extends ShadowNetElement {
    /* Serialization support. */
    @Serial
    private static final long serialVersionUID = 1696327514729295533L;

    /**
     * References all inscriptions (text inscriptions, arcs, etc.)
     * of this inscribable shadow net element.
     * <p>
     * This field is not serialized because we have to avoid deep
     * recursion on serialization. (This field would write arcs
     * attached to a node, the arc would write its other adjacent
     * node, the node would write another arc and so on and so on.)
     * Instead, its contents have to be rebuilt on deserialization.
     * All inscription net elements have to reregister themselves
     * on deserialization in the same way they do at their creation
     * time.
     * </p>
     **/
    private transient Set<ShadowNetElement> _elements;

    /**
     * Creates a new {@code ShadowInscribable} using the given {@code ShadowNet}.
     *
     * @param shadowNet the parent {@code ShadowNet} this element belongs to
     */
    protected ShadowInscribable(ShadowNet shadowNet) {
        super(shadowNet);
        _elements = new HashSet<>();
    }

    /**
     * Adds the given {@code ShadowNetElement} to this {@code ShadowInscribable}.
     *
     * @param element the {@code ShadowNetElement} to be added as an inscription
     */
    public void add(ShadowNetElement element) {
        _elements.add(element);
    }

    /**
     * Removes the given {@code ShadowNetElement} from this {@code ShadowInscribable}.
     *
     * @param element the {@link ShadowNetElement} to be removed
     */
    public void remove(ShadowNetElement element) {
        _elements.remove(element);
    }

    /**
     * Returns an unmodifiable set containing the current inscription elements.
     *
     * @return a set of {@code ShadowNetElement} inscriptions
     */
    public Set<ShadowNetElement> elements() {
        return Collections.unmodifiableSet(_elements);
    }

    /**
     * Deserialization method, behaves like default readObject
     * method, additionally re-initializes the set of elements.
     *
     * @param in the object to read
     * @throws java.io.IOException if object can't be read
     * @throws ClassNotFoundException if class can't be found while reading the object
     */
    @Serial
    private void readObject(java.io.ObjectInputStream in)
        throws java.io.IOException, ClassNotFoundException
    {
        in.defaultReadObject();
        _elements = new HashSet<>();
    }
}