#!/usr/bin/env lsc

#
# Nodulator Boostrap
#
# Usage: Nodulator (init | console) | ((install | remove) moduleName)
#

_ = require 'underscore'
fs = require 'fs'
path = require 'path'
exec = require('child_process').exec
async = require 'async'
coffee-script = require 'coffee-script/register'

args = process.argv[2 to]

NodulatorRoot = path.resolve fs.realpathSync(path.resolve __dirname, __filename), '../..'
appRoot = path.resolve '.'

moduleOrder = ['nodulator-socket', 'nodulator-assets', 'nodulator-angular', 'nodulator-account']

dependencies =
  'nodulator-angular': ['nodulator-socket', 'nodulator-assets']

capitalize = (str) ->
  str[0].toUpperCase() + str[1 to]*''

exists = (path, done) ->
  fs.realpath path, (err, realPath) ->
    return done false if err?

    fs.lstat realPath, (err, stat) ->
      return done false if err?

      if stat.isDirectory! or stat.isSymbolicLink! or stat.isFile()
        done true
      else
        done false

npmStandard = (action, pack, done) ->
  exec 'npm ' + action + ' ' + pack + ' --save', (err, stdout, stderr) ->
    return done err if err? and done?
    return console.error err if err?

    done() if done?

npmDevInstall = (action, pack, done) ->
  nameSplited = pack.split('/')
  name = nameSplited[nameSplited.length - 1]
  packCapit = ''
  if pack.split('-').length is 2
    packCapit = capitalize(pack.split('-')[0]) + '-' + capitalize(pack.split('-')[1])
  else
    packCapit = capitalize pack

  orig = path.resolve(NodulatorRoot, packCapit)

  exec 'mkdir -p ./node_modules', (err, stdout, stderr) ->
    return done err if err? and done?

    # exec  'cd ' + appRoot + ' && ln -sf ' + appRoot + '/' + packCapit + ' ' + appRoot + '/node_modules/' + name.toLowerCase() + '&& cd ..', (err, stdout, stderr) ->
    exec  "cd #appRoot && ln -sf #appRoot/#packCapit #appRoot/node_modules/#{name.toLowerCase!} && cd ..", (err, stdout, stderr) ->
      return done err if err? and done?
      return console.error err if err?

      done() if done?

usage = ->
  console.error 'Usage: Nodulator (init | console(or c)) | ((install |  install-dev | remove) moduleName1 [, moduleName2])'

generateMain = (modules) ->

  mainBefore = 'N = require \'nodulator\'\n'
  mainBefore += 'Server = require \'./server\'\n'

  mainAfter = ''
  mainAfter += '\n\n' if modules.length
  for module in (_(modules).sortBy (item) -> _(moduleOrder).indexOf item)
    name = module.split('-')[1]
    mainBefore += '\n' + capitalize(name) + ' = require \'' + module + '\''
    mainAfter += 'N.Use ' + capitalize(name) + '\n'

  mainAfter += '\nServer.Init!\n'
  mainAfter += 'N.Run!\n' if 'nodulator-assets' in modules

  fs.writeFileSync appRoot + '/index.ls', mainBefore + mainAfter

if args.length is 1 and args[0] not in ['init', 'install', 'remove', 'install-dev', 'console', 'c']
  return usage()


if not args[0]? or args[0] in ['console', 'c']
  if not args[1]?
    args[1] := './settings/dev'
  if not args[2]?
    args[2] := './server/resources'

  # cons =  require "#{appRoot}/node_modules/nodulator/bin/Console"
  cons = require __dirname + \/Console
  cons args[1], args[2]

if args[0] is 'init'
  async.series [
    (done) ->
      exists "#{appRoot}/node_modules/nodulator", (exist) ->
        if not exist
          process.stdout.write 'Installing Nodulator..............'
          npmStandard 'install', 'nodulator', (err) ->
            return done err if err?

            process.stdout.write 'Ok\n'
            done()

        else
          done()

    (done) ->
      process.stdout.write 'Installing base folder tree.......'
      exec 'mkdir -p node_modules', (err, stdout, stderr) ->
        exec 'cp -r ' + (path.resolve NodulatorRoot, 'bin/baseFiles/') + '/* ' + appRoot, ->
          done()

    (done) ->
      process.stdout.write 'Ok\n'
      process.stdout.write 'Processing submodules.............'
      fs.readdir 'node_modules', (err, files) ->
        return done err if err?

        nodulatorFiles = _(files).filter (name) -> name.split('-').length > 1 and name.split('-')[0] is 'nodulator'
        toWrite = if not nodulatorFiles.length then 'None\n' else nodulatorFiles.length
        process.stdout.write toWrite + '\n'

        generateMain nodulatorFiles

        i = 1
        async.eachSeries (_(nodulatorFiles).sortBy (item) -> _(moduleOrder).indexOf item), (file, done) ->
          binName = 'Nodulator-' + file.split('-')[1][0].toUpperCase() + file.split('-')[1][1 to]*'' + '.coffee'
          binPath = appRoot + '/node_modules/' + file + '/bin/' + binName
          test = binPath
          exists binPath, (exist) ->
            if not exist
              console.log test, 2
              binName = 'Nodulator-' + file.split('-')[1][0].toUpperCase() + file.split('-')[1][1 to]*'' + '.ls'
              binPath = appRoot + '/node_modules/' + file + '/bin/' + binName
              return exists binPath, (exist) ->
                return done() if not exist

                process.stdout.write '\n[' + i++ + ']Processing ' + binName.split('.')[0] + ': \n'
                (require binPath)(done)

            binName = 'Nodulator-' + file.split('-')[1][0].toUpperCase() + file.split('-')[1][1 to]*'' + '.coffee'
            binPath = appRoot + '/node_modules/' + file + '/bin/' + binName
            process.stdout.write '\n[' + i++ + ']Processing ' + binName.split('.')[0] + ': \n'
            (require binPath)(done)
        , done

  ], (err, results) ->
    return console.error err if err?

else if args[0] in ['install', 'remove', 'install-dev']

  npm = npmStandard
  if args[0] is 'install-dev'
    npm = npmDevInstall

  exec 'mkdir -p node_modules', (err, stdout, stderr) ->

    exists 'node_modules/nodulator', (exist) ->
      if not exist
        console.log 'Installing nodulator'
        npm(args[0], 'nodulator')
      else
        console.log 'Already installed: nodulator'

      for packageName in args[1 til]

        async.series [

          (done) ->
            #install dependencies
            if dependencies['nodulator-' + packageName]? and args[0] in ['install', 'install-dev']
              async.eachSeries dependencies['nodulator-' + packageName], (item, done) ->
                exists 'node_modules/' + item, (exist) ->
                  if not exist
                    console.log 'Installing ' + item
                    newItem = capitalize(item.split('-')[0]) + '-' + capitalize item.split('-')[1]
                    npm 'install', './node_modules/nodulator/src/Modules/' + newItem, done
                  else
                    console.log 'Already installed: ' + item
                    done()
              , done
            else
              done()

          (done) ->
            toInstall = 'nodulator-' + packageName
            if packageName? and toInstall in moduleOrder
              exists 'node_modules/' + toInstall, (exist) ->
                if exist
                  console.log 'Already installed: ' + toInstall
                  return done()

                console.log 'Installing ' + toInstall
                item = capitalize(toInstall.split('-')[0]) + '-' + capitalize toInstall.split('-')[1]
                npm args[0], './node_modules/nodulator/src/Modules/' + item, done

            else if args[1]?
              console.error 'Unknown module: ', toInstall
              return done()

        ], (err) ->
          console.error err if err?
