package ru.yandex.qe.dispenser.ws.common.domain.errors;

import java.util.Objects;

import org.jetbrains.annotations.NotNull;

public final class TypedError<E> {

    @NotNull
    private final E error;
    @NotNull
    private final ErrorType type;

    private TypedError(@NotNull final E error, @NotNull final ErrorType type) {
        this.error = error;
        this.type = type;
    }

    @NotNull
    public static <T> TypedError<T> invalid(@NotNull final T error) {
        Objects.requireNonNull(error, "Error is required.");
        return new TypedError<>(error, ErrorType.INVALID);
    }

    @NotNull
    public static <T> TypedError<T> forbidden(@NotNull final T error) {
        Objects.requireNonNull(error, "Error is required.");
        return new TypedError<>(error, ErrorType.FORBIDDEN);
    }

    @NotNull
    public static <T> TypedError<T> badRequest(@NotNull final T error) {
        Objects.requireNonNull(error, "Error is required.");
        return new TypedError<>(error, ErrorType.BAD_REQUEST);
    }

    @NotNull
    public static <T> TypedError<T> notFound(@NotNull final T error) {
        Objects.requireNonNull(error, "Error is required.");
        return new TypedError<>(error, ErrorType.NOT_FOUND);
    }

    @NotNull
    public static <T> TypedError<T> conflict(@NotNull final T error) {
        Objects.requireNonNull(error, "Error is required.");
        return new TypedError<>(error, ErrorType.CONFLICT);
    }

    @NotNull
    public E getError() {
        return error;
    }

    @NotNull
    public ErrorType getType() {
        return type;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final TypedError<?> that = (TypedError<?>) o;
        return Objects.equals(error, that.error) &&
                type == that.type;
    }

    @Override
    public int hashCode() {
        return Objects.hash(error, type);
    }

    @Override
    public String toString() {
        return "TypedError{" +
                "error=" + error +
                ", type=" + type +
                '}';
    }

}
