/** @babel */
import path from 'path';
import {CompositeDisposable} from 'atom';
import {allowUnsafeNewFunction} from 'loophole';
import setText from 'atom-set-text';
import pkgDir from 'pkg-dir';
import {sync as loadJson} from 'load-json-file';

let lintText;
allowUnsafeNewFunction(() => {
	lintText = require('xo').lintText;
});

function lint(textEditor) {
	const filePath = textEditor.getPath();
	const dir = pkgDir.sync(path.dirname(filePath));

	// no package.json
	if (!dir) {
		return [];
	}

	// ugly hack to workaround ESLint's lack of a `cwd` option
	// TODO: remove this when https://github.com/sindresorhus/atom-linter-xo/issues/19 is resolved
	const defaultCwd = process.cwd();
	process.chdir(dir);

	const pkg = loadJson(path.join(dir, 'package.json'));

	// only lint when `xo` is a dependency
	if (!(pkg.dependencies && pkg.dependencies.xo) &&
		!(pkg.devDependencies && pkg.devDependencies.xo)) {
		return [];
	}

	let report;
	allowUnsafeNewFunction(() => {
		report = lintText(textEditor.getText(), {
			cwd: dir,
			filename: filePath
		});
	});

	process.chdir(defaultCwd);

	return report.results[0].messages.map(x => ({
		filePath,
		type: x.severity === 2 ? 'Error' : 'Warning',
		text: `${x.message} (${x.ruleId})`,
		range: [
			[x.line - 1, x.column - 1],
			[x.line - 1, x.column - 1]
		]
	}));
}

export function provideLinter() {
	return {
		name: 'XO',
		grammarScopes: [
			'source.js',
			'source.jsx',
			'source.js.jsx'
		],
		scope: 'file',
		lintOnFly: true,
		lint
	};
}

export function activate() {
	require('atom-package-deps').install('linter-xo');

	this.subscriptions = new CompositeDisposable();
	this.subscriptions.add(atom.commands.add('atom-text-editor', {
		'XO:Fix': () => {
			const editor = atom.workspace.getActiveTextEditor();

			if (!editor) {
				return;
			}

			let report;

			allowUnsafeNewFunction(() => {
				report = lintText(editor.getText(), {
					fix: true,
					cwd: path.dirname(editor.getPath())
				});
			});

			const output = report.results[0].output;

			if (output) {
				setText(output);
			}
		}
	}));
}

export function deactivate() {
	this.subscriptions.dispose();
}

@@ -59,16 +59,23 @@
 sposable
+, Range
 %7D from '
@@ -1103,54 +1103,329 @@
 ;%0A%0A%09
-return report.results%5B0%5D.messages.map(x =%3E (%7B%0A
+const textBuffer = textEditor.getBuffer();%0A%0A%09return report.results%5B0%5D.messages.map(x =%3E %7B%0A%09%09let fix;%0A%0A%09%09if (x.fix) %7B%0A%09%09%09fix = %7B%0A%09%09%09%09range: new Range(%0A%09%09%09%09%09textBuffer.positionForCharacterIndex(x.fix.range%5B0%5D),%0A%09%09%09%09%09textBuffer.positionForCharacterIndex(x.fix.range%5B1%5D)%0A%09%09%09%09),%0A%09%09%09%09newText: x.fix.text%0A%09%09%09%7D;%0A%09%09%7D%0A%0A%09%09return %7B%0A%09
 %09%09fi
@@ -1432,16 +1432,25 @@
 lePath,%0A
+%09%09%09fix,%0A%09
 %09%09type: 
@@ -1491,16 +1491,17 @@
 ing',%0A%09%09
+%09
 text: %60$
@@ -1528,16 +1528,17 @@
 eId%7D)%60,%0A
+%09
 %09%09range:
@@ -1539,24 +1539,25 @@
 range: %5B%0A%09%09%09
+%09
 %5Bx.line - 1,
@@ -1575,16 +1575,17 @@
  1%5D,%0A%09%09%09
+%09
 %5Bx.line 
@@ -1607,15 +1607,20 @@
  1%5D%0A
+%09
 %09%09%5D%0A%09
+%09%7D;%0A%09
 %7D
-)
 );%0A%7D

add support for the upcoming Linter `fix` option