(.module: [library [lux (#- Name Type) [abstract [monad (#+ do)] [equivalence (#+ Equivalence)]] [control [pipe (#+ do> case>)] ["." try (#+ Try)] ["." exception (#+ exception:)] ["<>" parser ["<.>" xml (#+ Parser)] ["<.>" text]] [concurrency ["." async (#+ Async)]]] [data ["." product] ["." text ["%" format] [encoding ["." utf8]]] [format ["." xml (#+ XML)]] [collection ["." list ("#\." functor)]]] [math [number ["n" nat]]] ["." time (#+ Time) ["." instant (#+ Instant)] ["." date (#+ Date)] ["." year] ["." month]] [world [net ["." uri (#+ URI)]]]]] ["." // ["/#" // #_ [repository (#+ Repository)] ["#." artifact (#+ Group Name Version Artifact) ["#/." time] ["#/." type (#+ Type)] ["#/." versioning (#+ Versioning)] ["#/." snapshot ["#/." version] ["#/." stamp]]]]]) (type: #export Metadata {#artifact Artifact #versioning Versioning}) (template [ ] [(def: xml.Tag ["" ])] [ "groupId"] [ "artifactId"] [ "version"] [ "metadata"] ) (template [
]
  [(def: 
     (->  XML)
     (|>> 
 #xml.Text list (#xml.Node  xml.attributes)))]

  [group_format Group .. (|>)]
  [name_format Name .. (|>)]
  [version_format Version .. (|>)]
  )

(def: #export (format (^slots [#artifact #versioning]))
  (-> Metadata XML)
  (let [(^slots [#///artifact.group #///artifact.name #///artifact.version]) artifact]
    (#xml.Node ..
               xml.attributes
               (list (..group_format group)
                     (..name_format name)
                     (..version_format version)
                     (///artifact/versioning.format versioning)))))

(def: (text tag)
  (-> xml.Tag (Parser Text))
  (<| (.node tag)
      .text))

(def: #export parser
  (Parser Metadata)
  (<| (.node ..)
      (do {! <>.monad}
        [group (.somewhere (..text ..))
         name (.somewhere (..text ..))
         version (.somewhere (..text ..))
         versioning (with_expansions [ {#///artifact/snapshot/version.extension ///artifact/type.jvm_library
                                                         #///artifact/snapshot/version.value version
                                                         #///artifact/snapshot/version.updated ///artifact/time.epoch}]
                      (|> (.somewhere ///artifact/versioning.parser)
                          (\ ! map
                             (update@ #///artifact/versioning.versions
                                      (: (-> (List ///artifact/snapshot/version.Version)
                                             (List ///artifact/snapshot/version.Version))
                                         (|>> (case> (^ (list))
                                                     (list )

                                                     versions
                                                     versions)))))
                          (<>.else {#///artifact/versioning.snapshot #///artifact/snapshot.Local
                                    #///artifact/versioning.last_updated ///artifact/time.epoch
                                    #///artifact/versioning.versions (list )})))]
        (in {#artifact {#///artifact.group group
                        #///artifact.name name
                        #///artifact.version version}
             #versioning versioning}))))

(def: #export equivalence
  (Equivalence Metadata)
  ($_ product.equivalence
      ///artifact.equivalence
      ///artifact/versioning.equivalence
      ))

(def: #export uri
  (-> Artifact URI)
  //.remote_artifact_uri)

(def: #export (read repository artifact)
  (-> (Repository Async) Artifact (Async (Try Metadata)))
  (do async.monad
    [project (\ repository download (..uri artifact))]
    (case project
      (#try.Success project)
      (in (|> project
              (do> try.monad
                   [(\ utf8.codec decode)]
                   [(\ xml.codec decode)]
                   [list (.run ..parser)])))
      
      (#try.Failure error)
      (in (#try.Success
           {#artifact artifact
            #versioning ///artifact/versioning.init})))))

(def: #export (write repository artifact metadata)
  (-> (Repository Async) Artifact Metadata (Async (Try Any)))
  (|> metadata
      ..format
      (\ xml.codec encode)
      (\ utf8.codec encode)
      (\ repository upload (..uri artifact))))