    async = require 'async'

    utils = require '../../lib/utils'
    log = require '../../lib/log'

    sources = require './sources'
    notifications = require './notifications'
    notify = require '../../lib/notify'

    getSourceFiles = (cb) ->

      coffees = []

Because the source files could be structured specifically for an application, e.g. nested, this takes a little bit more effort to keep that structure intact.

      mapSources = (dir, sourcesArray) ->

        sourcesArray.map (source) -> 

          sourceName = source.split('/')[source.split('/').length - 1]

          to = source.replace "#{process.cwd()}/#{dir}", ''

          parent = to.replace sourceName, ''
          parent = parent.substring 1, parent.length

          to = to.replace sourceName, ''
          to = "#{process.cwd()}/_app/compiled/#{dir}/#{parent}#{sourceName.replace('.litcoffee', '.js')}"

          from: source, to: to, script: "compiled/#{dir}/#{parent}#{sourceName.replace('.litcoffee', '.js')}"

Pull all _AngularJS Modules_ and _Pages_ from their directories (could be nested for organization).

      utils.listFiles "#{process.cwd()}/angular_modules", '.litcoffee', (angularModuleSources) ->

        Array::push.apply coffees, mapSources('angular_modules', angularModuleSources)

        utils.listFiles "#{process.cwd()}/pages", '.litcoffee', (pagesSources) ->

          Array::push.apply coffees, mapSources('pages', pagesSources)

This is at the end to keep references intact (this file is generated at root level of `_app`).

          coffees.push from: "#{process.cwd()}/_app/app.litcoffee", to: "#{process.cwd()}/_app/compiled/app.js", script: 'compiled/app.js'

          cb coffees

`bake` task can be issued by itself, without invoking `pages run` or `pages start`.

    compileSource = (source, cb) ->

      args = 'co'

      name = source.to.split('/')[source.to.split('/').length - 1]

      to = source.to.replace(name, '')

      utils.runWithOutputAndCb "#{global.pkgBasePath}/node_modules/coffee-script/bin/coffee -#{args} #{to} #{source.from}", notifications.coffee, cb

    build = (cb) ->

We remove this on cleanup, so it needs to be created. 

      utils.runWithCb "mkdir #{process.cwd()}/_app/compiled", () ->

These vendor assets _should_ just be minified always (vendor is assumed good and stable), but _some_ default AngularJS vendor packages suck and can't be minified (poorly structured).

        vendor = sources.vendor.compile.js().map (dependency) -> dependency.file

        utils.concatFiles vendor, "#{process.cwd()}/_app/compiled/vendor.js", (error) ->

          notifications.compiler error  if error

          global.pages.assets.js.push 'compiled/vendor.js'

          getSourceFiles (coffees) -> 

Compile all source files, possibly add the watch flags (`development` just compiles, no concat happens).

            async.each coffees, compileSource, () ->

              switch process.env.NODE_ENV 

In `development`, these assets are referenced in `<script>` tags separately.

                when 'development'

                  Array::push.apply global.pages.assets.js, (coffees.map (coffee) -> coffee.script)

                  cb()

In `production`, we concat/minify all source files into a single file.

                when 'production'

                  js = coffees.map (coffee) -> coffee.to

                  utils.concatFiles js, "#{process.cwd()}/_app/compiled/production-app.js", (error) ->

                    notifications.compiler error  if error

                    utils.concatMinifyFile 'js', "#{process.cwd()}/_app/compiled/production-app.js", "#{process.cwd()}/_app/compiled/production-app.min.js", (error) -> 

                      notifications.compiler error  if error 
                      
                      global.pages.assets.js.push 'compiled/production-app.min.js'

                      cb()

## Public API ##

    publicFns = 
      build: build

    module.exports = publicFns