import { includes, some } from 'lodash'

import {
  ProseEditor,
  TOCProvider,
  Toolbar
} from 'substance'

import Comments from './panes/Comments/CommentBoxList'
import CommentsProvider from './panes/Comments/CommentsProvider'
import ContainerEditor from './ContainerEditor'

import Notes from './panes/Notes/Notes'
import NotesProvider from './panes/Notes/NotesProvider'

import TableOfContents from './panes/TableOfContents/TableOfContents'
import TrackChangesProvider from './elements/track_change/TrackChangesProvider'

import ModalWarning from './elements/modal_warning/ModalWarning'

class Editor extends ProseEditor {
  constructor (parent, props) {
    super(parent, props)

    this.handleActions({
      'showComments': function () { this.toggleCommentsArea(true) },
      'hideComments': function () { this.toggleCommentsArea(false) },

      // TODO -- clean them up like changesNotSaved
      'trackChangesUpdate': function () { this.updateTrackChange() },
      'trackChangesViewToggle': function () { this.trackChangesViewToggle() },
      // 'changesNotSaved': function () { this.changesNotSaved() }
      'changesNotSaved': this.changesNotSaved
    })
  }

  changesNotSaved () {
    this.extendState({ changesNotSaved: true })
  }

  trackChangesViewToggle () {
    this.extendState({
      trackChangesView: !this.state.trackChangesView
    })
  }

  updateTrackChange () {
    // TODO -- clean up this.props and this.refs
    this.extendProps({ trackChanges: !this.props.trackChanges })
    this.props.updateTrackChangesStatus(!this.props.trackChanges)
    this.refs.toolbar.extendProps({trackChanges: this.props.trackChanges})
  }

  willUpdateState () {}

  didMount () {
    this.extendState({ editorReady: true })
  }

  render ($$) {
    const { trackChangesView } = this.state
    const canToggleTrackChanges = this.canToggleTrackChanges()

    const el = $$('div').addClass('sc-prose-editor')

    // left side: editor and toolbar
    let toolbar = this._renderToolbar($$)
    let editor = this._renderEditor($$)

    let SplitPane = this.componentRegistry.get('split-pane')
    let ScrollPane = this.componentRegistry.get('scroll-pane')
    let Overlay = this.componentRegistry.get('overlay')

    // TODO -- unnecessary // posssibly breaks book builder dnd
    let ContextMenu = this.componentRegistry.get('context-menu') // new what does it do?
    // let Dropzones = this.componentRegistry.get('dropzones') // new what does it do?

    const footerNotes = $$(Notes)

    const props = {
      book: this.props.book,
      fragment: this.props.fragment,
      history: this.props.history
    }

    const toc = $$(TableOfContents, props)

    var editorWithFooter = $$('div')
      .append(
        editor,
        footerNotes
      )

    var commentsPane = this.state.editorReady
    ? $$(Comments, {
      // TODO -- should probably remove the || {}
      comments: this.props.fragment.comments || {},
      fragment: this.props.fragment,
      update: this.props.update,
      user: this.props.user
    }).addClass('sc-comments-pane')
    : $$('div')

    var editorWithComments = $$(SplitPane, { sizeA: '100%', splitType: 'vertical' })
      .append(
        editorWithFooter,
        commentsPane
      )

    var contentPanel = $$(ScrollPane, {
      name: 'contentPanel',
      // contextMenu: 'custom',
      scrollbarPosition: 'right'
    })
    .append(editorWithComments,
      $$(Overlay),
      $$(ContextMenu)
      // $$(Dropzones)
    )
    .attr('id', 'content-panel')
    .ref('contentPanel')

    const contentPanelWithSplitPane = $$(SplitPane, { sizeA: '75%', splitType: 'vertical' })
      .append(
        contentPanel,
        toc
      )

    el.append(
      $$(SplitPane, { splitType: 'horizontal' })
        .append(
          toolbar,
          contentPanelWithSplitPane
        )
    )

    if (trackChangesView && canToggleTrackChanges) {
      el.addClass('track-changes-mode')
    }

    const modal = $$(ModalWarning, {
      width: 'medium',
      textAlign: 'center'
    })

    if (this.state.changesNotSaved) {
      return el.append(modal)
    }

    return el
  }

  // TODO -- leverage ProseEditor's this._renderToolbar maybe?
  _renderToolbar ($$) {
    let viewMode = this.props.disabled ? $$('span')
        .addClass('view-mode')
        .append('Editor is in Read-Only mode')
        : ''

    let commandStates = this.commandManager.getCommandStates()

    return $$('div')
      .addClass('se-toolbar-wrapper')
      .append(
        $$(Toolbar, {
          commandStates: commandStates,
          trackChanges: this.props.trackChanges,
          trackChangesView: this.state.trackChangesView,
          toolGroups: [
            'text',
            'document',
            'annotations',
            'default',
            'track-change-enable',
            'track-change-toggle-view'
          ]
        }).ref('toolbar')
      )
      .append(viewMode)
  }

  _renderEditor ($$) {
    const configurator = this.props.configurator
    const editing = this.props.disabled ? 'selection' : 'full'
    return $$(ContainerEditor, {
      editing: editing,
      editorSession: this.editorSession,
      commands: configurator.getSurfaceCommandNames(),
      containerId: 'body',
      spellcheck: 'native',
      textTypes: configurator.getTextTypes(),
      trackChanges: this.props.trackChanges,
      updateTrackChangesStatus: this.props.updateTrackChangesStatus,
      history: this.props.history,
      book: this.props.book
    }).ref('body')
  }

  getInitialState () {
    return {
      changesNotSaved: false,
      editorReady: false,
      trackChangesView: true
    }
  }

  canToggleTrackChanges () {
    const { user } = this.props
    const accepted = ['admin', 'production-editor', 'copy-editor']
    return some(accepted, (role) => includes(user.roles, role))
  }

  scrollTo (nodeId) {
    this.refs.contentPanel.scrollTo(nodeId)
  }

  toggleCommentsArea (show) {
    var self = this

    setTimeout(function () {
      var el = self.refs.contentPanel

      if (show && !el.hasClass('sc-has-comments')) {
        el.addClass('sc-has-comments')
      }

      if (!show && el.hasClass('sc-has-comments')) {
        el.removeClass('sc-has-comments')
      }
    })
  }

  getChildContext () {
    const oldContext = super.getChildContext()
    const doc = this.doc

    // toc provider
    const tocProvider = new TOCProvider(doc, {
      containerId: 'body'
    })

    // notes provider
    const notesProvider = new NotesProvider(doc)

    // comments provider
    const commentsProvider = new CommentsProvider(doc, {
      commandManager: this.commandManager,
      comments: this.props.fragment.comments,
      containerId: this.props.containerId,
      controller: this,
      editorSession: this.editorSession,
      fragment: this.props.fragment,
      surfaceManager: this.surfaceManager,
      toggleCommentsArea: this.toggleCommentsArea,
      update: this.props.update
    })

    // TODO -- do I need all of these?
    // track changes provider
    const trackChangesProvider = new TrackChangesProvider(doc, {
      commandManager: this.commandManager,
      containerId: this.props.containerId,
      controller: this,
      editorSession: this.editorSession,
      surfaceManager: this.surfaceManager,
      user: this.props.user
    })

    // attach all to context
    return {
      ...oldContext,
      tocProvider,
      notesProvider,
      commentsProvider,
      trackChangesProvider
    }
  }
}

export default Editor