/**
 * Root component
 *
 * Generated by coz on 8/6/2016,
 * from a template provided by apeman-asset-templates.
 *
 * @class Root
 */
'use strict'

import React, { Component, PropTypes as types } from 'react'
import defineDebug from 'debug'
import { Header, Toast, Main, Stack, DevKit } from '../fragments'
import { viewPathname } from 'ore-fol-helpers'
import { asPure, asConnected, combine } from '../wrappers'
import { get } from 'bwindow'
import { title } from 'bmeta'
import { SessionFields } from 'ore-fol-enums'
import { Provider } from 'react-redux'
import ContextService from '../../../lib/services/context_service'
const { SIGNED_SESSION } = SessionFields

const debug = defineDebug('project:root')

/** @lends Root */
class Root extends Component {
  // --------------------
  // Specs
  // --------------------
  static get propTypes () {
    return {
      lang: types.string,
      topView: types.object,
      mainStackName: types.string,
      modalStackName: types.string,
      tabName: types.string,
      headerConfig: types.object,
      store: types.object
    }
  }

  static get defaultProps () {
    return {}
  }

  render () {
    const s = this
    const { props } = s

    let {
      srvc,
      l,
      lang,
      signed,
      mainStackName,
      modalStackName
    } = props
    let shared = { lang, l, signed, srvc }

    return (
      <div id={ props.id }
           className='root'>
        { props.spinner }
        <Header { ...shared }
                selectedTab={ props.tabName }
                mainStackName={ mainStackName }
                modalStackName={ modalStackName }
                { ...props.headerConfig }
        />
        <Main>
          <Toast />
          <Stack { ...shared }
                 className='main-stack'
                 stackName={ mainStackName }
                 modalStackName={ modalStackName }
                 views={ props.mainViews }
          />
          <DevKit />
        </Main>
        <Stack { ...shared }
               className='modal-stack'
               stackName={ modalStackName }
               modalStackName={ modalStackName }
               views={ props.modalViews }
               fixed
        />
      </div>
    )
  }

  // --------------------
  // Lifecycle
  // --------------------

  componentWillMount () {
    debug('willMount')
    const s = this
  }

  componentDidMount () {
    debug('didMount')
    const history = get('history')
    const s = this
    const { props } = s
    const { store, srvc } = props
    const { joinSystem } = srvc.systemService
    const { initSpin } = srvc.spinService
    const { pageTitle } = srvc.localeService

    initSpin('root-spin')
    joinSystem({})

    let { stackToRedirect } = props
    if (stackToRedirect) {
      history.replaceState(null, null, viewPathname(stackToRedirect))
      for (let hook of store.hooks) {
        hook.trigger({ force: true })
      }
    }

    title.set(pageTitle())
  }

  componentWillUnmount () {
    debug('willUnmount')
    const s = this
    const { props } = s
    const { srvc } = props
    const { leaveSystem } = srvc.systemService
    leaveSystem()
  }

  // --------------------
  // Context
  // --------------------
  getChildContext () {
    const s = this
    const { l, srvc } = s.props
    return {
      l,
      srvc
    }
  }

  static get childContextTypes () {
    return {
      l: types.func,
      srvc: types.object
    }
  }
}

export default combine(
  asConnected((state, ownProps) => {
    const {
      srvc,
      topView,
      mainStackName,
      modalStackName
    } = ownProps

    const { l } = srvc.localeService
    const { hasSpin } = srvc.spinService
    const { getViews } = srvc.viewService
    const { getSession } = srvc.sessionService
    const { getLang } = srvc.localeService
    return {
      l,
      srvc,
      lang: getLang(),
      signed: getSession(SIGNED_SESSION),
      spinning: hasSpin('root-spin'),
      mainViews: [ topView, ...getViews(mainStackName) ].filter(Boolean),
      modalViews: [ ...getViews(modalStackName) ].filter(Boolean)
    }
  }),
  (Root) =>
    (props) => {
      const { store } = props
      return (
        <Provider store={ store }>
          <Root { ...props }
                srvc={ ContextService.newServices({ store }) }
          />
        </Provider>
      )
    }
)(Root)
