"""
**********************************************************************

  A RapydScript to JavaScript compiler.
  https://github.com/atsepkov/RapydScript

  -------------------------------- (C) ---------------------------------

                       Author: Alexander Tsepkov
                         <atsepkov@pyjeon.com>
                         http://www.pyjeon.com

  Distributed under BSD license:
    Copyright 2013 (c) Alexander Tsepkov <atsepkov@pyjeon.com>

**********************************************************************
"""

fs = require('fs')
path = require('path')
rapydscript = require("../lib/rapydscript")

def read_whole_file(filename, cb):
    if not filename:
        chunks = []
        process.stdin.setEncoding('utf-8')
        process.stdin.on('data', def(chunk):
            chunks.push(chunk)
        ).on('end', def():
            cb(None, chunks.join(""))
        )
        process.openStdin()
    else:
        fs.readFile(filename, "utf-8", cb)

module.exports = def(start_time, argv, base_path, src_path, lib_path):
    # configure settings for input / output
    files = argv.files[:]
    metrics = {}
    num_of_files = files.length or 1
    dropDecorators = argv.drop_decorators.split(/\s*,\s*/)
    dropImports = argv.drop_imports.split(/\s*,\s*/)
    parseOpts = {
        filename: '?',
        readfile: fs.readFileSync,
        auto_bind: argv.auto_bind,
        es6: argv.ecmascript6,
        libdir: path.join(src_path, 'lib'),
        import_dirs: rapydscript.get_import_dirs(argv.import_path),
        dropDecorators: dropDecorators,
        dropImports: dropImports,
        dropDocstrings: argv.drop_docstrings,
        beautify: argv.beautify,
        private_scope: !argv.bare,
        omit_baselib: argv.omit_baselib,
        strict_names: argv.strict_names
    }
    if not argv.omit_baselib:
        parseOpts.baselib = rapydscript.parse_baselib(src_path, parseOpts.beautify)
    if argv.comments:
        if /^\//.test(argv.comments):
            parseOpts.comments = Function("return(" + argv.comments + ")")()
        elif argv.comments == "all":
            parseOpts.comments = True
        else:
            parseOpts.comments = def(node, comment):
                text = comment.value
                type = comment.type
                if type is "comment:multiline":
                    # multiline comment
                    return /@preserve|@license|@cc_on/i.test(text)

    def write_output(output):
        if argv.output:
            fs.writeFileSync(argv.output, output, "utf8")
        elif argv.execute:
            if argv.beautify:
                console.log('\n------------ Compilation -------------\n')
                console.log(output)
                console.log('\n------------ Execution -------------\n')
            require('vm').runInNewContext(output, {
                'console': console,
                'process': process,
                'require': require,
                'root': JS('typeof window') is 'object' ? window : global
            }, {'filename':files[0]})
        else:
            console.log(output)

    def time_it(name, cont):
        t1 = new Date().getTime()
        ret = cont()
        spent = new Date().getTime() - t1
        if metrics[name]:
            metrics[name] += spent
        else:
            metrics[name] = spent
        return ret

    def compile_single_file(err, code):
        nonlocal files
        if err:
            console.error("ERROR: can't read file: " + files[0])
            process.exit(1)

        # update file/dir per file
        parseOpts.filename = files[0]
        parseOpts.basedir = path.dirname(files[0])

        if argv.stats:
            # to gather stats, we have to perform steps individually
            time_it("parse", def():
                toplevel = rapydscript.parse(code, parseOpts)
            )

            time_it("generate", def():
                nonlocal output
                output = rapydscript.output(toplevel, parseOpts)
            )
        else:
            # regular compilation can be done in a single step
            output = rapydscript.compile(code, parseOpts)
        write_output(output)

        files = files[1:]
        if files.length:
            setImmediate(read_whole_file, files[0], compile_single_file)
            return
        if argv.stats:
            console.error(rapydscript.string_template("Timing information (compressed {count} files):", {
                count: num_of_files
            }))
            for i in dir(metrics):
                if metrics.hasOwnProperty(i):
                    console.error(rapydscript.string_template("- {name}: {time}s", {
                        name: i,
                        time: (metrics[i] / 1000).toFixed(3)
                    }))

    if files.filter(def(el): return el is "-";).length > 1:
        console.error("ERROR: Can read a single file from STDIN (two or more dashes specified)")
        process.exit(1)

    setImmediate(read_whole_file, files[0], compile_single_file)

