'use babel';

import fs from 'fs';
import path from 'path';
import os from 'os';
import { exec } from 'child_process';
import voucher from 'voucher';
import { EventEmitter } from 'events';



export const config = {
    jobs: {
        title: 'Simultaneous jobs',
        description: 'Limits how many jobs make will run simultaneously. Defaults to number of processors-1. Set to 1 for default behavior of make.',
        type: 'number',
        default: os.cpus().length - 1,
        minimum: 1,
        maximum: os.cpus().length,
        order: 1
    },
    makefileNames: {
        title: 'Considered makefile names',
        description: 'Comma separated list of makefile names to search for in the folder of the current file.',
        type: 'string',
        default: 'Makefile, GNUmakefile, makefile',
        order: 2
    }
};



export function provideBuilder() {
    const errorMatch = [
        // match make errors
        '(?<file>[^:\\n]+):(?<line>\\d+):(?<col>\\d+):\\s*(fatal error|error|warning):\\s*(?<message>.+)',
        // match LaTeX errors
        '\\n!\\s+(?<message>(.*\\n)+?l\\.(?<line>\\d+).*)', // alternative match: the message without the last line: '\\n!\\s+(?<message>(.*\\n)+?)l\\.(?<line>\\d+).*'
    ];

    return class MakeBuildProvider extends EventEmitter {
        constructor(cwd) {
            super();
            this.cwd = cwd;
            atom.config.observe('build-make-file.jobs', () => this.emit('refresh'));
            atom.config.observe('build-make-file.makefileNames', () => this.emit('refresh'));
            this.makefiles = atom.config.get('build-make-file.makefileNames').split(',').map(n => n.trim())
            this.curFilePath = null;
        }

        getNiceName() {
            return 'GNU Make in the folder of the current file';
        }

        // Returns true, if a makefile was found in the current file's folder.
        isEligible() {
            try {
                editor = atom.workspace.getActivePaneItem()
                this.curFilePath = path.dirname(editor.buffer.file.path)
                foundMakefiles = this.makefiles.map(f => path.join(this.curFilePath, f)).filter(fs.existsSync);
                return (foundMakefiles.length > 0);
            }
            catch(err) {
                this.curFilePath = null;
                return false;
            }
        }

        // Either returns all make targets reported by 'make -prRn',
        // or an "empty" target which just states that there were no targets in the makefile.
        settings() {
            const emptyTarget = {
                exec: 'echo "There is no target in the makefile!" && false',
                name: `No target found in makefile.`,
                args: [],
                sh: true,
                errorMatch: []
            };

            if (!this.curFilePath) {
                return [emptyTarget];
            }

            const args = ['-j' + atom.config.get('build-make-file.jobs')];
            const promise = voucher(exec, 'make -prRn', { cwd: this.curFilePath })
            return promise.then(output => {
                return output.toString('utf8')
                .split(/[\r\n]{1,2}/)
                .filter(line => /^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/.test(line))
                .map(targetLine => targetLine.split(':').shift())
                .map(target => ({
                    exec: 'make',
                    cwd:  this.curFilePath,
                    args: args.concat([target]),
                    name: `GNU Make in current file's folder: ${target}`,
                    sh: false,
                    errorMatch: errorMatch
                }));
            }).catch(e => [ emptyTarget ]);
        }
    };
}

@@ -181,24 +181,391 @@
 events';%0A%0A%0A%0A
+/**%0A * Returns the folder of the currently opened file.%0A * If an error occurrs (i.e. the settings pane is open or such),%0A * null is returned.%0A */%0Afunction getCurFilesPath() %7B%0A    try %7B%0A        editor = atom.workspace.getActivePaneItem();%0A        ret = path.dirname(editor.buffer.file.path);%0A        return ret;%0A    %7D%0A    catch(err) %7B%0A        return null;%0A    %7D%0A%0A%7D%0A%0A%0A%0A
 export const
@@ -2025,45 +2025,8 @@
 ())%0A
-            this.curFilePath = null;%0A
     
@@ -2250,71 +2250,37 @@
     
-try %7B%0A                editor = atom.workspace.getActivePaneItem
+curFilePath = getCurFilesPath
 ()%0A 
@@ -2286,33 +2286,29 @@
             
-    this.
+if (!
 curFilePath 
@@ -2310,56 +2310,57 @@
 Path
- = path.dirname(editor.buffer.file.path)%0A       
+) %7B%0A                return false;%0A            %7D%0A%0A
     
@@ -2364,16 +2364,19 @@
         
+   
 foundMak
@@ -2418,21 +2418,16 @@
 th.join(
-this.
 curFileP
@@ -2466,28 +2466,24 @@
             
- 
-   
 return (foun
@@ -2510,132 +2510,8 @@
 0);%0A
-            %7D%0A            catch(err) %7B%0A                this.curFilePath = null;%0A                return false;%0A            %7D%0A
     
@@ -2981,18 +2981,57 @@
     
+curFilePath = getCurFilesPath()%0A            
 if (!
-this.
 curF
@@ -3232,21 +3232,16 @@
  %7B cwd: 
-this.
 curFileP
@@ -3615,21 +3615,16 @@
   cwd:  
-this.
 curFileP

put getting the current path in an own function