const {
  getQueryStringParam, Component,
  InMemoryDarBuffer, substanceGlobals,
  platform
} = window.substance

const { JATSImportDialog, TextureArchive, Texture } = window.texture

const ipc = require('electron').ipcRenderer
const darServer = require('dar-server')
const { FSStorageClient } = darServer
const url = require('url')
const path = require('path')

window.addEventListener('load', () => {
  substanceGlobals.DEBUG_RENDERING = platform.devtools
  App.mount({}, window.document.body)
})

class App extends Component {

  didMount() {
    this._init()
    this._archive.on('archive:changed', this._archiveChanged, this)
    ipc.on('document:save', () => {
      this._save()
    })
    ipc.on('document:save-as', (event, newArchiveDir) => {
      this._saveAs(newArchiveDir)
    })
  }

  dispose() {
    // TODO: is it necessary to do ipc.off?
    // (App component is never unmounted, only the full window is killed)
  }

  getInitialState() {
    return {
      archive: undefined,
      error: undefined
    }
  }

  render($$) {
    let el = $$('div').addClass('sc-app')
    let { archive, error } = this.state

    if (archive) {
      el.append(
        $$(Texture, {
          archive
        })
      )
    } else if (error) {
      if (error.type === 'jats-import-error') {
        el.append(
          $$(JATSImportDialog, { errors: error.detail })
        )
      } else {
        el.append(
          'ERROR:',
          error.message
        )
      }
    } else {
      // LOADING...
    }
    return el
  }

  _init() {
    let archiveDir = getQueryStringParam('archiveDir')
    // let isNew = getQueryStringParam('isNew')
    console.info('archiveDir', archiveDir)
    let storage = new FSStorageClient()
    let buffer = new InMemoryDarBuffer()
    let archive = new TextureArchive(storage, buffer)
    this._archive = archive
    archive.load(archiveDir)
      .then(() => {
        this._updateTitle()
        this.setState({archive})
      })
      .catch(error => {
        console.error(error)
        this.setState({error})
      })
  }

  /*
    We may want an explicit save button, that can be configured on app level,
    but passed down to editor toolbars.
  */
  _save() {
    this.state.archive.save().then(() => {
      this._updateTitle(false)
    }).catch(err => {
      console.error(err)
    })
  }

  _saveAs(newArchiveDir) {
    console.info('saving as', newArchiveDir)
    this.state.archive.saveAs(newArchiveDir).then(() => {
      this._updateTitle(false)
      ipc.send('document:save-as:successful')
      // Update the browser url, so on reload, we get the contents from the
      // new location
      let newUrl = url.format({
        pathname: path.join(__dirname, 'index.html'),
        protocol: 'file:',
        query: {
          archiveDir: newArchiveDir
        },
        slashes: true
      })
      window.history.replaceState({}, 'After Save As', newUrl);
    }).catch(err => {
      console.error(err)
    })
  }

  _archiveChanged() {
    const hasPendingChanges = this._archive.hasPendingChanges()
    if (hasPendingChanges) {
      ipc.send('document:unsaved')
      this._updateTitle(hasPendingChanges)
    }
  }

  _updateTitle(hasPendingChanges) {
    let newTitle = this._archive.getTitle()
    if (hasPendingChanges) {
      newTitle += " *"
    }
    document.title = newTitle
  }
}

@@ -84,16 +84,35 @@
 platform
+, DefaultDOMElement
 %0A%7D = win
@@ -811,24 +811,151 @@
 )%0A  
-%7D%0A%0A  dispose() %7B
+  DefaultDOMElement.getBrowserWindow().on('keydown', this._keyDown, this)%0A  %7D%0A%0A  dispose() %7B%0A    DefaultDOMElement.getBrowserWindow().off(this)
 %0A   
@@ -3496,11 +3496,312 @@
 itle%0A  %7D
+%0A%0A  _keyDown(event) %7B%0A    if ( event.key === 'Dead' ) return%0A    // Handle custom keyboard shortcuts globally%0A    let archive = this.state.archive%0A    if (archive) %7B%0A      let manuscriptSession = archive.getEditorSession('manuscript')%0A      manuscriptSession.keyboardManager.onKeydown(event)%0A    %7D%0A  %7D
 %0A%7D%0A

Connect global key handling.