<template>
    <div :class="wrapClasses">
        <template v-if="type !== 'textarea'">
            <input 
                ref="input"
                :class="prefixCls"
                :type="type"
                :value="currentValue"
                :placeholder="placeholder"
                :maxlength="maxlength"
                :autocomplete="autocomplete"
                :autofocus="autofocus"
                :disabled="disabled"
                :readonly="readonly"
                :style="paddingStyles"
                @keyup.enter="handleDispatch($event, 'enter')"
                @keyup="handleDispatch($event, 'keyup')"
                @keypress="handleDispatch($event, 'keypress')"
                @keydown="handleDispatch($event, 'keydown')"
                @focus="handleDispatch($event, 'focus')"
                @blur="handleDispatch($event, 'blur')"
                @compositionstart="handleComposition"
                @compositionupdate="handleComposition"
                @compositionend="handleComposition"
                @input="handleInput"/>
        </template>
        <textarea 
            v-else
            ref="textarea"
            :class="prefixCls"
            :type="type"
            :value="currentValue"
            :placeholder="placeholder"
            :rows="rows"
            :style="[textareaStyles, paddingStyles]"
            :maxlength="maxlength"
            :autocomplete="autocomplete"
            :autofocus="autofocus"
            :disabled="disabled"
            :readonly="readonly"
            @keyup.enter="handleDispatch($event, 'enter')"
            @keyup="handleDispatch($event, 'keyup')"
            @keypress="handleDispatch($event, 'keypress')"
            @keydown="handleDispatch($event, 'keydown')"
            @focus="handleDispatch($event, 'focus')"
            @blur="handleDispatch($event, 'blur')"
            @compositionstart="handleComposition"
            @compositionupdate="handleComposition"
            @compositionend="handleComposition"
            @input="handleInput"/>
            <Icon 
                v-if="currentValue && clearable && !readonly && !disabled"
                type="close-circle-fill" 
                size="14px" 
                :class="`${prefixCls}-clearable`"
                :style="clearIconStyles"
                @click.prevent.native="handleClear"/>
            <span 
                ref="prefix"
                v-if="showPrefix"
                :class="`${prefixCls}-prefix`">
                <slot name="prefix"></slot>
            </span>
            <span 
                ref="suffix" 
                v-if="showSuffix"
                :class="`${prefixCls}-suffix`">
                <slot name="suffix"></slot>
            </span>
            <div :class="`${prefixCls}-count`"></div>    
    </div>
</template>
<script>
    /**
     * @displayName YYInput
     */
    import { oneOf, findComponentUpward } from '../../../utils/assist'
    import calcTextareaHeight from '../../../utils/calcTextareaHeight'
    import Emitter from '../../../mixins/emitter'
    import Icon from '../icon/'

    const prefixCls = "yy-input"
    export default {
        name: 'YYInput',
        mixins: [Emitter],
        components: {
            Icon
        },
        props: {
            /**
             * 输入框类型
             * @values text, textarea, password, url, email, date
             */
            type: {
                validator (value) {
                    return oneOf(value, ['text', 'textarea', 'password', 'url', 'email', 'date']);
                },
                default: 'text'
            },
            size: {
                validator(value) {
                    return oneOf(value, ['small', 'large'])
                }
            },
            value: {
                type: [String, Number],
                default: ''
            },
            placeholder: {
                type: String,
                default: ''
            },
            maxlength: {
                type: Number
            },
            disabled: {
                type: Boolean,
                default: false
            },
            error: {
                type: Boolean,
                default: false
            },
            readonly: {
                type: Boolean,
                default: false
            },
            autofocus: {
                type: Boolean,
                default: false
            },
            autocomplete: {
                validator (value) {
                    return oneOf(value, ['on', 'off']);
                },
                default: 'off'
            },
            clearable: {
                type: Boolean,
                default: true
            },
            number: {
                type: Boolean,
                default: false
            },
            rows: {
                type: Number,
                default: 4
            },
            autosize: {
                type: [Boolean, Object],
                default: false
            }
        },
        data() {
            return {
                prefixCls: prefixCls,
                isOnComposition: false,
                currentValue: this.value,
                calcTextareaHeight: {},
                showPrefix: false,
                showSuffix: false,
                suffixWidth: 0,
                prefixWidth: 0
            }
        },
        computed: {
            wrapClasses () {
                return [
                    `${prefixCls}-wrapper`,
                    {
                        [`${prefixCls}-wrapper-${this.size}`]: !!this.size,
                        [`${prefixCls}-wrapper-${this.type}`]: !!this.type,
                        [`${prefixCls}-wrapper-error`]: this.error,
                        [`${prefixCls}-wrapper-suffix`]: this.showSuffix,
                        [`${prefixCls}-wrapper-prefix`]: this.showPrefix,
                    }
                ]
            },
            textareaStyles() {
                return {
                    ...this.calcTextareaHeight
                }
            },
            paddingStyles() {
                let paddingLeft = this.prefixWidth || 10
                let paddingRight = 10 + this.suffixWidth + (this.clearable && (this.suffixWidth && 2 || 12))
                // if(this.suffixWidth && this.clearable) {
                //     paddingRight += 2
                // }
                // if(!this.suffixWidth && this.clearable) {
                //     paddingRight += 12
                // }
                return {
                    'padding-left': paddingLeft + 'px',
                    'padding-right': paddingRight + 'px'
                }
            },
            clearIconStyles() {
                const right = this.suffixWidth || 10
                return {
                    'right': right + 'px',
                }
            }
        },
        watch: {
            value (val) {
                this.setCurrentValue(val)
            }
        },
        methods: {
            resizeTextarea () {
                const autosize = this.autosize;
                if (!autosize || this.type !== 'textarea') {
                    return false;
                }

                const minRows = autosize.minRows || this.rows
                const maxRows = autosize.maxRows || this.rows * 4

                this.calcTextareaHeight = calcTextareaHeight(this.$refs.textarea, minRows, maxRows)
            },
            setCurrentValue (value) {
                if (value === this.currentValue) return
               
                this.currentValue = value
                this.$nextTick(() => {
                    this.resizeTextarea()
                })
                this.dispatch('YYFormItem', 'on-form-change', value)
            },
            handleClear() {
                this.setCurrentValue('')
                this.$emit('input', this.currentValue)
                this.$emit('on-clear', this.currentValue)
                if(this.type === 'textarea') {
                    this.$refs.textarea.focus()
                } else {
                    this.$refs.input.focus()
                }
                this.dispatch('YYFormItem', 'on-form-blur', this.currentValue);
            },
            handleDispatch(event, type) { // 分发父级method
                this.$emit(`on-${type}`, event)
                if(type === 'blur') {
                    this.dispatch('YYFormItem', 'on-form-blur', this.currentValue);
                }
            },
            handleComposition() {
                if (event.type === 'compositionstart') {
                    this.isOnComposition = true
                }
                if (event.type === 'compositionend') {
                    this.isOnComposition = false
                    this.handleInput(event)
                }
            },
            handleInput() {
                if (this.isOnComposition) return

                let value = event.target.value
                if (this.number && value !== '') value = Number.isNaN(Number(value)) ? value : Number(value)
                this.$emit('input', value)
                this.setCurrentValue(value)
                this.$emit('on-change', event)
            },
            focus() {
                if(this.type === 'textarea') {
                    this.$refs.textarea.focus()
                } else {
                    this.$refs.input.focus()
                }
            },
            blur() {
                if(this.type === 'textarea') {
                    this.$refs.textarea.blur()
                } else {
                    this.$refs.input.blur()
                }
            }
        },
        mounted() {
            this.resizeTextarea()
            this.showPrefix = !!this.$slots.prefix
            this.showSuffix = !!this.$slots.suffix
            this.$nextTick(()=>{
                setTimeout(()=>{
                    this.suffixWidth += this.$refs.suffix && this.$refs.suffix.offsetWidth || 0
                    this.prefixWidth += this.$refs.prefix && this.$refs.prefix.offsetWidth || 0
                }, 500)
            })
        }
    }
</script>
