<template>
	<view class="l-input" 
		:style="[styles, lStyle]"
		ref="rootRef"
		:class="[
			'l-input--' + layout,
			classic ? 'l-input--classic-' + status : '',
			{'l-input--classic': classic},
			{'l-input--classic-disabled':  classic && disabled},
			{'l-input--classic-focused':  classic && !disabled && innerFocused},
			{'l-input--border': bordered && !classic}]">
		<view class="l-input__wrap--prefix" v-if="label != null || $slots['label'] != null || $slots['prefix-icon'] != null || prefixIcon != null">
			<!-- #ifndef UNI-APP-X && APP -->
			<view class="l-input__icon--prefix" v-if="$slots['prefix-icon'] != null || prefixIcon != null">
				<slot name="prefix-icon">
					<l-icon :name="prefixIcon" v-if="prefixIcon != null" :color="prefixIconColor" :size="prefixIconSize"></l-icon>
				</slot>
			</view>
			<!-- #endif -->
			<!-- #ifdef UNI-APP-X && APP -->
			<slot name="prefix-icon">
				<l-icon class="l-input__icon--prefix" :name="prefixIcon" v-if="prefixIcon != null" :color="prefixIconColor" :size="prefixIconSize"></l-icon>
			</slot>
			<!-- #endif -->
			<text class="l-input__label" 
				:style="[labelStyle]"
				:class="{ 'l-input__label--gap': prefixIcon != null || $slots['prefix-icon'] != null}"
				v-if="label != null || $slots['label'] != null ">
				<slot name="label">{{label}}</slot>
			</text>
		</view>
		<view class="l-input__wrap">
			<view class="l-input__content">
				<input
					class="l-input__control"
					:style="[inputStyle]"
					:class="[
						'l-input--' + align,
						{
							'l-input__control--disabled': isDisabled,
							'l-input__control--read-only': isReadonly,
						}
					]"
					:maxlength="maxlength"
					:disabled="isDisabled || isReadonly"
					:placeholder="placeholder"
					:placeholder-style="innerPlaceholderStyle"
					:placeholder-class="innerPlaceholderStyle == '' ?  (isDisabled || isReadonly ? 'l-input__placeholder--disabled' : 'l-input__placeholder') : ''"
					:value="innerValue"
					:type="type == 'password' ? 'text' : type"
					:password="type == 'password'"
					:focus="focus"
					:confirm-type="confirmType"
					:confirm-hold="confirmHold"
					:cursor="cursor"
					:cursor-color="cursorColor"
					:cursor-spacing="cursorSpacing"
					:adjust-position="adjustPosition"
					:auto-focus="autoFocus"
					:always-embed="alwaysEmbed"
					:selection-start="selectionStart"
					:selection-end="selectionEnd"
					:hold-keyboard="holdKeyboard"
					:safe-password-cert-path="safePasswordCertPath"
					:safe-password-length="safePasswordLength"
					:safe-password-time-stamp="safePasswordTimeStamp"
					:safe-password-nonce="safePasswordNonce"
					:safe-password-salt="safePasswordSalt"
					:safe-password-custom-hash="safePasswordCustomHash"
					:aria-label="label"
					:aria-roledescription="label"
					@input="onInput"
					@focus="onFocus"
					@blur="onBlur"
					@confirm="onConfirm"
					@keyboardheightchange="onKeyboardHeightChange"
					@nicknamereview="onNickNameReview" />
				<!-- #ifndef UNI-APP-X && APP -->	
				<view class="l-input__wrap--clearable-icon" v-if="clearable" @click="clearInput" v-show="showClearIcon">
					<l-icon name="close-circle-filled" :size="clearIconSize"></l-icon>
				</view>
				<!-- #endif -->
				<!-- #ifdef UNI-APP-X && APP -->
				<view v-if="clearable" v-show="showClearIcon" @click="clearInput">
					<l-icon class="l-input__wrap--clearable-icon" name="close-circle-filled" :size="clearIconSize" ></l-icon>
				</view>
				<!-- <l-icon class="l-input__wrap--clearable-icon" name="close-circle-filled" size="44rpx" @click="clearInput"  v-if="clearable" v-show="showClearIcon"></l-icon> -->
				<!-- #endif -->
				<view class="l-input__wrap--suffix" @click="onSuffixClick" v-if="suffix != null || $slots['suffix'] != null">
					<slot name="suffix">
						<text class="l-input__wrap--suffix-text">{{suffix}}</text>
					</slot>
				</view>
				<!-- #ifndef UNI-APP-X && APP -->
				<view class="l-input__wrap--suffix-icon" v-if="suffixIcon != null || $slots['suffix-icon'] != null">
					<slot name="suffix-icon">
						<l-icon :name="suffixIcon" @click="onSuffixIconClick" :size="suffixIconSize" :color="suffixIconColor" v-if="suffixIcon != null"></l-icon>
					</slot>
				</view>
				<!-- #endif -->
				<!-- #ifdef UNI-APP-X && APP -->
				<slot name="suffix-icon">
					<l-icon class="l-input__wrap--suffix-icon" :name="suffixIcon" :size="suffixIconSize" :color="suffixIconColor" v-if="suffixIcon != null"></l-icon>
				</slot>
				<!-- #endif -->
			</view>
			<text class="l-input__tips" :style="[tipsStyle]" :class="['l-input__tips--' + status]" v-if="tips != null && tips!.length > 0 || $slots['tips'] != null">
				<slot name="tips">{{tips}}</slot>
			</text>
		</view>
		<!-- #ifdef APP -->
		<view class="l-input__border" v-if="bordered && !classic"></view>
		<!-- #endif -->
	</view>
</template>
<script lang="uts" setup>
	/**
	 * Input 输入框组件
	 * @description 增强版输入组件，支持安全加密输入、多类型验证和智能交互
	 * <br> 插件类型：LInputComponentPublicInstance 
	 * @tutorial https://ext.dcloud.net.cn/plugin?name=lime-input
	 * 
	 * @property {boolean} adjustPosition 键盘弹起时页面自动上推
	 * @property {'left'|'center'|'right'} align 文本对齐方式
	 * @value left   
	 * @value center  
	 * @value right    
	 * @property {boolean} alwaysEmbed iOS强制同层渲染（仅iOS生效）
	 * @property {boolean} autoFocus 自动聚焦（即将废弃，建议使用focus）
	 * @property {boolean} bordered 边框模式
	 * @property {'always'|'focus'} clearTrigger 清空按钮显示规则
	 * @value always
	 * @value focus     
	 * @property {boolean} clearable 显示清空按钮
	 * @property {boolean} confirmHold 点击确认按钮保持键盘
	 * @property {'send'|'search'|'next'|'go'|'done'} confirmType 确认按钮类型
	 * @value send    显示"发送"
	 * @value search  显示"搜索"
	 * @value next    显示"下一个"
	 * @value go      显示"前往"
	 * @value done    显示"完成"
	 * @property {number} cursor 初始光标位置（需配合selectionStart/End）
	 * @property {string} cursorColor 光标颜色
	 * @property {number} cursorSpacing 光标与键盘间距（单位px）
	 * @property {boolean} disabled 禁用状态
	 * @property {boolean} focus 强制聚焦
	 * @property {boolean} focused 是否显示获焦样式，用于结合自定义键盘使用时显示高亮效果
	 * @property {boolean} classic 是否使用经典边框样式
	 * @property {boolean} holdKeyboard 聚焦时保持键盘不收起
	 * @property {string} label 左侧标签文本
	 * @property {'horizontal'|'vertical'} layout 标签布局
	 * @value horizontal 
	 * @value vertical
	 * @property {number} maxcharacter 最大字符长度（中文算2字符）
	 * @property {number} maxlength 最大输入长度（中文算1字符）
	 * @property {string} placeholder 占位文本
	 * @property {string} placeholderStyle 占位符内联样式
	 * @property {string} placeholderClass 占位符CSS类名
	 * @property {boolean} readonly 只读模式
	 * @property {string} safePasswordCertPath 安全证书路径（仅App）
	 * @property {string} safePasswordCustomHash 自定义哈希算法（仅App）
	 * @property {number} safePasswordLength 安全密码长度（仅App）
	 * @property {string} safePasswordNonce 加密随机数（仅App）
	 * @property {string} safePasswordSalt 加密盐值（仅App）
	 * @property {number} safePasswordTimeStamp 加密时间戳（仅App）
	 * @property {'default'|'success'|'warning'|'error'} status 校验状态
	 * @value default
	 * @value success
	 * @value warning
	 * @value error
	 * @property {string} prefixIcon 前缀图标（支持图片路径/字体图标）
	 * @property {string} prefixIconSize 前缀图标尺寸（带单位）
	 * @property {string} prefixIconColor 前缀图标颜色
	 * @property {string} suffix 后缀文本内容
	 * @property {string} suffixIcon 后缀图标（支持图片路径/字体图标）
	 * @property {string} suffixIconSize 后缀图标尺寸（带单位）
	 * @property {string} clearIconSize 删除图标尺寸
	 * @property {string} suffixIconColor 后缀图标颜色
	 * @property {string} tips 底部提示文本（根据status变色）
	 * @property {'text'|'number'|'idcard'|'digit'|'safe-password'|'password'|'nickname'} type 输入类型
	 * @value text           普通文本
	 * @value number         数字键盘（非强制）
	 * @value idcard         身份证键盘（带X）
	 * @value digit          强制数字键盘
	 * @value safe-password  安全加密输入
	 * @value password       密码输入
	 * @value nickname       昵称输入（过滤特殊字符）
	 * @property {string} value 输入值（支持v-model）
	 * @property {string} modelValue 输入值（支持v-model）
	 * @property {string} lStyle 根节点自定义样式
	 * @property {string} labelStyle 标签样式
	 * @property {string} tipsStyle 提示文本样式
	 * @property {string} inputStyle 输入域样式
	 * @property {string} borderColor 边框颜色（bordered时生效）
	 * @property {string} focusedBorderColor 聚焦时边框颜色（bordered时生效）
	 * @event {Function} change 输入时触发
	 * @event {Function} focus 聚焦时触发
	 * @event {Function} blur 失焦时触发
	 * @event {Function} confirm 点击完成按钮触发
	 * @event {Function} clear 点击清空按钮触发
	 * @event {Function} click-icon 点击触发
	 */
	import { InputProps } from './type';
	import { characterLimit, type CharacterLengthResult } from '@/uni_modules/lime-shared/characterLimit';
	import { objToCss } from '@/uni_modules/lime-shared/objToCss';
	// #ifdef APP
	const themeVars = inject('limeConfigProviderThemeVars', computed(()=> ({})))
	// import { useDrawBorder, DrawBorderOptions } from '@/uni_modules/lime-style/hairline'
	// #endif
	
	defineOptions({
		behaviors: ['wx://form-field']
	})
	const emit = defineEmits(['change', 'update:modelValue' ,'focus', 'blur', 'confirm', 'clear', 'keyboardheightchange', 'nicknamereview' ,'click-icon'])
	const props = withDefaults(defineProps<InputProps>(),{
		adjustPosition: true,
		align: 'left',
		alwaysEmbed: false,
		autoFocus: false,
		bordered: true,
		clearTrigger: 'focus',
		clearable: false,
		confirmHold: false,
		confirmType: 'done',
		cursor: 0,
		cursorColor: '',
		cursorSpacing: 0,
		disabled: false,
		focus: false,
		holdKeyboard: false,
		layout: 'horizontal',
		maxlength: -1,
		placeholder: '',
		placeholderStyle: '',
		readonly: false,
		safePasswordCertPath: '',
		safePasswordCustomHash: '',
		// safePasswordLength: 0,
		safePasswordNonce: '',
		safePasswordSalt: '',
		// safePasswordTimeStamp: 0,
		selectionEnd: -1,
		selectionStart: -1,
		status: 'default',
		// suffixIcon: '',
		type: 'text',
		classic: false,
		focused: false
	})
	
	const formItemBlur = inject<(() => void)|null>('formItemBlur', null);
	const formDisabled = inject<Ref<boolean|null>|null>('formDisabled', null)
	const formReadonly = inject<Ref<boolean|null>|null>('formReadonly', null)
	
	const calculateValue = (value: string|number):CharacterLengthResult => {
		const { maxlength, maxcharacter } = props;
		if(maxcharacter != null && maxcharacter > 0) {
			return characterLimit('maxcharacter', `${value}`, maxcharacter)
		} 
		return {
			characters: `${value}`,
			length: `${value}`.length
		} as CharacterLengthResult
	}
	let _innerValue = ref<string|number>('');
	const innerFocused = ref(props.focus || props.focused);
	const innerValue = computed({
		set(value: string|number) {
			_innerValue.value = value;
			emit('change', value)
			emit('update:modelValue', value)
		},
		get():string|number {
			const _value = props.value ?? props.modelValue
			if(_innerValue.value != _value && props.type != 'number') {
				const { characters } = calculateValue(`${_value ?? _innerValue.value}`);
				return characters
			}
			return _value ?? _innerValue.value
		}
	} as WritableComputedOptions<string>)
	
	const isDisabled = computed(():boolean => props.disabled || (formDisabled?.value ?? false))
	const isReadonly = computed(():boolean => props.readonly || (formReadonly?.value ?? false))
	const innerPlaceholderStyle = computed(():string=>{
		let style = ''
		// #ifdef APP
		// 直接使用固定值，不依赖 themeVars
		// 注意：Android 原生 input 的 placeholder-style 不支持 rpx，必须使用 px
		style += `color: ${themeVars.value['inputPlaceholderTextColor'] ?? '#999999'};`
		// #endif
		
		return style + (typeof props.placeholderStyle == 'string' ? `${props.placeholderStyle}` : objToCss(props.placeholderStyle as UTSJSONObject))
	})
	const styles = computed(():Map<string, any>=>{
		const style = new Map<string, any>()
		// #ifndef UNI-APP-X && APP
		if(props.borderColor != null) {
			style.set('--l-input-border-color', props.borderColor)
		}
		if(props.focusedBorderColor != null) {
			style.set('--l-input-focused-border-color', props.focusedBorderColor)
		}
		// #endif
		return style
	})
	const showClearIcon = computed(():boolean => {
		const { clearTrigger, disabled, readonly } = props;
		if(disabled || readonly) {
			return false
		}
		return `${innerValue.value}`.length > 0 || clearTrigger == 'always' 
	})
	const onInput = (e: UniInputEvent) => {
		const { value, cursor, keyCode } = e.detail;
		if(props.type == 'number') {
			const _v:number = parseFloat(`${value}`)
			// @ts-ignore
			innerValue.value = isNaN(_v) ? '' : _v;
		} else {
			const { characters } = calculateValue(value);
			innerValue.value = characters;
		}
	}
	const onFocus = (event: UniInputFocusEvent) => {
		innerFocused.value = true;
		emit('focus', event)
	}
	const onBlur = (event: UniInputBlurEvent) => {
		innerFocused.value = false;
		emit('blur', event)
		formItemBlur?.()
	}
	const onConfirm = (event: UniInputConfirmEvent) => {
		emit('confirm', event)
	}
	const onKeyboardHeightChange = (event: UniInputKeyboardHeightChangeEvent) => {
		emit('keyboardheightchange', event)
	}
	const onNickNameReview = (event: any) => {
		emit('nicknamereview', event)
	}
	const clearInput = () => {
		innerValue.value = '';
		emit('clear')
	}
	const onSuffixClick = () => {
		emit('click-icon', { trigger: 'suffix' })
	}
	const onSuffixIconClick = () => {
		emit('click-icon', { trigger: 'suffix-icon' })
	}
	watchEffect(()=> {
		innerFocused.value = props.focus || props.focused;
	})
	// #ifdef APP-ANDROID || APP-IOS
	const rootRef = ref<UniElement|null>(null);

	onMounted(()=>{
		watchEffect(()=>{
			if(!props.classic) {
				if(props.borderColor != null && !innerFocused.value) {
					rootRef.value?.style.setProperty('border-color', props.borderColor)
				}
				if(props.focusedBorderColor != null && innerFocused.value) {
					rootRef.value?.style.setProperty('border-color', props.focusedBorderColor)
				}
			}
		})
	})
	// #endif
</script>
<style lang="scss">
	@import './index';
</style>
