/**
 * apeman react package for head component.
 * @class ApHead
 */

'use strict'

import React, { PropTypes as types } from 'react'
import stringcase from 'stringcase'

/** @lends ApHead */
const ApHead = React.createClass({
  // --------------------
  // Specs
  // --------------------

  propTypes: {
    /** CharSet */
    charSet: types.string,
    /** Document Title */
    title: types.string,
    /** Favicon */
    icon: types.string,
    /** Meta data */
    meta: types.oneOfType([
      types.arrayOf(types.object),
      types.object
    ]),
    /** Micro data settings */
    itemProps: types.oneOfType([
      types.arrayOf(types.object),
      types.object
    ]),
    /** CSS file urls */
    css: types.array,
    /** JS file urls */
    js: types.array,
    /** Version string */
    version: types.string,
    /** Query string key for version */
    versionKey: types.string,
    /** Global variables */
    globals: types.object,
    /** View port settings */
    viewPort: types.object,
    /** Base url */
    base: types.string,
    /** Target of base url. '_blank', '_parent', '_self', '_top' or frame name */
    baseTarget: types.string,
    /** Path of manifest.json */
    manifest: types.string,
    /** Theme color */
    color: types.string
  },

  mixins: [],

  statics: {
    renderBase (base, target) {
      if (!base) {
        return null
      }
      return (
        <base href={ base } target={ target }/>
      )
    },
    renderCharset (charSet) {
      if (!charSet) {
        return null
      }
      return (
        <meta className='ap-head-meta' charSet={ charSet }/>
      )
    },
    renderTitle (title) {
      if (!title) {
        return null
      }
      return (
        <title className='ap-head-title'>{ title }</title>
      )
    },
    renderIcon (url, query) {
      if (!url) {
        return null
      }
      return (
        <link rel='icon' href={ ApHead._addQuery(url, query) }/>
      )
    },
    renderMetaValues (values) {
      if (!values) {
        return null
      }
      return [].concat(values).map((values, i) =>
        Object.keys(values).map((name, j) =>
          <meta name={ name }
                content={ values[ name ] }
                key={ `meta-${i}-${j}` }/>
        )
      ).reduce((a, b) => [].concat(a, b), [])
    },
    renderItemProps (values) {
      if (!values) {
        return null
      }
      return [].concat(values).map((values, i) =>
        Object.keys(values).map((name, j) =>
          <meta itemProp={ name }
                content={ values[ name ] }
                key={ `item-prop${i}-${j}` }/>
        )
      ).reduce((a, b) => [].concat(a, b), [])
    },
    renderCss (urls, query) {
      if (!urls) {
        return null
      }
      return [].concat(urls).map((url, i) =>
        <link rel='stylesheet'
              type='text/css'
              key={ `css-${i}-${url}` }
              href={ ApHead._addQuery(url, query) }/>
      )
    },
    renderJs (urls, query) {
      if (!urls) {
        return null
      }
      return [].concat(urls).map((url, i) =>
        <script type='text/javascript'
                key={ `js-${i}-${url}` }
                src={ ApHead._addQuery(url, query)}></script>
      )
    },
    renderGlobals (values) {
      let _stringify = (data) => data ? JSON.stringify(data || {}) : 'null'

      return Object.keys(values || {}).map((key, i) =>
        <script type='text/javascript'
                key={ `global-${i}-${key}` }
                dangerouslySetInnerHTML={
                  { __html: `window.${key}=${_stringify(values[ key ])}` }
                }></script>
      )
    },
    renderViewPort (values) {
      let content = Object.keys(values || {}).map((key) =>
        [ stringcase.spinalcase(key), values[ key ] ].join('=')
      ).join(',')
      return <meta name='viewport' content={ content }/>
    },
    renderManifest (value) {
      if (!value) {
        return null
      }
      return <link rel='manifest' href={ value }/>
    },
    renderThemeColor (value) {
      if (!value) {
        return null
      }
      return <meta name='theme-color' content={ value }/>
    },
    _addQuery (url, query) {
      let joiner = /\?/.test(url) ? '&' : '?'
      return [ url, query ].join(joiner)
    }
  },

  getInitialState () {
    return {}
  },

  getDefaultProps () {
    return {
      charSet: 'utf-8',
      version: 'unknown',
      versionKey: 'v',
      viewPort: {
        width: 'device-width',
        initialScale: '1.0'
      },
      base: null,
      baseTarget: undefined
    }
  },

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

    let query = [ props.versionKey, props.version ].join('=')
    return (
      <head className='ap-head'>
        { ApHead.renderBase(props.base, props.baseTarget) }
        { ApHead.renderCharset(props.charSet) }
        { ApHead.renderTitle(props.title) }
        { ApHead.renderMetaValues(props.meta) }
        { ApHead.renderItemProps(props.itemProps) }
        { ApHead.renderIcon(props.icon, query) }
        { ApHead.renderGlobals(props.globals) }
        { ApHead.renderCss(props.css, query) }
        { ApHead.renderViewPort(props.viewPort) }
        { ApHead.renderManifest(props.manifest) }
        { ApHead.renderThemeColor(props.color) }
        { ApHead.renderJs(props.js, query) }
        { props.children }
      </head>
    )
  }
})

export default ApHead
