
require:
   path, fs


defaults = {
   language = .javascript
   theme = .default
}


theme-lightness = {
   '3024-day' => .light
   '3024-night' => .dark
   'abcdef' => .dark
   'ambiance' => .dark
   'base16-dark' => .dark
   'base16-light' => .light
   'bespin' => .dark
   'blackboard' => .dark
   'cobalt' => .dark
   'colorforth' => .dark
   'default' => .light
   'dracula' => .dark
   'eclipse' => .light
   'elegant' => .light
   'erlang-dark' => .dark
   'hopscotch' => .dark
   'icecoder' => .dark
   'isotope' => .dark
   'lesser-dark' => .dark
   'liquibyte' => .dark
   'material' => .dark
   'mbo' => .dark
   'mdn-like' => .light
   'midnight' => .dark
   'monokai' => .dark
   'neat' => .light
   'neo' => .light
   'night' => .dark
   'paraiso-dark' => .dark
   'paraiso-light' => .light
   'pastel-on-dark' => .dark
   'railscasts' => .dark
   'rubyblue' => .dark
   'seti' => .dark
   'solarized' => .light
   'the-matrix' => .dark
   'tomorrow-night-bright' => .dark
   'tomorrow-night-eighties' => .dark
   'ttcn' => .light
   'twilight' => .dark
   'vibrant-ink' => .dark
   'xq-dark' => .dark
   'xq-light' => .light
   'yeti' => .light
   'zenburn' => .dark
}


reg{@, lang, theme} =

   @register-resources with {
      'repple/{lang}.js' => {
         path = path.join{__dirname, '../client/{lang}.js'}
         contents = true
         type = .js
         method = .head
      }
      'repple/install.js' => {
         path = path.join{__dirname, '../client/install.js'}
         contents = true
         type = .js
         method = .head
      }
      'repple/install.js/run' => {
         path = null
         contents = "$$quaintReppleInstall();"
         type = .js
         method = .body
         inline = true
      }
      'repple/codemirror.css' => {
         path = path.join{__dirname, '../client/codemirror.css'}
         contents = true
         type = .css
         method = .head
      }
      'repple/repple.sass' => {
         path = path.join{__dirname, '../client/repple.sass'}
         contents = true
         type = .sass
         method = .head
      }
   }

   if theme !== .default:
      @register-resources with {
         'repple/{theme}.css' => {
            path = path.join{__dirname, '../theme/{theme}.css'}
            contents = true
            type = .css
            method = .head
         }
      }


var __gid = 0


install-card-macros{@, rv} =
   @register-rules with {
      "\\maybe\\label/\\code"{engine, {=> label, => var code}} =
         code = @tools.as-indented-block{code.shed{}}
         invoke = '{rv}${__gid += 1}'
         {
            script[raw] %
               'function {invoke}() \{ {rv}.repl.process({JSON.stringify{code}}, true, true) \}'
            code.repple-paste[raw] %
               onclick = '{invoke}()'
               code
         }
   }
   @


card-engine{engine, repple-variable} =
   install-card-macros{engine.fork{}, repple-variable}


install{@, _options} =

   options = defaults & _options

   QAst = @quaint.QAst

   leaf{x} =
      match x.raw{}:
         "true" -> true
         "false" -> false
         "null" -> null
         else -> x

   repl-zone{} =
      div.repple-repl %
         div.repple-scrollback %
         div.repple-inputline %
            div.repple-inbanner %
            div.repple-inputbox %
               textarea.repple-replarea %

   editor-zone{} =
      div.repple-editor %
         textarea.repple-editorarea %

   @register-macros with {

      repple{engine, type >> type.raw{}, body} =

         _id = [__gid += 1]
         id = 'repple-{_id}'
         repple-variable = '$$repple{_id}'

         settings = engine.tools.to-data{body, {= leaf}}

         cards = {=}
         results = {}

         push-card{cards, cls, name, order, title, contents} =
            div-id = 'repple-card-{__gid += 1}'
            div =
               div %
                  id = div-id
                  div %
                     class = 'repple-card {[cls each c -> "repple-card-"+c].join{"-"}}'
                     if{title, h2 % engine.gen{title}, ""}
                     div %
                        card-engine{engine, repple-variable}.gen{contents}
            results.push{div}
            {
               = div-id
               order = order or 0
            }

         get-cards{match key, value, cls, cards} =
            R"^\+(?:(\d*)-)?(?:([^-]*)-)?(.*)"!
                  \ {_, Number! order, var key, title} and match is value ->
               do:
                  key or= title
                  cards[key] or= {=}
               String? s or Array? s or QAst? s ->
                  cards[key].__main =
                     push-card{cards, cls, key, order, title, s}
               {=> body = null, title => _title = null} ->
                  if body:
                     cards[key].__main =
                        push-card{cards, cls, key, order, _title or title, body}
                  iter-cards{value, cls ++ {key}, cards[key]}
            else ->
               pass

         iter-cards{listing, cls, cards} =
            items{listing} each {key, value} ->
               get-cards{key, value, cls, cards}

         iter-cards{settings, {}, cards}

         language = settings.language??.raw{} or options.language
         theme = settings.theme??.raw{} or options.theme

         config = {
            = type
            div-id = id
            code = if{settings.code, @tools.as-indented-block{settings.code}, ""}
            variable = repple-variable
            = cards
            = language
            = theme
            indent = settings.indent??.raw{} or 3
            after = settings.after??.raw{} or null
         }
         reg{@, language, theme}
         theme2 = 'repple-theme-{theme-lightness[theme]}'
         elem =
            match type:
               .repl ->
                  div.repple-container.repple-repl-container %
                     id = id
                     class = theme2
                     repl-zone{}
               "repl-aside" ->
                  div.repple-container.repple-repl-aside-container %
                     id = id
                     class = theme2
                     repl-zone{}
                     div.repple-aside %
               .editor ->
                  div.repple-container.repple-editor-container %
                     id = id
                     class = theme2
                     editor-zone{}
                     div.repple-aside %
               "editor-repl" ->
                  div.repple-container.repple-editor-repl-container %
                     id = id
                     class = theme2
                     editor-zone{}
                     repl-zone{}
               else ->
                  throw E.repple{'Unknown repple component: "{type}"'}
         {
            elem
            script[raw] % '$$quaintReppleList.push({JSON.stringify{config}});'
            .repple-card-data %
               results
         }
   }


main{*match} =
   {@, options = {=}} when @is-quaint-engine ->
      install{@, options}
   {options = {=}} ->
      {@} -> main{@, options}

provide = main
