package de.renew.database;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serial;
import java.io.Serializable;

import de.renew.net.NetInstance;


/**
 * A net instance reference points to a net instance,
 * instead of containing it. This is required to serialize
 * tokens that contain net instances, so that the tokens
 * can be restored all again containing the same net instances,
 * if some of them contained the same ones.
 */
public class NetInstanceReference implements Serializable {

    /**
     * The net instance ID this reference points to.
     */
    private final String _netId;

    /**
     * The net instance this reference points to.
     * (temporarily memorized to resolve the reference)
     */
    private NetInstance _netInstance;

    /**
     * Creates the net instance reference.
     *
     * @param netID The net ID of the net instance this
     *              references points to.
     */
    public NetInstanceReference(String netID) {
        _netId = netID;
    }

    /**
     * Returns a string representation of the reference.
     */
    @Override
    public String toString() {
        return "[" + _netId + "]";
    }

    /**
     * Query the ID of the net instance. By default, the ID is a
     * simple number, but this is not guaranteed.
     * @return the current ID string
     */
    public String getID() {
        return _netId;
    }

    /**
     * Deserialization method to read an object from an
     * ObjectInputStream.
     *
     * @param stream The ObjectInputStream to read from.
     * @throws IOException if an input/output exception in the stream occurs
     * @throws ClassNotFoundException if the class is invalid
     */
    @Serial
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        _netInstance = ((NetInstanceResolutionInputStream) stream).getNetInstanceByNetID(getID());
    }

    /**
     * Deserialization method to replace the object
     * after it has been deserialized.
     * In this case, the NetInstanceReference is replaced
     * by the corresponding NetInstance.
     *
     * @return The corresponding NetInstance
     *         the reference points to.
     */
    @Serial
    private Object readResolve() {
        return _netInstance;
    }

    /**
     * Serialization method to write an object to an
     * ObjectOutputStream.
     * In this case, the NetInstance is not serialized
     * (it is serialized as null), because the deserialization
     * looks up the right net instance.
     *
     * @param stream The ObjectOutputStream to write to.
     * @throws IOException if an input/output exception in the stream occurs
     */
    @Serial
    private void writeObject(ObjectOutputStream stream) throws IOException {
        NetInstance netInstance = _netInstance;
        _netInstance = null;
        stream.defaultWriteObject();
        _netInstance = netInstance;

    }
}