<template>
	<view class="l-radio" :class="classes" :style="[styles]" @click="onClick">
		<slot name="radio" :checked="radioChecked" :disabled="isDisabled">
			<slot name="icon" :checked="radioChecked" :disabled="isDisabled">
				<view class="l-radio__icon" ref="iconRef" :class="iconClasses" :style="[iconStyle]"></view>
			</slot>
			<text class="l-radio__label" :class="labelClass" v-if="label != null || $slots['default'] != null">
				<slot>{{label}}</slot>
			</text>
		</slot>
	</view>
</template>
<script lang="uts" setup>
	import { RadioProps } from './type';
	// #ifndef APP
	import type { ComputedRef } from 'vue';
	type ComputedRefImpl<T> = ComputedRef<T>
	// #endif
	const emit = defineEmits(['change', 'update:checked'])
	const props = withDefaults(defineProps<RadioProps>(), {
		allowUncheck: false,
		checked: false,
		disabled: false,
		icon: 'circle',
		size: 'medium'
	})
	
	defineSlots<{
	    radio(props : { checked : boolean,  disabled: boolean}) : any,
	    icon(props : { checked : boolean,  disabled: boolean}) : any,
	    default(props : { checked : boolean,  disabled: boolean}) : any,
	  }>()
	
	const name = 'l-radio'
	const radioGroupProps = inject<LRadioGroupComponentPublicInstance|null>('limeRadioGroupProps', null);
	const radioGroupValue = inject<ComputedRefImpl<any>|null>('limeRadioGroupValue', null);
	const radioGroupChange = inject<((value: any|null) => void)|null>('limeRadioGroupChange', null);
	const modelValue = defineModel({type: Boolean, default: false});
	const innerChecked = computed({
		set(value: boolean){
			modelValue.value = value;
			emit('change', value)
		},
		get(): boolean{
			return props.checked || modelValue.value
		},
	} as WritableComputedOptions<boolean>)
	
	const isDisabled = computed(():boolean => (props.disabled || (radioGroupProps?.disabled ?? false)))
	const groupDisabled = computed(():boolean|null => radioGroupProps?.disabled);
	const radioChecked = computed(():boolean => innerChecked.value || (props.name != null && props.name == radioGroupValue?.value) || (props.value != null && props.value == radioGroupValue?.value));
	
	const finalAllowUncheck = computed(():boolean => props.allowUncheck || (radioGroupProps?.allowUncheck ?? false));
	
	const innerIcon = computed(():string => radioGroupProps?.icon ?? props.icon)
	const innerSize = computed(():string => radioGroupProps?.size ?? props.size)
	const innerIconSize = computed(():string|null => radioGroupProps?.iconSize ?? props.iconSize)
	const innerFontSize = computed(():string|null => radioGroupProps?.fontSize ?? props.fontSize)
	const innerCheckedColor = computed(():string|null => radioGroupProps?.checkedColor ?? props.checkedColor)
	const innerIconBgColor = computed(():string => props.iconBgColor ?? radioGroupProps?.iconBgColor ?? 'white')
	const innerIconBorderColor = computed(():string => props.iconBorderColor ?? radioGroupProps?.iconBorderColor ?? '#c5c5c5')
	const innerIconDisabledColor = computed(():string => props.iconDisabledColor ?? radioGroupProps?.iconDisabledColor ?? '#c5c5c5')
	const innerIconDisabledBgColor = computed(():string => props.iconDisabledBgColor ?? radioGroupProps?.iconDisabledBgColor ?? '#f3f3f3')
	
	const classes = computed(():Map<string, boolean>=>{
		const cls = new Map<string, boolean>();
		cls.set(`${name}--disabled`, isDisabled.value)
		return cls
	})
	
	const iconClasses = computed(():Map<string, boolean>=>{
		const cls = new Map<string, boolean>();
		// #ifdef APP
		cls.set(`${name}__icon--checked`, radioChecked.value && innerCheckedColor.value == null)
		cls.set(`${name}__icon--${innerIcon.value}`, true)
		cls.set(`${name}__icon--disabled`, isDisabled.value)
		// #endif
		// #ifndef APP
		cls.set(`${name}__icon--checked`, radioChecked.value)
		cls.set(`${name}__icon--${innerIcon.value}`, true)
		cls.set(`${name}__icon--disabled`, isDisabled.value)
		// #endif
		return cls
	})
	
	const labelClass = computed(():Map<string, boolean>=>{
		const cls = new Map<string, boolean>();
		cls.set(`${name}__label--disabled`, isDisabled.value)
		return cls
	})
	
	const styles = computed(():Map<string, any>=>{
		const style = new Map<string, any>();
		if(radioGroupProps != null && radioGroupProps.gap != null) {
			style.set(radioGroupProps.direction == 'horizontal' ? 'margin-right' : 'margin-bottom', radioGroupProps.gap!)
		}
		
		// #ifndef APP
		if(innerCheckedColor.value != null) {
			style.set('--l-radio-icon-checked-color', innerCheckedColor.value!)
		}
		if(innerIconBorderColor.value != null) {
			style.set('--l-radio-icon-border-color', innerIconBorderColor.value!) 
		}
		if(innerIconDisabledColor.value != null) {
			style.set('--l-radio-icon-disabled-color', innerIconDisabledColor.value!)
		}
		if(innerIconDisabledBgColor.value != null) {
			style.set('--l-radio-icon-disabled-bg-color', innerIconDisabledBgColor.value!)
		}
		if(innerFontSize.value != null) {
			style.set('--l-radio-font-size', innerFontSize.value!)
		}
		// #endif
		return style
	})
	
	const iconStyle = computed(():Map<string, any>=>{
		const style = new Map<string, any>();
		if(innerIconSize.value != null) {
			style.set('width', innerIconSize.value!)
			style.set('height', innerIconSize.value!)
			// #ifndef APP
			style.set('--l-radio-icon-size', innerIconSize.value!)
			// #endif
		}
		
		if(innerCheckedColor.value != null) {
			// #ifndef APP
			style.set('--l-radio-icon-checked-color', innerCheckedColor.value!)
			// #endif
			// #ifdef APP
			if(radioChecked.value && ['dot', 'circle'].includes(innerIcon.value)) {
				style.set('background', innerCheckedColor.value!)
				style.set('border-color', innerCheckedColor.value!)
			}
			if(!isDisabled.value && !radioChecked.value && ['dot', 'circle'].includes(innerIcon.value)) {
				style.set('background', innerIconBgColor.value)
				style.set('border-color', innerIconBorderColor.value)
			}
			if(isDisabled.value && ['dot', 'circle'].includes(innerIcon.value)) {
				style.set('background', innerIconDisabledBgColor.value)
				style.set('border-color', innerIconDisabledColor.value)
			}
			// #endif
		}
		
		return style
	})
	const labelStyle = computed(():Map<string, any>=>{
		const style = new Map<string, any>();
		const fontSize = props.fontSize ?? radioGroupProps?.fontSize
		if(fontSize != null) {
			style.set('font-size', fontSize)
		}
		return style
	})
	
	const onClick = (e: UniPointerEvent) => {
		if(isDisabled.value) return;
		const _name = props.value ?? props.name
		if(radioGroupChange != null && _name != null) {
			const value = finalAllowUncheck.value && radioChecked.value ? null : _name;
			radioGroupChange(value);
		} else {
			const value = finalAllowUncheck.value ? !radioChecked.value : true;
			innerChecked.value = value
		}
	}
	// #ifdef APP
	const iconRef = ref<UniElement|null>(null)
	const update = () => {
		if(iconRef.value == null) return
		const ctx = iconRef.value!.getDrawableContext()!;
		const rect = iconRef.value!.getBoundingClientRect();
		const x = rect.width / 2;
		const y = rect.height / 2;
		
		ctx.reset();
		if(innerIcon.value == 'circle') {
			if(radioChecked.value) {
				ctx.strokeStyle = isDisabled.value ? innerIconDisabledColor.value : 'white';
				ctx.lineWidth = rect.width * 0.12;
				ctx.lineCap = 'round';
				ctx.moveTo(rect.width * 0.2967, rect.height * 0.53)
				ctx.lineTo(rect.width * 0.4342, rect.height * 0.6675)
				ctx.lineTo(rect.width * 0.7092, rect.height * 0.3925)
				ctx.stroke()
			}
		} else if(innerIcon.value == 'line') {
			if(radioChecked.value) {
				ctx.strokeStyle = isDisabled.value ? innerIconDisabledColor.value : props.checkedColor ?? '#3283ff';
				ctx.lineWidth = rect.width * 0.16;
				ctx.lineCap = 'round';
				ctx.moveTo(rect.width * 0.10, rect.height * 0.5466)
				ctx.lineTo(rect.width * 0.3666, rect.height * 0.8134)
				ctx.lineTo(rect.width * 0.90, rect.height * 0.28)
				ctx.stroke()
			}
		} else if(innerIcon.value == 'dot'){
			if(radioChecked.value) {
				ctx.fillStyle = isDisabled.value ? innerIconDisabledColor.value : 'white';
				ctx.arc(x, y, rect.width * 0.22, 0, Math.PI * 2)
				ctx.fill()
			}
		}
		ctx.update();
	}
	watchEffect(update)
	
	onMounted(()=>{
		nextTick(update)
	})
	// #endif
	
</script>
<style lang="scss">
	@import './index-u';
</style>