<commit_before>'use babel';

// 3p
import _ from 'underscore-plus';
import { CompositeDisposable } from 'atom';
import fs from 'fs';
import path from 'path';

// project
import LauncherView from './utils/views/launcher-view.jsx';
import PyLprof from './pylprof/runner.js';
import StatsGutter from './utils/stats-gutter.js';
import StatusView from './utils/views/status-view.jsx';

class PProfile {

    constructor({config, statsGutter}) {
        this.subscriptions = null;
        this.showLauncher = false;
        this.config = config;
        this.statsGutter = statsGutter;
    }

    activate(state) {
        // initialize launcher
        this.launcherContent = state.launcherContent;
        if (!state.launcherContent) {
            let cmdfile = path.resolve(__dirname, 'launcher_cmd.py');
            this.launcherContent = fs.readFileSync(cmdfile, 'utf8');
        }

        this.launcherView = new LauncherView({
            show: this.showLauncher,
            onRun: this.run.bind(this),
            grammar: 'source.python',
            content: this.launcherContent,
            onChange: c => { this.launcherContent = c; }
        });
        atom.workspace.addBottomPanel({
            item: this.launcherView.element
        });

        // initialize status view
        this.statusView = new StatusView({
            show: false
        });
        atom.workspace.addBottomPanel({
            item: this.statusView.element
        });

        this.subscriptions = new CompositeDisposable();
        return this.subscriptions.add(atom.commands.add('atom-workspace', {
            'pprofile:toggle': (function(_this) {
                return function() {
                    return _this.toggle()
                };
            })(this)
        }));
    }

    deactivate() {
        this.modalPanel.destroy();
        this.subscriptions.dispose();
        this.pprofileView.destroy();
    }

    serialize() {
        return {
            launcherContent: this.launcherContent
        };
    }

    getFileStats(filename, stats) {
        let basename = path.basename(filename);
        let filestats = _.find(stats, s => s.file.endsWith(basename));
        return filestats ? filestats.stats : [];
    }

    run(userInput) {
        let tab = atom.workspace.getActiveTextEditor();

        if (!tab.buffer.file) {
            this.statusView.update({
                show: true,
                status: 'error',
                message: 'This buffer need to be saved'
            });
            return;
        }

        this.launcherView.update({
            content: this.launcherContent,
            status: 'running',
            show: true
        });

        let runner = new PyLprof();
        return runner.run({
            userInput: userInput,
            context: path.dirname(tab.buffer.file.path)
        })
        .then(({messagePProfile, stats}) => {
            // show success message
            this.statusView.update({
                show: true,
                status: 'success',
                message: messagePProfile
            });

            // render gutters
            atom.workspace.getTextEditors().forEach(editor => {
                let path = editor.buffer.file ? editor.buffer.file.path : null;
                if (path) {
                    this.statsGutter.render(
                        editor,
                        this.getFileStats(path, stats)
                    );
                }
            });
        }).catch(({message}) => {
            return this.statusView.update({
                show: true,
                status: 'error',
                message: message
            });
        }).finally(() => {
            return this.launcherView.update({
                status: 'idle'
            });
        });
    }

    toggle() {
        this.showLauncher = !this.showLauncher;
        if (this.showLauncher) {
            this.launcherView.update({
                show: true,
                content: this.launcherContent
            });
            return this.statusView.update({
                show: false
            });
        } else {
            this.launcherView.update({
                show: false,
                content: this.launcherContent
            });
            atom.workspace.getTextEditors().forEach(editor => {
                this.statsGutter.render(editor, [])
            });
        }
    }

};

let statsGutter = new StatsGutter({
    fields: [
        {<commit_msg>[core] Guard against invalid files<commit_after>'use babel';

// 3p
import _ from 'underscore-plus';
import { CompositeDisposable } from 'atom';
import fs from 'fs';
import path from 'path';

// project
import LauncherView from './utils/views/launcher-view.jsx';
import PyLprof from './pylprof/runner.js';
import StatsGutter from './utils/stats-gutter.js';
import StatusView from './utils/views/status-view.jsx';

class PProfile {

    constructor({config, statsGutter}) {
        this.subscriptions = null;
        this.showingLauncher = false;
        this.config = config;
        this.statsGutter = statsGutter;
    }

    getBufferFile() {
        const tab = atom.workspace.getActiveTextEditor();
        return tab.buffer.file;
    }

    validate(file) {
        if (!file) {
            return {
                valid: false,
                reason: 'Please save the buffer to run a profile.'
            }
        }
        if (path.extname(file.path) !== '.py') {
            return {
                valid: false,
                reason: 'Cannot profile non-python files.'
            }
        }
        return {
            valid: true
        }
    }

    activate(state) {
        // initialize launcher
        this.launcherContent = state.launcherContent;
        if (!state.launcherContent) {
            let cmdfile = path.resolve(__dirname, 'launcher_cmd.py');
            this.launcherContent = fs.readFileSync(cmdfile, 'utf8');
        }

        this.launcherView = new LauncherView({
            show: this.showingLauncher,
            onRun: this.run.bind(this),
            grammar: 'source.python',
            content: this.launcherContent,
            onChange: c => { this.launcherContent = c; }
        });
        atom.workspace.addBottomPanel({
            item: this.launcherView.element
        });

        // initialize status view
        this.statusView = new StatusView({
            show: false
        });
        atom.workspace.addBottomPanel({
            item: this.statusView.element
        });

        this.subscriptions = new CompositeDisposable();
        let cmds = atom.commands.add('atom-workspace', {
            'pprofile:toggle': this.toggle.bind(this)
        });
        return this.subscriptions.add(cmds);
    }

    deactivate() {
        this.modalPanel.destroy();
        this.subscriptions.dispose();
        this.pprofileView.destroy();
    }

    serialize() {
        return {
            launcherContent: this.launcherContent
        };
    }

    getFileStats(filename, stats) {
        let basename = path.basename(filename);
        let filestats = _.find(stats, s => s.file.endsWith(basename));
        return filestats ? filestats.stats : [];
    }

    run(userInput) {
        let file = this.getBufferFile();
        let validateResult = this.validate(file);
        if (!validateResult.valid) {
            this.statusView.update({
                show: true,
                status: 'error',
                message: validateResult.reason
            });
            return;
        }

        this.launcherView.update({
            content: this.launcherContent,
            status: 'running',
            show: true
        });

        let runner = new PyLprof();
        return runner.run({
            userInput: userInput,
            context: path.dirname(file.path)
        })
        .then(({messagePProfile, stats}) => {
            // show success message
            this.statusView.update({
                show: true,
                status: 'success',
                message: messagePProfile
            });

            // render gutters
            atom.workspace.getTextEditors().forEach(editor => {
                let path = editor.buffer.file ? editor.buffer.file.path : null;
                if (path) {
                    this.statsGutter.render(
                        editor,
                        this.getFileStats(path, stats)
                    );
                }
            });
        }).catch(({message}) => {
            return this.statusView.update({
                show: true,
                status: 'error',
                message: message
            });
        }).finally(() => {
            return this.launcherView.update({
                status: 'idle'
            });
        });
    }

    toggle() {
        let willShowLauncher = !this.showingLauncher;
        if (willShowLauncher) {
            // check whether the current buffer is saved
            let file = this.getBufferFile();
            let validateResult = this.validate(file);
            if (!validateResult.valid) {
                this.statusView.update({
                    show: true,
                    status: 'error',
                    message: validateResult.reason
                });
            }
            this.launcherView.update({
                show: true,
                content: this.launcherContent
            });
            this.showingLauncher = true;
        } else {
            this.launcherView.update({
                show: false,
                content: this.launcherContent
            });
            this.statusView.update({
                show: false
            });
            atom.workspace.getTextEditors().forEach(editor => {
                this.statsGutter.render(editor, [])
            });
            this.showingLauncher = false;
        }
    }

};

let statsGutter = new StatsGutter({
    fields: [
        {
{'fraction_non_alphanumeric': 0.11292913069664726, 'fraction_numerical': 0.0004015257980325236, 'mean_word_length': 1.4630407911001235, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2919880', 'n_tokens_mistral': 2706, 'n_tokens_neox': 2567, 'n_words': 514}