<commit_before>'use babel'

import React, {Component} from 'react'
// import {CompositeDisposable, Disposable} from 'atom'
import fs from 'fs'
import path from 'path'
import deepForceUpdate from 'react-deep-force-update'
import Output from './Output'

export default class OutputList extends Component {

  constructor(props) {
    super(props)
    this.state = {
      outputs: [],
      plugins: [],
    }
    this.watch = null
    // this.subscriptions = new CompositeDisposable()
    this.copyOutputs = this.copyOutputs.bind(this)
    // this.copyOutput = this.copyOutput.bind(this)
    this.clearOutputs = this.clearOutputs.bind(this)
    this.editPlugin = this.editPlugin.bind(this)
    this.selectPlugin = this.selectPlugin.bind(this)
    // this.createPlugin = this.createPlugin.bind(this)
    this.selectHistory = this.selectHistory.bind(this)
    this.parseProps = this.parseProps.bind(this)
    this.parseOutput = this.parseOutput.bind(this)
    this.indexPlugins = this.indexPlugins.bind(this)
    this.watchPlugins = this.watchPlugins.bind(this)
  }

  componentWillMount() {
    let plugins = this.indexPlugins()
    this.setState({plugins})
    this.watch = this.watchPlugins()
  }

  componentDidMount() {
    this.parseProps(this.props)
  }

  componentWillReceiveProps(nextProps) {
    this.parseProps(nextProps)
  }

  shouldComponentUpdate(nextProps, nextState) {
    return nextState !== this.state
  }

  componentWillUnmount() {
    this.watch.close()
  }

  render() {
    let buttons = (
      <div className="buttons">
        <button
          className="copy btn btn-default icon icon-clippy"
          title="Copy"
          data-toggle="tooltip"
          onClick={this.copyOutputs}
        />
        <button
          className="clear btn btn-default icon icon-trashcan"
          title="Clear outputs"
          data-toggle="tooltip"
          onClick={this.clearOutputs}
        />
        {/*<button
          className="new btn btn-default icon icon-plus"
          title="Create new plugin"
          data-toggle="tooltip"
          onClick={this.createPlugin}
        />*/}
      </div>
    )
    let outputs = this.state.outputs.map(output => {
      return <Output
        key={output.key}
        output={output}
        plugins={this.state.plugins}
        selectPlugin={this.selectPlugin}
        copyOutput={this.copyOutput}
        editPlugin={this.editPlugin}
      />
    })
    return (
      <div className="output-list native-key-bindings" tabIndex={-1}>
        {buttons}
        {outputs}
      </div>
    )
  }

  copyOutputs(event) {
    let outputs = this.state.outputs.map(output => output.data)
    atom.clipboard.write(JSON.stringify(outputs))
  }

  // copyOutput(output) {
  //   atom.clipboard.write(JSON.stringify(output))
  // }

  clearOutputs(event) {
    this.setState({outputs: []})
  }

  editPlugin(output) {
    let plugin = this.state.plugins.find(plugin => plugin.name === output.plugin)
    atom.workspace.open(plugin.filepath, {
      split: 'down',
      searchAllPanes: true
    })
  }

  selectPlugin(output, plugin) {
    let outputs = this.state.outputs.map(_output => {
      if (_output.key === output.key) return Object.assign({}, _output, {plugin})
      return _output
    })
    this.setState({outputs})
  }

  // createPlugin(event) {
  //   let source = path.join(__dirname, '..', 'utils', 'plugin-template.js')
  //   let target = path.join(__dirname, '..', 'plugins', 'New.js')
  //   // fs.createReadStream(source).pipe(target)
  //   fs.writeFileSync(target, fs.readFileSync(source))
  //   atom.workspace.open(target, {
  //     split: 'down'
  //   })
  // }

  parseProps(props) {
    if (props.status) {
      switch (props.status) {
        case 'started':
          return console.group('OutputList.render')
        case 'exited':
        case 'stopped':
          this.history = this.history.concat({
            time: new Date(),
            outputs: this.state.outputs.map(output => Object.assign({}, output))
          })
          this.setState({historyIndex: this.history.length - 1})
          // this.state.outputs.forEach(output => console.log(output))<commit_msg>Add output state history and controls<commit_after>'use babel'

import React, {Component} from 'react'
// import {CompositeDisposable, Disposable} from 'atom'
import fs from 'fs'
import path from 'path'
import deepForceUpdate from 'react-deep-force-update'
import Output from './Output'

export default class OutputList extends Component {

  constructor(props) {
    super(props)
    this.state = {
      outputs: [],
      plugins: [],
      historyIndex: 0
    }
    this.history = []
    this.watch = null
    // this.subscriptions = new CompositeDisposable()
    this.copyOutputs = this.copyOutputs.bind(this)
    // this.copyOutput = this.copyOutput.bind(this)
    this.clearOutputs = this.clearOutputs.bind(this)
    this.editPlugin = this.editPlugin.bind(this)
    this.selectPlugin = this.selectPlugin.bind(this)
    // this.createPlugin = this.createPlugin.bind(this)
    this.selectHistory = this.selectHistory.bind(this)
    this.parseProps = this.parseProps.bind(this)
    this.parseOutput = this.parseOutput.bind(this)
    this.indexPlugins = this.indexPlugins.bind(this)
    this.watchPlugins = this.watchPlugins.bind(this)
  }

  componentWillMount() {
    let plugins = this.indexPlugins()
    this.setState({plugins})
    this.watch = this.watchPlugins()
  }

  componentDidMount() {
    this.parseProps(this.props)
  }

  componentWillReceiveProps(nextProps) {
    this.parseProps(nextProps)
  }

  shouldComponentUpdate(nextProps, nextState) {
    return nextState !== this.state
  }

  componentWillUnmount() {
    this.watch.close()
  }

  render() {
    let options = this.history.map((snapshot, index) => {
      let time = snapshot.time.toLocaleString()
      return <option key={index} value={index}>{time}</option>
    })
    let toggle;
    if (this.history.length > 0) toggle = (
      <select
        className="toggle"
        value={this.state.historyIndex}
        onChange={this.selectHistory}
      >
        {options}
      </select>
    )
    let buttons = (
      <div className="buttons">
        {toggle}
        <button
          className="copy btn btn-default icon icon-clippy"
          title="Copy"
          data-toggle="tooltip"
          onClick={this.copyOutputs}
        />
        <button
          className="clear btn btn-default icon icon-trashcan"
          title="Clear outputs"
          data-toggle="tooltip"
          onClick={this.clearOutputs}
        />
        {/*<button
          className="new btn btn-default icon icon-plus"
          title="Create new plugin"
          data-toggle="tooltip"
          onClick={this.createPlugin}
        />*/}
      </div>
    )
    let outputs = this.state.outputs.map(output => {
      return <Output
        key={output.key}
        output={output}
        plugins={this.state.plugins}
        selectPlugin={this.selectPlugin}
        copyOutput={this.copyOutput}
        editPlugin={this.editPlugin}
      />
    })
    return (
      <div className="output-list native-key-bindings" tabIndex={-1}>
        {buttons}
        {outputs}
      </div>
    )
  }

  copyOutputs(event) {
    let outputs = this.state.outputs.map(output => output.data)
    atom.clipboard.write(JSON.stringify(outputs))
  }

  // copyOutput(output) {
  //   atom.clipboard.write(JSON.stringify(output))
  // }

  clearOutputs(event) {
    this.setState({outputs: []})
  }

  editPlugin(output) {
    let plugin = this.state.plugins.find(plugin => plugin.name === output.plugin)
    atom.workspace.open(plugin.filepath, {
      split: 'down',
      searchAllPanes: true
    })
  }

  selectPlugin(output, plugin) {
    let outputs = this.state.outputs.map(_output => {
      if (_output.key === output.key) return Object.assign({}, _output, {plugin})
      return _output
    })
    this.setState({outputs})
    this.history[this.state.historyIndex].outputs = this.state.outputs.map(output => Object.assign({}, output))
  }

  selectHistory(event) {
    let historyIndex = event.target.value
    let outputs = this.history[historyIndex].outputs.map(output => Object.assign({}, output))
    this.setState({outputs, historyIndex})
  }

  // createPlugin(event) {
  //   let source = path.join(__dirname, '..', 'utils', 'plugin-template.js')
  //   let target = path.join(__dirname, '..', 'plugins', 'New.js')
  //   // fs.createReadStream(source).pipe(target)
  //   fs.writeFileSync(target, fs.readFileSync(source))
  //   atom.workspace.open(target, {
  //     split: 'down'
  //   })
  // }

  parseProps(props) {
    if (props.status) {
      switch (props.status) {
        case 'started':
          return console.group('OutputList.render')
        case 'exited':
        case 'stopped':
          this.history = this.history.concat({
            time: new Date(),
            outputs: this.state.outputs.map(output => Object.assign({}, output))
          })
          this.setState({historyIndex: this.history.length - 1})
          // this.state.outputs.forEach(output => console.log(output))
{'fraction_non_alphanumeric': 0.13946879440375998, 'fraction_numerical': 0.0006558093780741065, 'mean_word_length': 2.5756154747948417, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 39, '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': '5677384', 'n_tokens_mistral': 2788, 'n_tokens_neox': 2761, 'n_words': 484}