 {exec} = require 'child_process'
 
 SRC_DIRS = ['src', 'lib', 'app']
+BLACKLIST_FILES = ['Gruntfile.coffee']
 
 module.exports = class MetaDoc
   @Parser: Parser

        file = path.relative(package_json_path, composite_main)
        file = file.substring(1, file.length) if file.match /^\.\./
        return file

  # Public: Find the source directories.
  @detectSources: (done) ->
    Async.filter SRC_DIRS, fs.exists, (results) ->
      results.push '.' if results.length is 0
      done null, results

  # Public: Find the project's README.
  @detectReadme: (done) ->
    Async.filter [
      'README.markdown'
      'README.md'
      'README'
      'readme.markdown'
      'readme.md'
      'readme'
    ], fs.exists, (results) -> done null, _.first(results) || ''

  # Public: Find extra project files in the repository.
  @detectExtras: (done) ->
    Async.filter [
      'CHANGELOG.markdown'
      'CHANGELOG.md'
      'AUTHORS'
      'AUTHORS.md'
      'AUTHORS.markdown'
      'LICENSE'
      'LICENSE.md'
      'LICENSE.markdown'
      'LICENSE.MIT'
      'LICENSE.GPL'
    ], fs.exists, (results) -> done null, results

  # Public: Find the project name by either parsing `package.json`,
  # or getting the current working directory name.
  #
  # done - The {Function} callback to call once this is done
  @detectName: (done) ->
    if fs.existsSync('package.json')
      name = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'))['name']
    else
      name = path.basename(process.cwd())

    done null, name.charAt(0).toUpperCase() + name.slice(1)

  # Public: Find the project's latest Git tag.
  #
  # done - The {Function} callback to call once this is done
  @detectTag: (done) ->
    exec 'git describe --abbrev=0 --tags', (error, stdout, stderr) ->
      currentTag = stdout || "master"

      done null, currentTag

  # Public: Find the project's Git remote.origin URL.
  #
  # done - The {Function} callback to call once this is done
  @detectOrigin: (done) ->
    exec 'git config --get remote.origin.url', (error, stdout, stderr) ->
      url = stdout
      if url
        if url.match /https:\/\/github.com\// # e.g., https://github.com/foo/bar.git
          url = url.replace(/\.git/, '')
        else if url.match /git@github.com/    # e.g., git@github.com:foo/bar.git
          url = url.replace(/^git@github.com:/, 'https://github.com/').replace(/\.git/, '')

      done null, url

  @version: ->
    'v' + JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'))['version']

  @run: ->

    optimist = require('optimist')
      .usage("""
      Usage: $0 [options] [source_files]
      """)
      .options('o',
        alias: 'output-dir'
        describe: 'The output directory'
        default: './doc'
      )
      .options('d',
        alias: 'debug'
        describe: 'Show stacktraces and converted CoffeeScript source'
        boolean: true
        default: false
      )
      .options('h',
        alias: 'help'
        describe: 'Show the help'
      )

    argv = optimist.argv

    if argv.h
      console.log optimist.help()
      return

    options =
      inputs: argv._
      output: argv.o

    parser = new Parser(options)
    metadataSlugs = []

    for input in options.inputs
      continue unless (fs.existsSync || path.existsSync)(input)

      # collect probable package.json path
      package_json_path = path.join(input, 'package.json')
      stats = fs.lstatSync input
      absoluteInput = path.resolve(process.cwd(), input)

      if stats.isDirectory()
        for filename in walkdir.sync input
          if @isAcceptableFile(filename) and @isInAcceptableDir(absoluteInput, filename)
            console.log absoluteInput, filename

            try
              relativePath = filename
              relativePath = path.normalize(filename.replace(process.cwd(), ".#{path.sep}")) if filename.indexOf(process.cwd()) == 0
              parser.parseFile relativePath
            catch error
              throw error if options.debug
              console.log "Cannot parse file #{ filename }@#{error.location.first_line}: #{ error.message }"
      else
        if @isAcceptableFile(input)
          try
            parser.parseFile input
          catch error
            throw error if options.debug
            console.log "Cannot parse file #{ filename }@#{error.location.first_line}: #{ error.message }"

      metadataSlugs.push @generateMetadataSlug(package_json_path, parser, options)

    @writeMetadata(metadataSlugs, options)

  @isAcceptableFile = (filePath) ->
    for file in BLACKLIST_FILES
      return false if new RegExp(file+'$').test(filePath)

    filePath.match(/\._?coffee$/)

  @isInAcceptableDir = (inputPath, filePath) ->
    # is in the root of the input?
    return true if path.join(inputPath, path.basename(filePath)) is filePath

    # is under src, lib, or app?
    acceptableDirs = (path.join(inputPath, dir) for dir in SRC_DIRS)
    for dir in acceptableDirs
      return true if filePath.indexOf(dir) == 0

    false

  @writeMetadata: (metadataSlugs, options) ->
    fs.writeFileSync path.join(options.output, 'metadata.json'), JSON.stringify(metadataSlugs, null, "    ")
