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

import React, { Component, PropTypes as types } from 'react'
import defineDebug from 'debug'
import {
  ApView, ApViewHeader, ApViewBody
} from 'apeman-react-basic'
import { PostForm } from '../../fragments'
import {
  asConnected,
  asView,
  asLocaled,
  asServed,
  forSpin,
  forOne,
  forEntry,
  forEvent,
  ofThread,
  combine
} from '../../wrappers'
import { imageError } from 'ore-fol-errors'

import { IconClasses, ViewEvents } from 'ore-fol-enums'
import { PostTypeCodes } from 'ore-fol-codes'

const { POST_ICON } = IconClasses
const { POST_CREATE_EVENT } = ViewEvents
const { UPLOAD_POST, LINK_POST } = PostTypeCodes

const debug = defineDebug('project:view:post-create')

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

  static get defaultProps () {
    return {}
  }

  render () {
    const s = this
    const {
      props,
      labels,
      postTypes,
      errors,
      placeholders,
      l
    } = s
    return (
      <ApView id='post-create-view'
              className='view'
              spinning={ props.spinning }
              way={ props.way }
      >
        <ApViewHeader onLeftTap={ s.handlePop }
                      leftText={ null }
                      leftIcon={ props.popIcon }
                      titleText={ l('titles.NEW_POST') }
                      titleIcon={ POST_ICON }
                      onRightTap={ null }
                      rightIcon={ null }
                      rightText={ null }
        />

        <ApViewBody>
          <PostForm labels={ labels }
                    placeholders={ placeholders }
                    types={ postTypes }
                    values={ props.entryValues }
                    errors={ errors }
                    onSubmit={ s.handleSubmit }
                    onUpdate={ s.handleEntryUpdate }
          />
        </ApViewBody>
      </ApView>
    )
  }

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

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

  componentDidMount () {
    debug('didMount')
    const s = this

    s.handleEntryUpdate({
      type: UPLOAD_POST
    })
  }

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

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

  handleSubmit () {
    const s = this
    const { props, l } = s
    const { infoToast } = s.service('toastService')
    const { isValidImage } = s.service('imageService')
    let { threadId, entryValues } = props
    let { type, text } = entryValues
    let image = s.imageWithEntryValues(entryValues)

    return s.applySpinWhile(() =>
      s.normalizeImage(image)
        .catch(s.handleEntryErrorCatch)
        .then((image) =>
          isValidImage(image).then((valid) => {
            if (!valid) {
              let error = imageError.invalid({
                messages: {
                  image: 'errors.IMAGE_INVALID'
                }
              })
              return s.handleEntryErrorCatch(error)
            }
            const { use } = s.service('apiService')
            return use('postApi')
              .then((postApi) =>
                postApi.create({
                  type,
                  threadId,
                  text,
                  image,
                  additionalInfo: {}
                })
              )
              .then((created) => {
                infoToast(l('toasts.POST_SUCCESS'))
                s.fireEvent(POST_CREATE_EVENT, { created })
                return s.handlePop()
                  .then(s.handleEntryClear)
              })
              .catch(s.handleEntryErrorCatch)
          })
        )
    )
  }

  // --------------------
  // Dynamic Variables
  // --------------------
  get labels () {
    const s = this
    const { l } = s
    return {
      type: l('labels.POST_TYPE'),
      image: l('labels.POST_IMAGE'),
      text: l('labels.POST_TEXT'),
      submit: l('buttons.DO_POST')
    }
  }

  get postTypes () {
    const s = this
    const { l } = s
    return {
      [UPLOAD_POST]: l('labels.POST_TYPE_UPLOAD'),
      [LINK_POST]: l('labels.POST_TYPE_LINK')
    }
  }

  get placeholders () {
    const s = this
    const { l } = s
    return {
      text: l('placeholders.POST_TEXT')
    }
  }

  get errors () {
    const s = this
    const { localizeErrors } = s.service('localeService')
    const { props, labels } = s
    return localizeErrors(props.entryErrors, { labels })
  }

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

  imageWithEntryValues (entryValues) {
    let { type, uploadedImage, linkedImage } = entryValues
    switch (type) {
      case UPLOAD_POST:
        return uploadedImage
      case LINK_POST:
        return linkedImage
      default:
        return null
    }
  }

  normalizeImage (image) {
    const s = this
    const { uploadImage } = s.service('imageService')
    if (!image) {
      return Promise.resolve(null)
    }
    if (typeof image === 'string') {
      return Promise.resolve(image)
    }
    let { url, file } = image
    let { type, size } = file
    const { use } = s.service('apiService')
    return use('storageApi').then((storageApi) =>
      storageApi.policy({ type, size })
        .then(({ url: uploadUrl, fields, opts }) =>
          uploadImage(uploadUrl, file, fields, opts)
            .then((uploadedUrl) => uploadedUrl || url)
        )
    )
  }

}

export default combine(
  asServed(),
  forSpin(),
  forEntry(),
  forOne(),
  forEvent(),
  ofThread(),
  asLocaled(),
  asView(),
  asConnected()
)(PostCreateView)

