from zmqtt.errors import MQTTInvalidTopicError


def validate_publish(topic: str) -> None:
    if not topic:
        msg = "Topic must not be empty"
        raise MQTTInvalidTopicError(msg)
    if "#" in topic or "+" in topic:
        msg = f"Wildcards not allowed in publish topic: {topic!r}"
        raise MQTTInvalidTopicError(msg)
    if "$" in topic[1:]:
        msg = f"'$' is only valid as the first character of a topic: {topic!r}"
        raise MQTTInvalidTopicError(msg)


def validate_subscribe_topic(topic: str) -> None:
    if not topic:
        msg = "Topic filter must not be empty"
        raise MQTTInvalidTopicError(msg)
    if "$" in topic[1:]:
        msg = f"'$' is only valid as the first character of a topic filter: {topic!r}"
        raise MQTTInvalidTopicError(msg)
    if "#" in topic:
        idx = topic.index("#")
        if idx != len(topic) - 1:
            msg = f"'#' must be the last character in a topic filter: {topic!r}"
            raise MQTTInvalidTopicError(msg)
        if idx > 0 and topic[idx - 1] != "/":
            msg = f"'#' must be preceded by '/' in a topic filter: {topic!r}"
            raise MQTTInvalidTopicError(msg)
    for level in topic.split("/"):
        if "+" in level and level != "+":
            msg = f"'+' must occupy an entire topic level in filter: {topic!r}"
            raise MQTTInvalidTopicError(msg)


def validate_response_topic(topic: str) -> None:
    validate_publish(topic)
