import kdl_rs


# from kdl_rs' example directory
kdl_text = """
document {
    info {
        title "KDL Schema" lang=en
        description "KDL Schema KDL schema in KDL" lang=en
        author "Kat Marchán" {
            link "https://github.com/zkat" rel=self
        }
        contributor "Lars Willighagen" {
            link "https://github.com/larsgw" rel=self
        }
        link "https://github.com/zkat/kdl" rel=documentation
        license "Creative Commons Attribution-ShareAlike 4.0 International License" spdx=CC-BY-SA-4.0 {
            link "https://creativecommons.org/licenses/by-sa/4.0/" lang=en
        }
        published "2021-08-31"
        modified "2021-09-01"
    }
    node document {
        min 1
        max 1
        children id=node-children {
            node node-names id=node-names-node description="Validations to apply specifically to arbitrary node names" {
                children ref=#"[id="validations"]"#
            }
            node other-nodes-allowed id=other-nodes-allowed-node description="Whether to allow child nodes other than the ones explicitly listed. Defaults to '#false'." {
                max 1
                value {
                    min 1
                    max 1
                    type boolean
                }
            }
            node tag-names description="Validations to apply specifically to arbitrary type tag names" {
                children ref=#"[id="validations"]"#
            }
            node other-tags-allowed description="Whether to allow child node tags other than the ones explicitly listed. Defaults to '#false'." {
                max 1
                value {
                    min 1
                    max 1
                    type boolean
                }
            }
            node info description="A child node that describes the schema itself." {
                children {
                    node title description="The title of the schema or the format it describes" {
                        value description="The title text" {
                            type string
                            min 1
                            max 1
                        }
                        prop lang id=info-lang description="The language of the text" {
                            type string
                        }
                    }
                    node description description="A description of the schema or the format it describes" {
                        value description="The description text" {
                            type string
                            min 1
                            max 1
                        }
                        prop ref=#"[id="info-lang"]"#
                    }
                    node author description="Author of the schema" {
                        value id=info-person-name description="Person name" {
                            type string
                            min 1
                            max 1
                        }
                        prop orcid id=info-orcid description="The ORCID of the person" {
                            type string
                            pattern #"\d{4}-\d{4}-\d{4}-\d{4}"#
                        }
                        children {
                            node ref=#"[id="info-link"]"#
                        }
                    }
                    node contributor description="Contributor to the schema" {
                        value ref=#"[id="info-person-name"]"#
                        prop ref=#"[id="info-orcid"]"#
                        children {
                            node ref=#"[id="info-link"]"#
                        }
                    }
                    node link id=info-link description="Links to itself, and to sources describing it" {
                        value description="A URL that the link points to" {
                            type string
                            format url irl
                            min 1
                            max 1
                        }
                        prop rel description="The relation between the current entity and the URL" {
                            type string
                            enum self documentation
                        }
                        prop ref=#"[id="info-lang"]"#
                    }
                    node license description="The license(s) that the schema is licensed under" {
                        value description="Name of the used license" {
                            type string
                            min 1
                            max 1
                        }
                        prop spdx description="An SPDX license identifier" {
                            type string
                        }
                        children {
                            node ref=#"[id="info-link"]"#
                        }
                    }
                    node published description="When the schema was published" {
                        value description="Publication date" {
                            type string
                            format date
                            min 1
                            max 1
                        }
                        prop time id=info-time description="A time to accompany the date" {
                            type string
                            format time
                        }
                    }
                    node modified description="When the schema was last modified" {
                        value description="Modification date" {
                            type string
                            format date
                            min 1
                            max 1
                        }
                        prop ref=#"[id="info-time"]"#
                    }
                    node version description="The version number of this version of the schema" {
                        value description="Semver version number" {
                            type string
                            pattern #"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"#
                            min 1
                            max 1
                        }
                    }
                }
            }
            node tag id=tag-node description="A tag belonging to a child node of `document` or another node." {
                value description="The name of the tag. If a tag name is not supplied, the node rules apply to _all_ nodes belonging to the parent." {
                    type string
                    max 1
                }
                prop description description="A description of this node's purpose." {
                    type string
                }
                prop id description="A globally-unique ID for this node." {
                    type string
                }
                prop ref description="A globally unique reference to another node." {
                    type string
                    format kdl-query
                }
                children {
                    node ref=#"[id="node-names-node"]"#
                    node ref=#"[id="other-nodes-allowed-node"]"#
                    node ref=#"[id="node-node"]"#
                }
            }
            node node id=node-node description="A child node belonging either to `document` or to another `node`. Nodes may be anonymous." {
                value description="The name of the node. If a node name is not supplied, the node rules apply to _all_ nodes belonging to the parent." {
                    type string
                    max 1
                }
                prop description description="A description of this node's purpose." {
                    type string
                }
                prop id description="A globally-unique ID for this node." {
                    type string
                }
                prop ref description="A globally unique reference to another node." {
                    type string
                    format kdl-query
                }
                children {
                    node prop-names description="Validations to apply specifically to arbitrary property names" {
                        children ref=#"[id="validations"]"#
                    }
                    node other-props-allowed description="Whether to allow properties other than the ones explicitly listed. Defaults to '#false'." {
                        max 1
                        value {
                            min 1
                            max 1
                            type boolean
                        }
                    }
                    node min description="minimum number of instances of this node in its parent's children." {
                        max 1
                        value {
                            min 1
                            max 1
                            type number
                        }
                    }
                    node max description="maximum number of instances of this node in its parent's children." {
                        max 1
                        value {
                            min 1
                            max 1
                            type number
                        }
                    }
                    node ref=#"[id="value-tag-node"]"#
                    node prop id="prop-node" description="A node property key/value pair." {
                        value description="The property key." {
                            type string
                        }
                        prop id description="A globally-unique ID of this property." {
                            type string
                        }
                        prop ref description="A globally unique reference to another property node." {
                            type string
                            format kdl-query
                        }
                        prop description description="A description of this property's purpose." {
                            type string
                        }
                        children description="Property-specific validations." {
                            node required description="Whether this property is required if its parent is present." {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type boolean
                                }
                            }
                        }
                        children id=validations description="General value validations." {
                            node tag id=value-tag-node description="The tags associated with this value" {
                                max 1
                                children ref=#"[id="validations"]"#
                            }
                            node type description="The type for this prop's value." {
                                max 1
                                value {
                                    min 1
                                    type string
                                }
                            }
                            node enum description="An enumeration of possible values" {
                                max 1
                                value description="Enumeration choices" {
                                    min 1
                                }
                            }
                            node pattern description="PCRE (Regex) pattern or patterns to test prop values against." {
                                value {
                                    min 1
                                    type string
                                }
                            }
                            node min-length description="Minimum length of prop value, if it's a string." {
                                max 1
                                value {
                                    min 1
                                    type number
                                }
                            }
                            node max-length description="Maximum length of prop value, if it's a string." {
                                max 1
                                value {
                                    min 1
                                    type number
                                }
                            }
                            node format description="Intended data format." {
                                max 1
                                value {
                                    min 1
                                    type string
                                    // https://json-schema.org/understanding-json-schema/reference/string.html#format
                                    enum date-time date time duration decimal currency country-2 country-3 country-subdivision email idn-email hostname idn-hostname ipv4 ipv6 url url-reference irl irl-reference url-template regex uuid kdl-query i8 i16 i32 i64 u8 u16 u32 u64 isize usize f32 f64 decimal64 decimal128
                                }
                            }
                            node % description="Only used for numeric values. Constrains them to be multiples of the given number(s)" {
                                max 1
                                value {
                                    min 1
                                    type number
                                }
                            }
                            node gt description="Only used for numeric values. Constrains them to be greater than the given number(s)" {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type number
                                }
                            }
                            node gte description="Only used for numeric values. Constrains them to be greater than or equal to the given number(s)" {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type number
                                }
                            }
                            node lt description="Only used for numeric values. Constrains them to be less than the given number(s)" {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type number
                                }
                            }
                            node lte description="Only used for numeric values. Constrains them to be less than or equal to the given number(s)" {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type number
                                }
                            }
                        }
                    }
                    node value id=value-node description="one or more direct node values" {
                        prop id description="A globally-unique ID of this value." {
                            type string
                        }
                        prop ref description="A globally unique reference to another value node." {
                            type string
                            format kdl-query
                        }
                        prop description description="A description of this property's purpose." {
                            type string
                        }
                        children ref=#"[id="validations"]"#
                        children description="Node value-specific validations" {
                            node min description="minimum number of values for this node." {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type number
                                }
                            }
                            node max description="maximum number of values for this node." {
                                max 1
                                value {
                                    min 1
                                    max 1
                                    type number
                                }
                            }
                        }
                    }
                    node children id=children-node {
                        prop id description="A globally-unique ID of this children node." {
                            type string
                        }
                        prop ref description="A globally unique reference to another children node." {
                            type string
                            format kdl-query
                        }
                        prop description description="A description of this these children's purpose." {
                            type string
                        }
                        children ref=#"[id="node-children"]"#
                    }
                }
            }
            node definitions description="Definitions to reference in parts of the top-level nodes" {
                children {
                    node ref=#"[id="node-node"]"#
                    node ref=#"[id="value-node"]"#
                    node ref=#"[id="prop-node"]"#
                    node ref=#"[id="children-node"]"#
                    node ref=#"[id="tag-node"]"#
                }
            }
        }
    }
}
"""


def main():
    doc = kdl_rs.parse(kdl_text)
    print("KDL Source:")
    print("-----------", end="")
    print(doc.to_string())


if __name__ == "__main__":
    main()
