package ru.yandex.direct.api.v5.common.validation;

import com.yandex.direct.api.v5.general.GetRequestGeneral;
import com.yandex.direct.api.v5.general.LimitOffset;

import ru.yandex.direct.api.v5.validation.DefectType;
import ru.yandex.direct.api.v5.validation.DefectTypes;
import ru.yandex.direct.validation.builder.ItemValidationBuilder;
import ru.yandex.direct.validation.builder.When;
import ru.yandex.direct.validation.result.ValidationResult;

import static ru.yandex.direct.api.v5.common.constants.GetRequestCommonConstants.DEFAULT_MAX_LIMIT;
import static ru.yandex.direct.api.v5.common.constants.GetRequestCommonConstants.DEFAULT_MAX_OFFSET;
import static ru.yandex.direct.api.v5.common.constants.GetRequestCommonConstants.DEFAULT_MIN_LIMIT;
import static ru.yandex.direct.api.v5.common.constants.GetRequestCommonConstants.DEFAULT_MIN_OFFSET;
import static ru.yandex.direct.api.v5.validation.constraints.Constraints.notGreaterThan;
import static ru.yandex.direct.api.v5.validation.constraints.Constraints.notLessThan;

public class GetRequestGeneralValidator {

    public static <T extends GetRequestGeneral> ValidationResult<T, DefectType> validateRequest(T request) {
        ItemValidationBuilder<T, DefectType> vb = ItemValidationBuilder.of(request);
        vb.item(request.getPage(), "Page")
                .checkBy(GetRequestGeneralValidator::validatePage, When.notNull());
        return vb.getResult();
    }

    private static ValidationResult<LimitOffset, DefectType> validatePage(LimitOffset limitOffset) {
        ItemValidationBuilder<LimitOffset, DefectType> vb = ItemValidationBuilder.of(limitOffset);
        vb.item(limitOffset.getLimit(), "Limit")
                .check(notLessThan(DEFAULT_MIN_LIMIT), DefectTypes.incorrectPageNonPositiveLimit())
                .check(notGreaterThan(DEFAULT_MAX_LIMIT), DefectTypes.incorrectPageLimitExceeded(DEFAULT_MAX_LIMIT));
        vb.item(limitOffset.getOffset(), "Offset")
                .check(notLessThan(DEFAULT_MIN_OFFSET), DefectTypes.incorrectPageNegativeOffset())
                .check(notGreaterThan(DEFAULT_MAX_OFFSET), DefectTypes.incorrectPageOffsetExceeded(DEFAULT_MAX_OFFSET));
        return vb.getResult();
    }

    /**
     * Вызов проверки запроса на выход limit и offset страницы за допустимые границы
     *
     * @param request {@link GetRequestGeneral}
     * @return Результат валидации, хранящий ошибки в виде DefectType {@link ValidationResult}{@link DefectType}
     */
    public static <T extends GetRequestGeneral> ValidationResult<T, DefectType> validateRequestWithDefectTypes(
            T request) {
        ItemValidationBuilder<T, DefectType> vb = ItemValidationBuilder.of(request);
        vb.item(request.getPage(), "Page")
                .checkBy(GetRequestGeneralValidator::validatePage, When.notNull());
        return vb.getResult();
    }
}
