<template>
	<div class="v-input">
		<div class='prepend' v-if="$slots.prepend && type !== 'textarea'">
			<slot name='prepend' class='prepend'></slot>
		</div>
		<div :class='["v-input-box", { disabledBox: disabled }]' @mouseover='mouseover' @mouseout='mouseout'>
			<div class='prefix' ref='cPrefix' v-if='type !== "textarea"'>
				<i v-if='prefixIcon' :class='[prefixIcon]'></i>
				<slot name='prefix'></slot>
			</div>
			<input
			v-if='type !== "textarea"'
			ref='cInput'
			:type="myType"
			:value='modelValue'
			:disabled='disabled'
			:readonly='readonly'
			:maxlength='maxlength'
			:minlength='minlength'
			:min='min'
			:max='max'
			:name='name'
			:step='step'
			:class='["input", { disabled }, 
			{ paddingLeftSmall: prefixIcon },
			{ paddingLeft: $slots.prefix && prefixIcon },
			{ prependBorderRadius: $slots.prepend }, 
			{ appendBorderRadius: $slots.append },
			{ allBorderRadius: $slots.append && $slots.prepend }
			]'
			:placeholder="placeholder"
			@input.stop="handleInput"
			@change.stop='handleChange'
			@focus.stop="handleFocus"
			@blur.stop="handleBlur"
			@compositionstart="handleCompositionStart"
			@compositionend="handleCompositionEnd"
			/>	
			<textarea 
			ref='cTextarea'
			v-if='type === "textarea"' 
			:class='["textarea", { disabled }, { resize }]' 
			:disabled='disabled'
			:placeholder="placeholder"
			:cols="cols"
			:rows="rows"
			:name='name'
			:value='modelValue'
			:readonly='readonly'
			:maxlength="maxlength"
			@input.stop="handleTextareaInput"
			@change.stop='handleTextareaChange'
			@focus.stop="handleTextareaFocus"
			@blur.stop="handleTextareaBlur"
			@compositionstart="handleTextareaCompositionStart"
			@compositionend="handleTextareaCompositionEnd"
			/>
			<div class='suffix'>
				<div class='imgBox' v-if='type !== "textarea"'>
					<i v-show='(componentType === "select" || componentType === "cascader") && !disabled && !isClear && !remote && !loading' ref='cSelectArrow'
                    :class='["img", "iconfont icon-xiajiantou"]' style='color: #aaa'></i>
					<i :class='["img", "iconfont icon-xiajiantou", "arrow"]' v-if='disabled && componentType === "select"' ref='cSelectArrow'></i>
					<i :class='["img", "iconfont icon-guanbi"]' v-show='clearable && isClear' @click='handleClear'></i>
					<i v-if='loading' :class='["img", "loading", "iconfont icon-loading"]'></i>
					<i :class='["img", "iconfont icon-guanbi-yanjing"]' v-if='type === "password" && showPassword && showPsw'  @click='handleEyesClick(false)'></i>
					<i :class='["img", "iconfont icon-yanjing"]' v-if='type === "password" && showPassword && !showPsw' @click='handleEyesClick(true)'></i>
					<i v-if='suffixIcon' :class='[suffixIcon]'></i>
					<slot name='suffix'></slot>
				</div>
				<div class='showWordLimit' v-if='showWordLimit'>
					<span>{{ modelValue? modelValue.length : 0 }}</span>
					<span>/</span>
					<span>{{ maxlength }}</span>
				</div>
			</div>
		</div>
		<div class='append' v-if="$slots.append && type !== 'textarea'">
			<slot name='append'></slot>
		</div>
		<v-auto-complete 
		v-if='type === "text" && fetchSuggestions'
		:options='options'
		:showTime='showTime'
		@change='handleAutoCompleteChange'
		></v-auto-complete>
	</div>
</template>

<script>
import VairInput from '../../types/input';
import handleComposition from "./hooks/handleComposition";
import handleTextareaComposition from "./hooks/handleTextareaComposition";
import mouse from "./hooks/mouse";
import vAutoComplete from '../AutoComplete/AutoComplete';
import { ref, watch, nextTick } from "vue";

export default {
	name: "Input",
	components: {
		vAutoComplete
	},
	props: VairInput,
	setup(props, ctx) {
		let show = false;
		const flag = ref(false);
		const TextareaFlag = ref(false);
		const isClear = ref(false);
		const loading = ref(false);
		const cBox = ref(null);
		const cArrow = ref(null);
		const cInput = ref(null);
		const cPrefix = ref(null);
		const cTextarea = ref(null);
        const cSelectArrow = ref(null);
		const showPsw = ref(props.type === 'password');
		const myType = ref(props.type);
		const options = ref([]);
		const showTime = ref(false);

		watch(() => props.arrowShow, (newValue) => {
            cSelectArrow.value.style.transform = `rotate(${newValue? 180 : 0}deg)`;
		});

		watch(() => props.loading, (newValue) => {
            loading.value = newValue;
		});

		const handleAutoCompleteChange = (data) => {
			ctx.emit('update:modelValue', data.label);
		};

		const handleTextareaChange = (event) => {
			ctx.emit('change', event);
		};
		
		const handleTextareaInput = (event) => {
			if (props.autosize) textareaAutosize(event);
			if (TextareaFlag.value || props.modelValue === event.target.value) return;
			ctx.emit('update:modelValue', event.target.value);
			ctx.emit('input', event.target.value);
		};

		const handleTextareaFocus = (event) => {
			ctx.emit('focus', event);
			changeBorderColor(true);
		};

		const handleTextareaBlur = (event) => {
			changeBorderColor(false);
			ctx.emit('blur', event);
		};

		const textareaAutosize = (event) => {
			const scrollHeight = event.target.scrollHeight;
			const clientHeight = cTextarea.value.clientHeight;
			if (scrollHeight > clientHeight) {
				cTextarea.value.style.height = scrollHeight + 'px';
			}
		};

		// -----------------------------------------------------

		const handleChange = (event) => {
			ctx.emit("change", event.target.value); 
		};

		const handleInput = (event) => {
			if (flag.value || props.modelValue === event.target.value) return
			props.clearable && (isClear.value = event.target.value? true : false);
			ctx.emit('update:modelValue', event.target.value);
			ctx.emit('input', event.target.value);
			ctx.emit('selectInput', event.target.value);
			nextTick(() => {
				cInput.value.value = props.modelValue;
			});
			if (props.fetchSuggestions) {
				options.value = [];
				showTime.value = true;
				props.fetchSuggestions(event.target.value, cb);
			}
			if (props.remote) {
				if (event.target.value) {
					loading.value = true;
				}
				ctx.emit("remote-method", event.target.value || '');
				if (!event.target.value) {
					show = false;
					cArrow.value && (cArrow.value.style.display = 'none');
					cArrow.value && (cArrow.value.style.transform = 'rotate(0deg)');
					cBox.value && (cBox.value.style.transform = 'rotateX(90deg)');
				}
			}
		};

		const handleFocus = (event) => {
			ctx.emit('focus', event);
			changeBorderColor(true);
			if ((props.triggerOnFocus && props.fetchSuggestions) || (!props.triggerOnFocus && props.modelValue && props.fetchSuggestions)) {
				options.value = [];
				showTime.value = true;
				props.fetchSuggestions(event.target.value, cb);
			}
		};

		const handleBlur = (event) => {
			changeBorderColor(false);
			setTimeout(() => {
				props.fetchSuggestions && (showTime.value = false);
			}, 100);
			ctx.emit('blur', event);
		};

		const changeBorderColor = (bool) => {
			cInput.value && (cInput.value.style.borderColor = bool? '#409EFF' : '#ddd');
			cTextarea.value && (cTextarea.value.style.borderColor = bool? '#409EFF' : '#ddd');
		};

		const cb = (data) => {
			if (Array.isArray(data)) {
				options.value = data.length? data : null;
				data.length === 0 && (showTime.value = false);
			} else {
				showTime.value = false;
			}
		};

		const handleClear = () => {
			ctx.emit('clear');
			props.clearable && (isClear.value = false);
			ctx.emit('update:modelValue', '');
        };

		const handleEyesClick = (bool) => {
			showPsw.value = bool;
			myType.value = bool? 'password' : 'text';
			cInput.value.focus();
			const len = props.modelValue.length;
			cInput.value.style = 'color: transparent; text-shadow: 0 0 0 #000;';
			setTimeout(() => {
				cInput.value.style = 'text-shadow: 0 0 0 #000;';
				cInput.value.selectionStart = cInput.value.selectionEnd = len; 
			}, 0);
		};

		const focus = () => {
			cTextarea.value? cTextarea.value.focus() : cInput.value.focus();
		};

		const blur = () => {
			cTextarea.value? cTextarea.value.blur() : cInput.value.blur();
		};

		const select = () => {
			cTextarea.value? cTextarea.value.select() : cInput.value.select();
		};

		const { handleCompositionEnd, handleCompositionStart } = handleComposition(handleInput, flag);
		const { handleTextareaCompositionEnd, handleTextareaCompositionStart } = handleTextareaComposition(handleTextareaInput, TextareaFlag);
		const { mouseover, mouseout } = mouse(props, isClear);

		return {
			handleInput,
			handleChange,
			handleFocus,
			handleBlur,
			handleClear,
			handleEyesClick,
			handleTextareaChange,
			handleTextareaInput,
			handleTextareaFocus,
			handleTextareaBlur,
			show,
			isClear,
			loading,
			cBox,
			cArrow,
			cInput,
			cPrefix,
			cTextarea,
			cSelectArrow,
			flag,
			TextareaFlag,
			handleCompositionEnd,
			handleCompositionStart,
			handleTextareaCompositionEnd,
			handleTextareaCompositionStart,
			handleAutoCompleteChange,
			mouseover,
			mouseout,
			showPsw,
			myType,
			options,
			showTime,
			focus,
			blur,
			select
		};
	}
};
</script>

<style lang='less'>
@import url('./index.less');
</style>