<script>
import omit from 'omit.js'

import inputProps from './inputProps'

import calculateNodeHeight from './calculateNodeHeight'

function onNextFrame (cb) {
  if (window.requestAnimationFrame) {
    return window.requestAnimationFrame(cb)
  }
  return window.setTimeout(cb, 1)
}

function clearNextFrameAction (nextFrameId) {
  if (window.cancelAnimationFrame) {
    window.cancelAnimationFrame(nextFrameId)
  } else {
    window.clearTimeout(nextFrameId)
  }
}
function fixControlledValue (value) {
  if (typeof value === 'undefined' || value === null) {
    return ''
  }
  return value
}

export default {
  name: 'TextArea',
  props: {
    ...inputProps,
    autosize: [Object, Boolean],
  },
  model: {
    prop: 'value',
    event: 'change.value',
  },
  data () {
    const { value, defaultValue } = this.$props
    return {
      stateValue: fixControlledValue(value === undefined ? defaultValue : value),
      nextFrameActionId: undefined,
      textareaStyles: {},
    }
  },
  computed: {
  },
  watch: {
    value (val) {
      this.stateValue = fixControlledValue(val)
      if (this.nextFrameActionId) {
        clearNextFrameAction(this.nextFrameActionId)
      }
      this.nextFrameActionId = onNextFrame(this.resizeTextarea)
    },
  },
  mounted () {
    this.resizeTextarea()
  },
  methods: {
    handleKeyDown (e) {
      if (e.keyCode === 13) {
        this.$emit('pressEnter', e)
      }
      this.$emit('keydown', e)
    },
    resizeTextarea () {
      const { autosize } = this.$props
      if (!autosize || !this.$refs.textArea) {
        return
      }
      const minRows = autosize ? autosize.minRows : null
      const maxRows = autosize ? autosize.maxRows : null
      const textareaStyles = calculateNodeHeight(this.$refs.textArea, false, minRows, maxRows)
      this.textareaStyles = textareaStyles
    },

    getTextAreaClassName () {
      const { prefixCls, disabled } = this.$props
      return {
        [prefixCls]: true,
        [`${prefixCls}-disabled`]: disabled,
      }
    },

    handleTextareaChange (e) {
      const { value } = this.$props
      if (value === undefined) {
        this.stateValue = e.target.value
        this.$nextTick(() => {
          this.resizeTextarea()
        })
      } else {
        this.$forceUpdate()
        this.$emit('change.value', e.target.value)
        this.$emit('change', e)
      }
    },

    focus () {
      this.$refs.textArea.focus()
    },

    blur () {
      this.$refs.textArea.blur()
    },

  },
  render () {
    const { stateValue, getTextAreaClassName, handleKeyDown, handleTextareaChange, textareaStyles } = this
    const otherProps = omit(this.$props, [
      'prefixCls',
      'autosize',
      'type',
    ])
    const attrs = {
      attrs: { ...otherProps, ...this.$attrs },
    }
    return (
      <textarea
        {...attrs}
        value={stateValue}
        class={getTextAreaClassName()}
        style={textareaStyles}
        onKeydown={handleKeyDown}
        onInput={handleTextareaChange}
        ref='textArea'
      />
    )
  },
}
</script>