(.require
 [library
  [lux (.except)
   ["$" documentation]
   [data
    [text (.only \n)
     ["%" \\format (.only format)]]
    [collection
     ["[0]" list]]]
   [meta
    [macro
     ["[0]" template]]]]]
 ["[0]" \\parser]
 [\\library
  ["[0]" /]])

(`` (def \\parser
      (List $.Documentation)
      (list ($.module \\parser._
                      "")

            ($.definition \\parser.unconsumed_input)
            ($.definition \\parser.empty_input)
            ($.definition \\parser.unexpected_value)
            ($.definition \\parser.value_mismatch)

            ($.definition (\\parser.Parser it)
              "A JSON parser.")

            ($.definition \\parser.result
              (format "Executes the parser against a JSON object."
                      \n "Verifies that all of the JSON was consumed by the parser.")
              [(result parser json)])

            ($.definition \\parser.any
              "Just returns the JSON input without applying any logic.")

            (,, (with_template [<name>]
                  [(`` ($.definition <name>
                         (format "Reads a JSON value as " (,, (template.text [<name>])) ".")))]

                  [\\parser.null]
                  [\\parser.boolean]
                  [\\parser.number]
                  [\\parser.string]
                  ))

            (,, (with_template [<test> <check> <read>]
                  [(`` ($.definition <test>
                         (format "Asks whether a JSON value is a " (,, (template.text [<read>])) ".")))
                   (`` ($.definition <check>
                         (format "Ensures a JSON value is a " (,, (template.text [<read>])) ".")))]

                  [\\parser.boolean? \\parser.this_boolean ..boolean]
                  [\\parser.number?  \\parser.this_number  ..number]
                  [\\parser.string?  \\parser.this_string  ..string]
                  ))

            ($.definition \\parser.nullable
              "Enhances parser by adding NULL-handling."
              [(nullable parser)])

            ($.definition \\parser.array
              "Parses the contents of a JSON array."
              [(array parser)])

            ($.definition \\parser.object
              (format "Parses the contents of a JSON object."
                      \n "Use this with the 'field' combinator.")
              [(object parser)])

            ($.definition \\parser.field
              (format "Parses a field inside a JSON object."
                      \n "Use this inside the 'object' combinator.")
              [(field field_name parser)])

            ($.definition \\parser.dictionary
              "Parses a dictionary-like JSON object.")
            )))

(`` (.def .public documentation
      (List $.Documentation)
      (list.partial ($.module /._
                              (format "Functionality for reading and writing values in the JSON format."
                                      \n "For more information, please see: http://www.json.org/"))

                    ($.definition /.Null)
                    ($.definition /.Boolean)
                    ($.definition /.Number)
                    ($.definition /.String)
                    ($.definition /.JSON)
                    ($.definition /.Array)
                    ($.definition /.Object)
                    ($.definition /.null?)
                    ($.definition /.object)
                    ($.definition /.equivalence)
                    ($.definition /.format)
                    ($.definition /.codec)

                    ($.definition /.json
                      "A simple way to produce JSON literals."
                      ["null"
                       (json #null)]
                      ["true"
                       (json #1)]
                      ["123.456"
                       (json +123.456)]
                      ["'this is a string'"
                       (json "this is a string")]
                      ["['this' 'is' 'an' 'array']"
                       (json ["this" "is" "an" "array"])]
                      ["{'this' 'is', 'an' 'object'}"
                       (json {"this" "is" "an" "object"})])

                    ($.definition /.fields
                      "Get all the fields in a JSON object."
                      [(fields json)])

                    ($.definition /.field
                      "A JSON object field getter."
                      [(field key json)])

                    ($.definition /.has
                      "A JSON object field setter."
                      [(has key value json)])

                    (,, (with_template [<name> <desc>]
                          [($.definition <name>
                             (format "A JSON object field getter for " <desc> "."))]

                          [/.boolean_field "booleans"]
                          [/.number_field  "numbers"]
                          [/.string_field  "strings"]
                          [/.array_field   "arrays"]
                          [/.object_field  "objects"]
                          ))

                    ..\\parser
                    )))
