/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

const _css = `
.weex-indicator {
  position: absolute;
  z-index: 10;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  -moz-box-orient: horizontal;
  -moz-box-direction: normal;
  flex-direction: row;
  -webkit-box-orient: horizontal;
  margin: 0;
  padding: 0;
}

.weex-indicator-item {
  display: inline-block;
  position: relative;
  border-radius: 50%;
  width: 0.266667rem;
  height: 0.266667rem;
  background-color: #BBBBBB;
}
.weex-indicator-item + .weex-indicator-item {
  margin-left: 0.133333rem;
}

.weex-indicator-item-active {
  background-color: blue;
}
`

let extractComponentStyle, extend, extendKeys

function getIndicatorItemStyle (spec, isActive) {
  const style = {}
  style['background-color'] = spec[isActive ? 'itemSelectedColor' : 'itemColor']
  style['width'] = style['height'] = spec['itemSize']
  return style
}

function _render (context, h) {
  const children = []
  const mergedStyle = extractComponentStyle(context)
  const indicatorSpecStyle = extendKeys(
      {},
      mergedStyle,
      ['itemColor', 'itemSelectedColor', 'itemSize']
    )
  for (let i = 0; i < Number(context.count); ++i) {
    const classNames = ['weex-indicator-item weex-el']
    let isActive = false
    if (i === Number(context.active)) {
      classNames.push('weex-indicator-item-active')
      isActive = true
    }
    children.push(h('mark', {
      staticClass: classNames.join(' '),
      staticStyle: getIndicatorItemStyle(indicatorSpecStyle, isActive)
    }))
  }
  context.$nextTick(function () {
    _reLayout(this, _getVirtualRect(this, mergedStyle), _getLtbr(this, mergedStyle))
  })
  return h('nav', {
    attrs: { 'weex-type': 'indicator' },
    staticClass: 'weex-indicator weex-ct',
    staticStyle: mergedStyle
  }, children)
}

/**
 * get indicator's virtual rect (width, height), which is the .
 */
function _getVirtualRect (context, mergedStyle) {
  const ct = context._getParentRect()
  const rect = ['width', 'height'].reduce((pre, key) => {
    const msv = mergedStyle && mergedStyle[key]
    pre[key] = msv ? parseFloat(msv) : ct[key]
    return pre
  }, {})
  return rect
}

/**
 * get indicator's ltbr values (without units).
 */
function _getLtbr (context, mergedStyle) {
  return ['left', 'top', 'bottom', 'right'].reduce((pre, key) => {
    const msv = mergedStyle && mergedStyle[key]
    if (!msv && msv !== 0) { return pre }
    pre[key] = parseFloat(msv)
    return pre
  }, {})
}

/**
 * get indicator's rect (width, height).
 */
function _getIndicatorRect (el) {
  let width, height
  if (el.children.length === 1) {
    width = height = window.getComputedStyle(el.children[0])
  }
  else {
    const itemComputedStyle = window.getComputedStyle(el.children[1])
    const padding = parseFloat(itemComputedStyle.marginLeft)
    height = parseFloat(itemComputedStyle.height)
    width = el.children.length * (height + padding) - padding
  }
  return { width, height }
}

/**
 * calculate and reset indicator's width, height, and ltbr.
 * @param {object} virtualRect. width and height of indicator's virtual rect box.
 * @param {object} ltbr. the user specified left, top, bottom, right pixels (without units).
 */
function _reLayout (context, virtualRect, ltbr) {
  const el = context.$el
  const rect = _getIndicatorRect(el)
  const rectWithPx = Object.keys(rect).reduce((pre, key) => {
    pre[key] = rect[key] + 'px'
    return pre
  }, {})
  extend(el.style, rectWithPx)
  const axisMap = [{
    dir: ltbr.left || ltbr.left === 0
      ? 'left' : ltbr.right || ltbr.right === 0
      ? 'right' : 'left',
    scale: 'width'
  }, {
    dir: ltbr.top || ltbr.top === 0
      ? 'top' : ltbr.bottom || ltbr.bottom === 0
      ? 'bottom' : 'top',
    scale: 'height'
  }]
  Object.keys(axisMap).forEach(key => {
    const { dir, scale } = axisMap[key]
    el.style[dir] = (ltbr[dir] || 0) + virtualRect[scale] / 2 - rect[scale] / 2 + 'px'
  })
}

const indicator = {
  name: 'weex-indicator',
  methods: {
    show: function () {
      this.$el.style.visibility = 'visible'
    }
  },
  data () {
    return {
      count: 0,
      active: 0
    }
  },
  render (createElement) {
    const { count, active } = this.$vnode.data.attrs || {}
    this.count = count
    this.active = active
    if (!this.count) { return }
    return _render(this, createElement)
  },
  _css
}

export default {
  init (weex) {
    extractComponentStyle = weex.extractComponentStyle
    extend = weex.utils.extend
    extendKeys = weex.utils.extendKeys
    weex.registerComponent('indicator', indicator)
  }
}
