const { CompositeDisposable, Emitter } = require('atom')
const AboutView = require('./components/about-view')

// Deferred requires
let shell

module.exports = class About {
  constructor (initialState) {
    this.subscriptions = new CompositeDisposable()
    this.emitter = new Emitter()

    this.state = initialState
    this.views = {
      aboutView: null
    }

    this.subscriptions.add(
      atom.workspace.addOpener(uriToOpen => {
        if (uriToOpen === this.state.uri) {
          return this.deserialize()
        }
      })
    )

    this.subscriptions.add(
      atom.commands.add('atom-workspace', 'about:view-release-notes', () => {
        shell = shell || require('electron').shell
        shell.openExternal(
          this.state.updateManager.getReleaseNotesURLForCurrentVersion()
        )
      })
    )
  }

  destroy () {
    if (this.views.aboutView) this.views.aboutView.destroy()
    this.views.aboutView = null

    if (this.state.updateManager) this.state.updateManager.dispose()
    this.setState({ updateManager: null })

    this.subscriptions.dispose()
  }

  setState (newState) {
    if (newState && typeof newState === 'object') {
      let { state } = this
      this.state = Object.assign({}, state, newState)

      this.didChange()
    }
  }

  didChange () {
    this.emitter.emit('did-change')
  }

  onDidChange (callback) {
    this.emitter.on('did-change', callback)
  }

  deserialize (state) {
    if (!this.views.aboutView) {
      this.setState(state)

      this.views.aboutView = new AboutView({
        uri: this.state.uri,
        updateManager: this.state.updateManager,
        currentAtomVersion: this.state.currentAtomVersion,
        currentElectronVersion: this.state.currentElectronVersion,
        currentChromeVersion: this.state.currentChromeVersion,
        currentNodeVersion: this.state.currentNodeVersion,
        availableVersion: this.state.updateManager.getAvailableVersion()
      })
      this.handleStateChanges()
    }

    return this.views.aboutView
  }

  handleStateChanges () {
    this.onDidChange(() => {
      if (this.views.aboutView) {
        this.views.aboutView.update({
          updateManager: this.state.updateManager,
          currentAtomVersion: this.state.currentAtomVersion,
          currentElectronVersion: this.state.currentElectronVersion,
          currentChromeVersion: this.state.currentChromeVersion,
          currentNodeVersion: this.state.currentNodeVersion,
          availableVersion: this.state.updateManager.getAvailableVersion()
        })
      }
    })

    this.state.updateManager.onDidChange(() => {
      this.didChange()
    })
  }
}
