"""
    pygments.lexers.dns
    ~~~~~~~~~~~~~~~~~~~

    Pygments lexers for DNS

    :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

import re

from pygments.token import Comment, Operator, Keyword, Name, String, Number, Punctuation, Whitespace, Literal
from pygments.lexer import RegexLexer, bygroups, include

__all__ = ["DnsZoneLexer"]


CLASSES = [
    "IN",
    "CS",
    "CH",
    "HS",
]

CLASSES_RE = "(" + "|".join(CLASSES) + ")"


class DnsZoneLexer(RegexLexer):

    """
    Lexer for DNS zone file

    .. versionadded:: 2.16
    """

    flags = re.MULTILINE

    name = "Zone"
    aliases = ["zone"]
    filenames = ["*.zone"]
    url = "https://datatracker.ietf.org/doc/html/rfc1035"
    mimetypes = ["text/dns"]

    tokens = {
        "root": [
            # Empty/comment line:
            (r"([ \t]*)(;.*)(\n)", bygroups(Whitespace, Comment.Single, Whitespace)),
            # Special directives:
            (r"^\$ORIGIN\b", Keyword, "values"),
            (r"^\$TTL\b", Keyword, "values"),
            (r"^\$INCLUDE\b", Comment.Preproc, "include"),
            # TODO, $GENERATE https://bind9.readthedocs.io/en/v9.18.14/chapter3.html#soa-rr
            (r"^\$[A-Z]+\b", Keyword, "values"),
            # Records:
            # <domain-name> [<TTL>] [<class>] <type> <RDATA> [<comment>]
            (
                r"^(@)([ \t]+)(?:([0-9]+[smhdw]?)([ \t]+))?(?:" + CLASSES_RE + "([ \t]+))?([A-Z]+)([ \t]+)",
                bygroups(
                    Operator, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace
                ),
                "values",
            ),
            (
                r"^([^ \t\n]*)([ \t]+)(?:([0-9]+[smhdw]?)([ \t]+))?(?:" + CLASSES_RE + "([ \t]+))?([A-Z]+)([ \t]+)",
                bygroups(
                    Name, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace
                ),
                "values",
            ),
            # <domain-name> [<class>] [<TTL>] <type> <RDATA> [<comment>]
            (
                r"^(Operator)([ \t]+)(?:" + CLASSES_RE + "([ \t]+))?(?:([0-9]+[smhdw]?)([ \t]+))?([A-Z]+)([ \t]+)",
                bygroups(
                    Name, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace
                ),
                "values",
            ),
            (
                r"^([^ \t\n]*)([ \t]+)(?:" + CLASSES_RE + "([ \t]+))?(?:([0-9]+[smhdw]?)([ \t]+))?([A-Z]+)([ \t]+)",
                bygroups(
                    Name, Whitespace, Number.Integer, Whitespace, Name.Class, Whitespace, Keyword.Type, Whitespace
                ),
                "values",
            ),
        ],
        # Parsing values:
        "values": [
            (r"\n", Whitespace, "#pop"),
            (r"\(", Punctuation, "nested"),
            include("simple-values"),
        ],
        # Parsing nested values (...):
        "nested": [
            (r"\)", Punctuation, "#pop"),
            include("simple-values"),
        ],
        # Parsing values:
        "simple-values": [
            (r"(;.*)(\n)", bygroups(Comment.Single, Whitespace)),
            (r"[ \t]+", Whitespace),
            (r"@\b", Operator),
            ('"', String, "string"),
            (r"[0-9]+[smhdw]?$", Number.Integer),
            (r"([0-9]+[smhdw]?)([ \t]+)", bygroups(Number.Integer, Whitespace)),
            (r"\S+", Literal),
        ],
        "include": [
            (
                r"([ \t]+)([^ \t\n]+)([ \t]+)([-\._a-zA-Z]+)([ \t]+)(;.*)?$",
                bygroups(Whitespace, Comment.PreprocFile, Whitespace, Name, Whitespace, Comment.Single),
                "#pop",
            ),
            (r"([ \t]+)([^ \t\n]+)([ \t\n]+)$", bygroups(Whitespace, Comment.PreprocFile, Whitespace), "#pop"),
        ],
        "string": [
            (r'\\"', String),
            (r'"', String, "#pop"),
            (r'[^"]+', String),
        ],
    }

    def analyse_text(text):
        return text.startswith("$ORIGIN")
