package com.wishurgift.entry.validator;

import java.util.ArrayList;
import java.util.List;

public abstract class Validator<T> {

    private List<String> errors = new ArrayList<>();

    private String prefix = "";

    /**
     * Verfie si l'objet passé en parametre est valide à l'aide d'assertion
     *
     * @param data L'objet à tester
     */
    protected abstract void validate(T data);

    protected void clearErrors() {
        errors.clear();
    }

    public boolean isValid(T data) {
        clearErrors();
        validate(data);
        return haveNoErrors();
    }

    public boolean isValid(List<T> data) {
        clearErrors();
        for (int i = 0; i < data.size(); i++) {
            prefix = i + ": ";
            validate(data.get(i));
        }
        prefix = "";
        return haveNoErrors();
    }

    public boolean isNotValid(T data) {
        return !isValid(data);
    }

    public boolean isNotValid(List<T> data) {
        return !isValid(data);
    }

    public String getError(int index) {
        if (index < 0 || index >= errors.size()) {
            return null;
        }
        return errors.get(index);
    }

    public List<String> getAllErrors() {
        return new ArrayList<>(errors);
    }

    public boolean haveNoErrors() {
        return errors.isEmpty();
    }

    public boolean haveErrors() {
        return !haveNoErrors();
    }

    public int getErrorNumber() {
        return errors.size();
    }

    protected boolean assertTrue(boolean test, String errorMessage) {
        if (!test) {
            errors.add(prefix + errorMessage);
        }
        return test;
    }

    protected boolean assertTrue(boolean test, List<String> errorsMessage) {
        if (!test) {
            errorsMessage.forEach(msg -> errors.add(prefix + msg));
        }
        return test;
    }

    protected boolean assertFalse(boolean test, String errorMessage) {
        return assertTrue(!test, errorMessage);
    }

    protected boolean assertFalse(boolean test, List<String> errorsMessage) {
        return assertTrue(!test, errorsMessage);
    }

}
