package leigh.elements.sdk;

import leigh.elements.sdk.actions.*;
import leigh.elements.sdk.type1.Element;
import leigh.elements.sdk.type1.ScreenElement;
import leigh.eo.EO;
import leigh.mecha.lang.FutureResult;

import java.util.UUID;

/**
 * Classes implementing this interface provide mechanics for processing an Elements screen.
 *
 * @author Alex Leigh
 */
public interface AppScreenInstance {
    /**
     * Return a data frame to the caller which has previously been stored for this screen.
     */
    AppDataFrame getDataFrame(UUID id);

    /**
     * Put a data frame into this screen. If a data frame with the given ID already exists, it will be replaced
     * with the provided frame. The frame is identified via the <code>getId()</code> method.
     */
    void putDataFrame(AppDataFrame frame);

    /**
     * Return the next sequence value for the given sequence name.
     */
    Integer sequenceNextVal(String key);

    /**
     * Build the screen-graph from scratch. This builds the entire screen, and so returns a
     * {@link ScreenElement}. The screen that is returned reflects the current
     * state of the model at the time it is called.
     */
    Element build();

    /**
     * Return the element factory associated with this screen. This is required when an element needs to know
     * how to conditionally produce more elements (and therefore needs the factory associated with the screen).
     */
    ElementFactory getFactory();

    /**
     * Synchronously call a function on this screen. The result is returned.
     */
    FutureResult<ScreenAction> call(String cmdTarget, String cmdName);

    void setMessageListener(MessageActionListener listener);

    /**
     * Register a popup screen listener with this screen instance. If a popup should be shown to the user, this
     * method will be called.
     */

    void setModalScreenListener(ModalScreenActionListener listener);

    void processAction(ScreenAction result);

    void setScreenCloseListener(ScreenCloseActionListener screenCloseListener);

    void setScreenOpenListener(ScreenOpenListener screenOpenListener);

    /**
     * Something, somewhere, has changed, and now the screen should update. Such changes could include changes
     * to the contents of any of the datasources, changes to the elements screen graph, etc. All visual elements should
     * re-process themselves to ensure they are displaying the current, correct values. This method could
     * be called by UI elements on the screen, or other, outside factors.
     * <p>
     * Calling this method is potentially expensive, so if there are many updates made, it is best of the caller
     * batches the updates and then calls the update method only one time.
     */
    void update() throws Exception;

    /**
     * Return the {@link AppInstance} object to which this screen belongs.
     */
    AppInstance getAppInstance();

    Theme getTheme();

    /**
     * Elements should call this method when they are activated (focused), and that event is going to have some
     * impact on the screen. It is expected that this method may be called to activate an element which is
     * already active.
     */
    void activateElement(Object obj);

    EO createNewRecord();
}
