/**
 * Show mixin.
 * @module ApShowMixin
 *
 * Generated by coz on 1/31/2016,
 * from a template provided by apeman-bud-react.
 *
 * @see https://facebook.github.io/react/
 */
'use strict'

import React from 'react'
import assert from 'assert'
import defaults from 'defaults'

const MODAL_WAY = 'PULL_UP'
const NAVIGATION_WAY = 'PUSH_LEFT'
const IMMEDIATE_WAY = 'NONE'

let ComponentsToShow = null

/** @lends ApShowMixin */
let ApShowMixin = {

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

  $apShowMixed: true,

  /**
   * Show view as with navigation way.
   * @param {object} name - Name of view component to show.
   * @param {object} [params] - View params
   * @returns {*|Promise}
   */
  showAsNavigated (name, params) {
    const s = this
    return s._show(name, params, NAVIGATION_WAY)
  },

  /**
   * Show view as with modal way.
   * @param {object} name - Name of view component to show.
   * @param {object} [params] - View params
   * @returns {*|Promise}
   */
  showAsModal (name, params) {
    const s = this
    return s._show(name, params, MODAL_WAY)
  },

  /**
   * Show view as with immediate way.
   * @param {object} name - Name of view component to show.
   * @param {object} [params] - View params
   * @returns {*|Promise}
   */
  showAsImmediate (name, params) {
    const s = this
    return s._show(name, params, IMMEDIATE_WAY)
  },

  /**
   * Register components to show.
   * @param {object} components - View components.
   */
  registerComponentsForShow (components) {
    ComponentsToShow = components.default || components
  },

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

  componentWillMount () {
    const s = this
    defaults(s, {
      stackerToShow: () => null
    })
  },

  // --------------------
  // Private
  // --------------------

  /**
   * Show a view.
   * @param {object} name - Name of view component to show.
   * @param {object} params - Component props.
   * @param {string} way - How to show.
   * @returns {Promise}
   * @private
   */
  _show (name, params, way) {
    assert.ok(ComponentsToShow, 'Show not initialized. You need to call .registerComponentsForShow() before using show mixin')

    const s = this

    let component = ComponentsToShow[ name ]
    if (!component) {
      throw new Error(`Unknown component: ${name}`)
    }
    let stacker = s.stackerToShow()
    if (stacker) {
      return stacker.pushView(component, params, way)
    } else {
      return s.pushViewToCurrentStack(component, params, way)
    }
  }
}

export default ApShowMixin
