package p.studio.controls.forms;

import java.util.Objects;
import java.util.function.UnaryOperator;

public final class StudioFormSession<T> {
    private T source;
    private T draft;
    private StudioFormMode mode;

    public StudioFormSession(T source) {
        replaceSource(source);
    }

    public void replaceSource(T source) {
        this.source = Objects.requireNonNull(source, "source");
        this.draft = source;
        this.mode = StudioFormMode.READ_ONLY;
    }

    public T source() {
        return source;
    }

    public T draft() {
        return draft;
    }

    public StudioFormMode mode() {
        return mode;
    }

    public boolean isDirty() {
        return !Objects.equals(source, draft);
    }

    public void beginEdit() {
        mode = StudioFormMode.EDITING;
    }

    public void setDraft(T draft) {
        this.draft = Objects.requireNonNull(draft, "draft");
    }

    public void updateDraft(UnaryOperator<T> update) {
        draft = Objects.requireNonNull(update, "update").apply(draft);
        draft = Objects.requireNonNull(draft, "draft");
    }

    public void resetDraft() {
        draft = source;
    }

    public void cancelEdit() {
        resetDraft();
        mode = StudioFormMode.READ_ONLY;
    }

    public T apply() {
        source = draft;
        mode = StudioFormMode.READ_ONLY;
        return source;
    }
}
