(.module:
  [lux #*
   ["_" test (#+ Test)]
   [abstract
    [monad (#+ do)]
    [hash (#+ Hash)]
    {[0 #spec]
     [/
      ["$." equivalence]
      ["$." monoid]]}]
   [control
    [pipe (#+ case>)]
    ["." try]
    [parser
     ["." cli]]]
   [data
    ["." text]
    [collection
     ["." set (#+ Set)]
     ["." dictionary (#+ Dictionary)]]]
   [math
    ["." random (#+ Random) ("#\." monad)]
    [number
     ["n" nat]]]]
  [//
   ["@." artifact]
   ["@." dependency]]
  {#program
   ["." /
    ["/#" // #_
     ["#." dependency (#+ Dependency)]
     ["#." format]
     [repository
      [remote (#+ Address)]]]]})

(def: distribution
  (Random /.Distribution)
  (random.or (random\wrap [])
             (random\wrap [])))

(def: license
  (Random /.License)
  ($_ random.and
      (random.ascii/alpha 1)
      (random.ascii/alpha 1)
      ..distribution))

(def: scm
  (Random /.SCM)
  (random.ascii/alpha 1))

(def: organization
  (Random /.Organization)
  ($_ random.and
      (random.ascii/alpha 1)
      (random.ascii/alpha 1)))

(def: email
  (Random /.Email)
  (random.ascii/alpha 1))

(def: developer
  (Random /.Developer)
  ($_ random.and
      (random.ascii/alpha 1)
      (random.ascii/alpha 1)
      (random.maybe organization)))

(def: contributor
  (Random /.Contributor)
  ..developer)

(def: (list_of random)
  (All [a] (-> (Random a) (Random (List a))))
  (do {! random.monad}
    [size (\ ! map (n.% 5) random.nat)]
    (random.list size random)))

(def: (set_of hash random)
  (All [a] (-> (Hash a) (Random a) (Random (Set a))))
  (\ random.functor map
     (set.from_list hash)
     (..list_of random)))

(def: (dictionary_of key_hash key_random value_random)
  (All [k v] (-> (Hash k) (Random k) (Random v) (Random (Dictionary k v))))
  (\ random.functor map
     (dictionary.from_list key_hash)
     (..list_of (random.and key_random value_random))))

(def: info
  (Random /.Info)
  ($_ random.and
      (random.maybe (random.ascii/alpha 1))
      (random.maybe ..scm)
      (random.maybe (random.ascii/alpha 1))
      (..list_of ..license)
      (random.maybe ..organization)
      (..list_of ..developer)
      (..list_of ..contributor)
      ))

(def: name
  (Random /.Name)
  (random.ascii/alpha 1))

(def: repository
  (Random Address)
  (random.ascii/alpha 1))

(def: source
  (Random /.Source)
  (random.ascii/alpha 1))

(def: target
  (Random /.Target)
  (random.ascii/alpha 1))

(def: #export random
  (Random /.Profile)
  ($_ random.and
      (..list_of ..name)
      (random.maybe @artifact.random)
      (random.maybe ..info)
      (..set_of text.hash ..repository)
      (..set_of //dependency.hash @dependency.random)
      (..set_of text.hash ..source)
      (random.maybe ..target)
      (random.maybe (random.ascii/alpha 1))
      (random.maybe (random.ascii/alpha 1))
      (..dictionary_of text.hash (random.ascii/alpha 1) ..repository)
      ))

(def: #export test
  Test
  (<| (_.covering /._)
      (_.for [/.Distribution /.License /.SCM /.Organization
              /.Email /.Developer /.Contributor /.Info
              /.Source /.Target /.Name /.Profile]
             ($_ _.and
                 (_.for [/.equivalence]
                        ($equivalence.spec /.equivalence ..random))
                 (_.for [/.monoid]
                        ($monoid.spec /.equivalence /.monoid ..random))
                 ))))