... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.using
 [library
  [lux (.except Label
                or and for same? not)
   [data
    ["[0]" text (.only)
     ["%" \\injection]]]
   [math
    [number
     [/64
      ["i" integer]]]]
   [macro
    ["[0]" template]]
   [type
    ["[0]" nominal]]
   [world
    ["[0]" locale (.only Locale)]]]]
 ["[0]" //
  ["[1][0]" id (.only ID)]
  ["[1][0]" class (.only Class)]
  [//
   [html
    ["[0]" tag]]]])

(every .public Label Text)

(every .public Attribute Label)

(nominal.every .public (Generic brand) Any)

(template.with [<generic> <brand>]
  [(nominal.every <brand> Any)
   (every .public <generic> (Generic <brand>))]

  [[Can_Chain Can_Chain']
   [Cannot_Chain Cannot_Chain']])

(nominal.every .public Unique Any)
(nominal.every .public Specific Any)
(nominal.every .public Composite Any)

(nominal.every .public (Selector kind)
  Text

  (the .public selector
    (-> (Selector Any) Text)
    (|>> nominal.as))

  (the .public any
    (Selector Cannot_Chain)
    (nominal.of "*"))

  (the .public tag
    (-> tag.Name (Selector Cannot_Chain))
    (|>> nominal.of))

  (template.with [<name> <type> <prefix> <kind> <out>]
    [(the .public <name>
       (-> <type> (Selector <kind>))
       (|>> <out>
            (text <prefix>)
            nominal.of))]

    [[id ID "#" Unique //id.id]
     [class Class "." Can_Chain //class.class]])

  (template.with [<right> <left> <combinator>+]
    [(template.with [<combinator> <name>]
       [(the .public (<name> right left)
          (-> (Selector <right>) (Selector <left>) (Selector Composite))
          (nominal.of
           (text (nominal.as left)
                 <combinator>
                 (nominal.as right))))]

       <combinator>+)]

    [[Can_Chain (Generic Any)
      [["" and]]]
     [Specific (Generic Any)
      [["" at]]]
     [Unique (Generic Any)
      [["" for]]]
     [Any Any
      [["," or]
       [" " in]
       [">" sub]
       ["+" next]
       ["~" later]]]])

  (every .public (Specializer kind)
    (-> (Selector kind) (Selector (Generic Any)) (Selector Composite)))

  (every .public Combinator
    (-> (Selector Any) (Selector Any) (Selector Composite)))

  (the .public (with? attribute)
    (-> Attribute (Selector Can_Chain))
    (nominal.of
     (text "[" attribute "]")))

  (template.with [<check> <name>]
    [(the .public (<name> attribute value)
       (-> Attribute Text (Selector Can_Chain))
       (nominal.of
        (text "[" attribute <check> value "]")))]

    [["=" same?]
     ["~=" has?]
     ["|=" has_start?]
     ["^=" starts?]
     ["$=" ends?]
     ["*=" contains?]])

  (template.with [<kind> <pseudo>+]
    [(template.with [<name> <pseudo>]
       [(the .public <name>
          (Selector <kind>)
          (nominal.of <pseudo>))]

       <pseudo>+)]

    [[Can_Chain
      [[active ":active"]
       [checked ":checked"]
       [default ":default"]
       [disabled ":disabled"]
       [empty ":empty"]
       [enabled ":enabled"]
       [first_child ":first-child"]
       [first_of_type ":first-of-type"]
       [focused ":focus"]
       [hovered ":hover"]
       [in_range ":in-range"]
       [indeterminate ":indeterminate"]
       [invalid ":invalid"]
       [last_child ":last-child"]
       [last_of_type ":last-of-type"]
       [link ":link"]
       [only_of_type ":only-of-type"]
       [only_child ":only-child"]
       [optional ":optional"]
       [out_of_range ":out-of-range"]
       [read_only ":read-only"]
       [read_write ":read-write"]
       [required ":required"]
       [root ":root"]
       [target ":target"]
       [valid ":valid"]
       [visited ":visited"]]]
     
     [Specific
      [[after "::after"]
       [before "::before"]
       [first_letter "::first-letter"]
       [first_line "::first-line"]
       [placeholder "::placeholder"]
       [selection "::selection"]]]])

  (the .public (language locale)
    (-> Locale (Selector Can_Chain))
    (|> locale
        locale.code
        (text.enclosed ["(" ")"])
        (text ":lang")
        nominal.of))

  (the .public not
    (-> (Selector Any) (Selector Can_Chain))
    (|>> nominal.as
         (text.enclosed ["(" ")"])
         (text ":not")
         nominal.of))

  (nominal.every .public Index
    Text

    (the .public index
      (-> Natural Index)
      (|>> %.natural
           nominal.of))

    (template.with [<name> <index>]
      [(the .public <name>
         Index
         (nominal.of <index>))]
      
      [[odd "odd"]
       [even "even"]])

    (every .public Formula
      (Record
       [#constant Integer
        #variable Integer]))

    (the .public (formula input)
      (-> Formula Index)
      (let [(open "_[0]") input]
        (nominal.of
         (text (if (i.< +0 _#variable)
                   (%.integer _#variable)
                   (%.natural (.natural _#variable)))
               (%.integer _#constant)))))
    
    (template.with [<name> <pseudo>]
      [(the .public (<name> index)
         (-> Index (Selector Can_Chain))
         (|> (nominal.as index)
             (text.enclosed ["(" ")"])
             (text <pseudo>)
             (nominal.of Selector)))]

      [[nth_child ":nth-child"]
       [nth_last_child ":nth-last-child"]
       [nth_of_type ":nth-of-type"]
       [nth_last_of_type ":nth-last-of-type"]])
    )
  )
