// import { get } from 'lodash'
import React from 'react'
import ReactDOM from 'react-dom'

import {
  ProseEditorConfigurator as Configurator,
  EditorSession
} from 'substance'

import config from './config'
import Editor from './Editor'
import Importer from './SimpleEditorImporter'
import SimpleExporter from './SimpleEditorExporter'

import './SimpleEditor.scss'

export default class SimpleEditor extends React.Component {
  constructor (props) {
    super(props)
    this.save = this.save.bind(this)
    this.updateTrackChangesStatus = this.updateTrackChangesStatus.bind(this)
    this._checkRights = this._checkRights.bind(this)

    this._releaseLock = this._releaseLock.bind(this)
    this._acquireLock = this._acquireLock.bind(this)
  }

  // TODO -- is this necessary?
  componentWillMount () {
    const { fragment } = this.props
    if (fragment) {
      this._checkRights()
      this._acquireLock()
    }
  }

  createSession () {
    const { fragment } = this.props
    let source
    if (fragment) { source = fragment.source }

    const configurator = new Configurator().import(config)
    configurator.addImporter('html', Importer)

    const importer = configurator.createImporter('html')
    const doc = importer.importDocument(source)

    const editorSession = new EditorSession(doc, {
      configurator: configurator
    })

    editorSession.setSaveHandler({
      saveDocument: this.save,
      uploadFile: this.props.fileUpload
    })

    return {
      configurator: configurator,
      editorSession: editorSession
    }
  }

  updateTrackChangesStatus () {
    const { fragment, update } = this.props

    const patch = {
      id: fragment.id,
      trackChanges: !fragment.trackChanges
    }

    update(patch)
  }

  save (source, changes, callback) {
    const { onSave } = this.props
    const config = this.state.config
    const exporter = new SimpleExporter(config)
    const convertedSource = exporter.exportDocument(source)

    return onSave(convertedSource)
  }

  // NOTE -- Theoretically, we shouldn't lock when the editor is in read only
  // mode. This gets complicated however, as the user will be able to be add
  // comments, which will in turn affect the fragment. So, it is better to
  // avoid any possible data corruption until collaboration is added.
  _acquireLock () {
    const { fragment, update, user } = this.props

    fragment.lock = {
      editor: { username: user.username },
      timestamp: new Date()
    }

    update(fragment)
  }

  _releaseLock () {
    const { fragment, update } = this.props

    // TODO -- maybe this is causing the lock problems?
    // if (get(fragment, 'lock.editor.username') === user.username) {
    //   fragment.lock = null
    // }

    fragment.lock = null
    update(fragment)
  }

  // TODO -- rewrite cleaner, and as isDisabled (returns boolean)
  _checkRights () {
    const { fragment, user } = this.props

    if (user.admin) return this.setState({ canEdit: true })

    if ((fragment.progress['review'] === 1 && user.teams[0].teamType.name === 'Author') ||
        (fragment.progress['edit'] === 1 && user.teams[0].teamType.name === 'Copy Editor')) {
      this.setState({ canEdit: true })
    } else {
      this.setState({ canEdit: false })
    }
    if (user.teams[0].teamType.name === 'Production Editor') {
      this.setState({ canEdit: true })
    }
  }

  // TODO -- remove when reloading works correctly (by refreshing props)
  componentWillReceiveProps (nextProps) {
    const { fragment } = this.props
    if (fragment) return

    var self = this
    if (nextProps.fragment) {
      setTimeout(function () {
        self._checkRights()
        self.componentDidMount()
      }, 0)
    }
  }

  componentDidMount () {
    const el = ReactDOM.findDOMNode(this)

    const { book, fragment, history, onSave, update, user } = this.props
    const { configurator, editorSession } = this.createSession()

    if (!fragment) return

    const containerId = 'body'

    // TODO -- delete
    const trackChanges = fragment.trackChanges
    const updateTrackChangesStatus = this.updateTrackChangesStatus
    const disabled = !this.state.canEdit

    // TODO -- justify
    this.setState({
      config: configurator.config
    })

    this.editor = Editor.mount({
      book,
      configurator,
      containerId,
      disabled,
      editorSession,
      fragment,
      history,
      onSave,
      trackChanges,
      update,
      updateTrackChangesStatus,
      user
    }, el)
    // TODO -- pull all above into its own function

    window.addEventListener('beforeunload', this._releaseLock)
  }

  componentWillUnmount () {
    this._releaseLock()
    window.removeEventListener('beforeunload', this._releaseLock)

    this.editor.dispose()
  }

  // TODO -- use this for correctly refreshing props when the fragment arrives
  // this.writer does not exist, you have to make it in componentDidMount
  // this.writer = Editor.mount( ....

  // New props arrived, update the editor
  // componentDidUpdate () {
  //   console.log('did update')
  //
  //   var session = this.createSession()
  //   var documentSession = session.documentSession
  //   var configurator = session.configurator
  //
  //   this.writer.extendProps({
  //     documentSession: documentSession,
  //     configurator: configurator
  //   })
  //
  //   console.log(this.writer)
  // }
  //
  // componentWillUnmount () {
  //   this.writer.dispose()
  // }

  // TODO -- do I even need a render here?
  render () {
    return (
      <div className='editor-wrapper' />
    )
  }
}

SimpleEditor.propTypes = {
  book: React.PropTypes.object,
  // canEdit: React.PropTypes.bool, // needed?
  fragment: React.PropTypes.object,
  history: React.PropTypes.object.isRequired,
  onSave: React.PropTypes.func.isRequired,
  update: React.PropTypes.func.isRequired,
  fileUpload: React.PropTypes.func.isRequired,
  user: React.PropTypes.object.isRequired
}