/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 *--------------------------------------------------------*/
'use strict';
define(["require", "exports", 'vs/base/node/mono', 'fs', 'child_process', 'monaco'], function (require, exports, monoHelper, fs, cp, monaco) {
    var omnisharpEnv = 'OMNISHARP';
    var isWindows = /^win/.test(process.platform);
    function launch(configService, cwd, argv) {
        return checkRuntime().then(function (_) { return launchDetails(configService, argv); }).then(function (details) {
            return new monaco.Promise(function (c, e) {
                try {
                    var result;
                    if (isWindows) {
                        var args = details.argv.slice(0);
                        args.unshift(details.command);
                        args = [[
                                '/s',
                                '/c',
                                '"' + args.map(function (arg) { return /^[^"].* .*[^"]/.test(arg) ? "\"" + arg + "\"" : arg; }).join(' ') + '"'
                            ].join(' ')];
                        result = cp.spawn('cmd', args, {
                            windowsVerbatimArguments: true,
                            detached: false,
                            env: details.env,
                            cwd: cwd
                        });
                    }
                    else {
                        result = cp.spawn(details.command, details.argv, {
                            detached: false,
                            env: details.env,
                            cwd: cwd
                        });
                    }
                    // async error - when target not not ENEOT
                    result.on('error', function (err) {
                        e(err);
                    });
                    // success after a short freeing event loop
                    setTimeout(function () {
                        c({
                            process: result,
                            command: details.command
                        });
                    }, 0);
                }
                catch (err) {
                    e(err);
                }
            });
        });
    }
    exports.default = launch;
    function checkRuntime() {
        if (isWindows) {
            return monaco.Promise.as(null);
        }
        return monoHelper.hasMono('>=3.10.0').then(function (hasIt) {
            if (!hasIt) {
                throw new Error('Cannot start Omnisharp because Mono version >=3.10.0 is required. See http://go.microsoft.com/fwlink/?linkID=534832#_20001');
            }
        });
    }
    function launchDetails(configService, argv) {
        var commandPromise = configService.loadConfiguration('csharp').then(function (config) {
            if (config && typeof config['omnisharp'] === 'string') {
                // from configuration
                return config['omnisharp'];
            }
            else if (typeof process.env[omnisharpEnv] === 'string') {
                // form enviroment variable
                console.warn('[deprecated] use workspace or user settings with "csharp.omnisharp":"/path/to/omnisharp"');
                return process.env[omnisharpEnv];
            }
            else {
                // bundled version of Omnisharp
                return new monaco.Promise(function (c, e) {
                    var local = monaco.URI.parse(require.toUrl('./bin/omnisharp')).fsPath;
                    local = isWindows
                        ? local + '.cmd'
                        : local;
                    fs.exists(local, function (localExists) {
                        if (localExists) {
                            c(local);
                        }
                        else {
                            e(new Error('Local OmniSharp bin folder not found and OMNISHARP env variable not set'));
                        }
                    });
                });
            }
        });
        return commandPromise.then(function (command) {
            return {
                command: command,
                argv: argv
            };
        });
    }
});
