package org.jboss.resteasy.plugins.validation;

import java.util.Iterator;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ElementKind;
import jakarta.validation.Path.Node;

import org.jboss.resteasy.api.validation.ConstraintType;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import org.jboss.resteasy.spi.validation.ConstraintTypeUtil;

public class ConstraintTypeUtilImpl implements ConstraintTypeUtil {

    @Override
    public ConstraintType.Type getConstraintType(Object o) {
        if (!(o instanceof ConstraintViolation)) {
            throw new RuntimeException(Messages.MESSAGES.unknownObjectPassedAsConstraintViolation(o));
        }
        ConstraintViolation<?> v = ConstraintViolation.class.cast(o);

        Iterator<Node> nodes = v.getPropertyPath().iterator();
        Node firstNode = nodes.next();

        switch (firstNode.getKind()) {
            case BEAN:
                return ConstraintType.Type.CLASS;
            case CONSTRUCTOR:
            case METHOD:
                Node secondNode = nodes.next();

                if (secondNode.getKind() == ElementKind.PARAMETER || secondNode.getKind() == ElementKind.CROSS_PARAMETER) {
                    return ConstraintType.Type.PARAMETER;
                } else if (secondNode.getKind() == ElementKind.RETURN_VALUE) {
                    return ConstraintType.Type.RETURN_VALUE;
                } else {
                    throw new RuntimeException(Messages.MESSAGES.unexpectedPathNodeViolation(secondNode.getKind()));
                }
            case PROPERTY:
                return ConstraintType.Type.PROPERTY;
            case CROSS_PARAMETER:
            case PARAMETER:
            case RETURN_VALUE:
            case CONTAINER_ELEMENT: // we shouldn't encounter these element types at the root
            default:
                throw new RuntimeException(Messages.MESSAGES.unexpectedPathNode(firstNode.getKind()));
        }
    }
}
