package be.iminds.ilabt.jfed.experimenter_gui.editor.rspec_validation;

import be.iminds.ilabt.jfed.rspec.rspec_source.RequestRspecSource;
import javafx.application.Platform;
import javafx.stage.Window;

/**
 * User: twalcari
 * Date: 1/22/2015
 * Time: 16:43
 */
public class RspecValidationEngine {

    //order is important!
    private final RspecValidator[] validators = new RspecValidator[]{
            new ModelParsingValidator(), //check if model can be created must happen before all other tests!
            new CheckIfLosingDataValidator(),
            new InterfaceIdsValidator(),
            new DiskImageUrlValidator(),
            new ExperimentCommandNamespaceValidator(),
            new UniqueCliendIdValidator(),
            new IsRequestValidator(),
            new HasExpiresValidator(),
            new HasComponentManagerIdsValidator(),
            new AnsibleServiceValidator()
    };


    /**
     * Checks if there is data loss or other Rspec problem. Offers some options to fix things.
     *
     * @param reason the reason for the check. This does not change the tests, but does change the dialog options and text.
     * @return - for SWITCH_TO_VISUAL_EDITOR or RUN_EXPERIMENT:
     * - return an FXModelRspec if there is no data loss, or the user has accepted the warning.
     * - null to abort, so to revert to the RawRspecEditor.
     * - for checks (OPENED_FILE and CHECK_RSPEC):
     * - return null unless the user changed the rspec, in that case return a FXModelRspec
     */
    public RspecValidationResult validateRSpec(RspecCheckReason reason, RequestRspecSource requestRspecSource, Window dialogOwner) {
        assert Platform.isFxApplicationThread();

        boolean requestRspecSourceChanged = false;

        for (RspecValidator validator : validators) {
            RspecValidationResult validationResult = validator.validateRSpec(reason, requestRspecSource, dialogOwner);

            if (validationResult != null) {
                if (validationResult.isAbort())
                    return validationResult;
                else {
                    requestRspecSource = validationResult.getReplacementRequestRspecSource();
                    requestRspecSourceChanged = true;
                    //continue with the other validations
                }
            }
        }

        if (requestRspecSourceChanged) {
            return new RspecValidationResult(requestRspecSource, false);
        } else
            return null;
    }
}
