/**
 * ThreadList view
 *
 * Generated by coz on 2016-12-11,
 * from a template provided by apeman-asset-templates.
 *
 * @function ThreadListView
 */
'use strict'

import React, { Component, PropTypes as types } from 'react'
import defineDebug from 'debug'
import {
  ApView, ApViewHeader, ApViewBody,
  ApToggle, ApSearch,
  ApContainer,
  ApIconButton
} from 'apeman-react-basic'
import { ThreadList } from '../../fragments'
import { IconClasses, ViewEvents, PreferenceFields } from 'ore-fol-enums'
import {
  asConnected,
  asLocaled,
  asView,
  asServed,
  forSpin,
  forAuth,
  forList,
  forEvent,
  combine
} from '../../wrappers'

const debug = defineDebug('project:view:thread-list')

const { THREAD_ICON, ADD_ICON } = IconClasses
const { THREAD_SORT } = PreferenceFields

const { THREAD_CREATE_EVENT, THREAD_UPDATE_EVENT, THREAD_DESTROY_EVENT } = ViewEvents

const THREAD_SEARCH_TEXT = 'memory:thread-search-text'
const THREAD_SEARCH_DELAY = 300

/** @lends ThreadListView */
class ThreadListView extends Component {
  // --------------------
  // Specs
  // --------------------
  static get propTypes () {
    return {}
  }

  static get defaultProps () {
    return {}
  }

  render () {
    const s = this
    const {
      props,
      l,
      sortOptions
    } = s
    let {
      threads,
      searchText,
      sorter
    } = props
    return (
      <ApView id='thread-list-view'
              className='view'
              spinning={ props.spinning }
              way={ props.way }
      >
        <ApViewHeader onLeftTap={ s.handlePop }
                      leftText={ null }
                      leftIcon={ props.popIcon }
                      titleText={ s.title }
                      titleIcon={ THREAD_ICON }
                      onRightTap={ null }
                      rightIcon={ null }
                      rightText={ null }
        />

        <ApViewBody>
          <div className="thread-list-toolbar">
            <div className="thread-list-toolbar-item">
            </div>
            <div className="thread-list-toolbar-item">
              <ApToggle value={ sorter }
                        options={ sortOptions }
                        onToggle={ ({ data }) => s.handleSort(data) }
              />
            </div>
            <div className="thread-list-toolbar-item">
              <ApSearch righted
                        onChange={ ({ target }) => s.handleSearch(target.value) }
                        onClear={ () => s.handleSearch('') }
                        value={ props.searchText }
                        open={ !!props.searchText }
              />
            </div>
          </div>
          {
            searchText ? (
                <div className="thread-list-lead">
                  { l('leads.THREAD_LIST_LEAD', { vars: { searchText } }) }
                </div>
              ) : null
          }
          {
            threads ? (
                <div className='thread-list-wrap'>
                  <ThreadList spinning={ props.listSpinning }
                              threads={ threads.entities }
                              onDetail={ s.handleDetail }
                              alt={ l('alt.NO_THREAD_FOUND') }
                              hasMore={ threads.more }
                              moreText={ l('buttons.SHOW_MORE') }
                              onMore={ s.handleMore }
                              moreSpinning={ props.moreSpinning }
                  />
                </div>
              ) : (
                <div className="thread-list-loading">{ l('messages.NOW_LOADING') }</div>
              )
          }
        </ApViewBody>
        <div className="floated-button-wrap">
          <ApContainer>
            <div className="avoid-aside">
              <ApIconButton className="floated-button"
                            primary
                            icon={ ADD_ICON }
                            onTap={ s.handleAdd }
              />
            </div>
          </ApContainer>
        </div>
      </ApView>
    )
  }

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

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

  componentDidMount () {
    debug('didMount')
    const s = this
    const { props } = s
    let { sorter, searchText } = props
    s.loadThreads({ sorter, searchText })

    s.listenEvent(THREAD_CREATE_EVENT, s.reloadThreads)
    s.listenEvent(THREAD_UPDATE_EVENT, s.reloadThreads)
    s.listenEvent(THREAD_DESTROY_EVENT, s.reloadThreads)
  }

  componentWillUnmount () {
    debug('willUnmount')
    const s = this

    clearTimeout(s._applySearchTimer)
  }

  // --------------------
  // Handlers
  // --------------------

  handleMore () {
    const s = this
    const { props } = s
    let { threads, searchText, sorter } = props
    let { next: offset } = threads.counts
    s.loadMoreThreads({ offset, sorter, searchText })
  }

  handleDetail ({ id: threadId }) {
    const s = this
    s.handlePush('ThreadDetailView', { threadId })
  }

  handleSort (sorter) {
    const s = this
    const { props } = s
    const { setPreference } = s.service('preferenceService')
    let changed = props.sorter !== sorter
    if (!changed) {
      return
    }
    setPreference(THREAD_SORT, sorter)
    let { searchText } = s.props
    s.loadThreads({ sorter, searchText })
  }

  handleSearch (searchText) {
    const s = this
    const { setMemory } = s.servivce('memoryService')
    setMemory(THREAD_SEARCH_TEXT, searchText && String(searchText).trim())
    clearTimeout(s._applySearchTimer)
    s._applySearchTimer = setTimeout(() => {
      let { sorter, searchText } = s.props
      s.loadThreads({ sorter, searchText })
    }, THREAD_SEARCH_DELAY)
  }

  handleAdd () {
    const s = this
    return s.ifAuthorized(() =>
      s.handlePushToModal('ThreadCreateView', {})
    )
  }

  // --------------------
  // Dynamic variables
  // --------------------

  get title () {
    const s = this
    const { totalText } = s.service('localeService')
    const { props, l } = s
    const { threads } = props
    return l('titles.THREADS', {
      vars: { total: totalText(threads && threads.counts) }
    })
  }

  get sortOptions () {
    const s = this
    const { l } = s
    return {
      ofNew: l('toggles.SORT_NEW'),
      ofStar: l('toggles.SORT_STAR')
      // FIXME
      // ofRecommend: l('toggles.SORT_RECOMMEND')
    }
  }

  // --------------------
  // Custom
  // --------------------

  loadThreads ({ sorter, searchText }) {
    const s = this
    const { use } = s.service('apiService')
    let load = () => use('threadApi').then((threadApi) =>
      s.applyListLoad({
        threads: () => threadApi.list({ searchText, sorter })
      })
    )
    let { threads } = s.props
    if (threads && threads.entities.length > 0) {
      return s.applySpinWhile({ listSpinning: load })
    } else {
      return s.applySpinWhile({ spinning: load })
    }
  }

  loadMoreThreads ({ sorter, searchText, offset }) {
    const s = this
    const { use } = s.service('apiService')
    return use('threadApi').then((threadApi) =>
      s.applySpinWhile({
        moreSpinning: () => s.applyListMore({
          threads: () => threadApi.list({ searchText, sorter, offset })
        })
      })
    )
  }

  reloadThreads () {
    const s = this
    const { props } = s
    let { sorter, searchText } = props
    s.loadThreads({ sorter, searchText })
  }

}

export default combine(
  forSpin(),
  forList(),
  forAuth(),
  forEvent(),
  asView(),
  asLocaled(),
  asServed(),
  asConnected(
    (state, { srvc }) => {
      const { getPreference } = srvc.preferenceService
      const { getMemory } = srvc.memoryService
      return {
        sorter: getPreference(THREAD_SORT) || 'ofNew',
        searchText: getMemory(THREAD_SEARCH_TEXT) || ''
      }
    }
  )
)(ThreadListView)

