// 引入颜色处理库
import { tinyColor } from '@/uni_modules/lime-color';


/**
 * 操作类型
 * play: 开始动画
 * failed: 显示失败状态
 * clear: 清除动画
 * destroy: 销毁实例
 */
export type TickType = 'play' | 'failed' | 'clear' | 'destroy' | 'pause'
/**
 * 加载动画类型
 * circular: 环形加载动画
 * spinner: 旋转器加载动画
 * failed: 失败状态动画
 */
export type LoadingType = 'circular' | 'spinner' | 'failed';
/**
 * 加载组件返回接口
 */
export type UseLoadingReturn = {
	ratio : 1;
	type : LoadingType;
	mode : 'raf' | 'animate'; // 
	color : string;//Ref<string>;
	play : () => void;
	failed : () => void;
	clear : () => void;
	destroy : () => void;
	pause : () => void;
}


/**
 * 计算圆周上指定角度的点的坐标
 * @param centerX 圆心的 X 坐标
 * @param centerY 圆心的 Y 坐标
 * @param radius 圆的半径
 * @param angleDegrees 角度（以度为单位）
 * @returns 包含 X 和 Y 坐标的对象
 */
function getPointOnCircle(
	centerX : number,
	centerY : number,
	radius : number,
	angleDegrees : number
) : number[] {
	// 将角度转换为弧度
	const angleRadians = (angleDegrees * Math.PI) / 180;

	// 计算点的 X 和 Y 坐标
	const x = centerX + radius * Math.cos(angleRadians);
	const y = centerY + radius * Math.sin(angleRadians);

	return [x, y]
}

export function useLoading(element : Ref<UniElement | null>) : UseLoadingReturn {

	const tick = ref<TickType>('pause')

	const state = reactive<UseLoadingReturn>({
		color: '#000',
		type: 'circular',
		ratio: 1,
		mode: 'raf',
		play: () => {
			tick.value = 'play'
		},
		failed: () => {
			tick.value = 'failed'
		},
		clear: () => {
			tick.value = 'clear'
		},
		destroy: () => {
			tick.value = 'destroy'
		},
		pause: () => {
			tick.value = 'pause'
		}
	})

	const context = shallowRef<DrawableContext | null>(null);
	// let ctx:DrawableContext|null = null

	// let rotation = 0
	let isPlaying = false
	let canvasWidth = ref(0)
	let canvasHeight = ref(0)
	let canvasSize = ref(0)

	let animationFrameId = -1
	let animation : UniAnimation | null = null

	let drawFrame : (() => void) | null = null
	const size = computed(() : number => state.ratio > 1 ? state.ratio : canvasSize.value * state.ratio)
	// 绘制圆形加载
	const drawCircular = () => {
		let startAngle = 0;   // 起始角度
		let endAngle = 0;     // 结束角度
		let rotate = 0;       // 旋转角度

		// const ctx = context.value!
		// 动画参数配置
		const MIN_ANGLE = 5;          // 最小保持角度
		const ARC_LENGTH = 359.5      // 最大弧长（避免闭合）
		const PI = Math.PI / 180      // 角度转弧度系数
		const SPEED = 0.018 / 4           // 动画速度
		const ROTATE_INTERVAL = 0.09 / 4  // 旋转增量

		const lineWidth = size.value / 10;  // 线宽计算
		const x = canvasWidth.value / 2           // 中心点X
		const y = canvasHeight.value / 2          // 中心点Y
		const radius = size.value / 2 - lineWidth // 实际绘制半径
		try {
			drawFrame = () => {
				if (context.value == null || !isPlaying) return
				let ctx = context.value!
			
			
				// console.log('radius', radius, size.value)
				ctx.reset();
			
				// 绘制圆弧
				ctx.beginPath();
				ctx.arc(
					x,
					y,
					radius,
					startAngle * PI + rotate,
					endAngle * PI + rotate
				);
				ctx.lineWidth = lineWidth;
				ctx.strokeStyle = state.color;
				ctx.stroke();
			
				// 角度更新逻辑
				if (endAngle < ARC_LENGTH) {
					endAngle = Math.min(ARC_LENGTH, endAngle + (ARC_LENGTH - MIN_ANGLE) * SPEED);
				} else if (startAngle < ARC_LENGTH) {
					startAngle = Math.min(ARC_LENGTH, startAngle + (ARC_LENGTH - MIN_ANGLE) * SPEED);
				} else {
					// 重置时保留最小可见角度
					startAngle = 0;
					endAngle = MIN_ANGLE;
				}
			
				ctx.update()
			
			
			
				if (state.mode == 'raf') {
					rotate = (rotate + ROTATE_INTERVAL) % 360; // 持续旋转并限制范围
					if (isPlaying && drawFrame != null) {
						animationFrameId = requestAnimationFrame(drawFrame!)
					}
				}
			}
		} catch(err) {
			
		}
	}

	let lastTime = Date.now();
	const drawSpinner = () => {
		const steps = 12;     // 旋转线条数量
		// const size = state.ratio > 1 ? state.ratio : canvasSize.value
		const lineWidth = size.value / 10;  // 线宽
		const x = canvasWidth.value / 2  // 中心坐标
		const y = canvasHeight.value / 2

		let step = 0;         // 当前步数
		// #ifdef APP-HARMONY
		const length = size.value / 3.4 - lineWidth;  // 线长
		// #endif
		// #ifndef APP-HARMONY
		const length = size.value / 3.6 - lineWidth;  // 线长
		// #endif
		const offset = size.value / 4;      // 距中心偏移

		/** 生成颜色渐变数组 */
		function generateColorGradient(hex : string, steps : number) : string[] {
			const colors : string[] = []
			const _color = tinyColor(hex)

			for (let i = 1; i <= steps; i++) {
				_color.setAlpha(i / steps);
				colors.push(_color.toRgbString());
			}
			return colors
		}

		// 计算颜色渐变
		let colors = computed(() : string[] => generateColorGradient(state.color, steps))

		/** 帧绘制函数 */
		drawFrame = () => {
			if (context.value == null || !isPlaying) return
			const delta = Date.now() - lastTime;


			if (delta >= 1000 / 10) {
				lastTime = Date.now();
				let ctx = context.value!
				ctx.reset();
				for (let i = 0; i < steps; i++) {
					const stepAngle = 360 / steps;    // 单步角度
					const angle = stepAngle * i;      // 当前角度
					const index = (steps + i - step) % steps // 颜色索引
					// 计算线段坐标
					const radian = angle * Math.PI / 180;
					const cos = Math.cos(radian);
					const sin = Math.sin(radian);

					// 绘制线段
					ctx.beginPath();
					ctx.moveTo(x + offset * cos, y + offset * sin);
					ctx.lineTo(x + (offset + length) * cos, y + (offset + length) * sin);
					ctx.lineWidth = lineWidth;
					ctx.lineCap = 'round';
					ctx.strokeStyle = colors.value[index];
					ctx.stroke();
				}
				
				ctx.update()
				if(state.mode == 'raf') {
					// step += 1
					step = (step + 1) % steps; // 限制step范围
				}
			}


			if (state.mode == 'raf') {
				if (isPlaying && drawFrame != null) {
					animationFrameId = requestAnimationFrame(drawFrame!)
				}
			}
		}
	}

	const drwaFailed = () => {
		if (context.value == null) return
		let ctx = context.value!

		// const size = state.ratio > 1 ? state.ratio : canvasSize.value
		const innerSize = size.value * 0.8 // 内圈尺寸
		const lineWidth = innerSize / 10; // 线宽
		const lineLength = (size.value - lineWidth) / 2 // X长度
		const centerX = canvasWidth.value / 2;
		const centerY = canvasHeight.value / 2;
		const radius = (size.value - lineWidth) / 2



		const angleRadians1 = 45 * Math.PI / 180
		const angleRadians2 = (45 - 90) * Math.PI / 180

		ctx.reset()
		ctx.lineWidth = lineWidth;
		ctx.strokeStyle = state.color;

		// 绘制逐渐显示的圆
		ctx.beginPath();
		ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
		ctx.lineWidth = lineWidth;
		ctx.strokeStyle = state.color;
		ctx.stroke();

		const [startX1, startY] = getPointOnCircle(centerX, centerY, lineLength / 2, 180 + 45)
		const [startX2] = getPointOnCircle(centerX, centerY, lineLength / 2, 180 + 90 + 45)

		const x2 = Math.sin(angleRadians1) * lineLength + startX1
		const y2 = Math.cos(angleRadians1) * lineLength + startY

		ctx.beginPath();
		ctx.moveTo(startX1, startY)
		ctx.lineTo(x2, y2)
		ctx.stroke();

		const x3 = Math.sin(angleRadians2) * lineLength + startX2
		const y3 = Math.cos(angleRadians2) * lineLength + startY

		ctx.beginPath();
		ctx.moveTo(startX2, startY)
		ctx.lineTo(x3, y3)
		ctx.stroke();


		ctx.update()
	}

	let currentType : LoadingType | null = null
	const useMode = () => {
		if (state.mode != 'raf') {
			const keyframes = [{ transform: 'rotate(0)' }, { transform: 'rotate(360)' }]
			animation = element.value!.animate(keyframes, {
				duration: 80000,
				easing: 'linear',
				// fill: 'forwards',
				iterations: Infinity
			})
		}
	}
	const startAnimation = (type : string) => {
		if (context.value == null || element.value == null) return
		animation?.pause()

		if (currentType == type) {
			isPlaying = true
			animation?.play()
			drawFrame?.()
			return
		}

		if (type == 'circular') {
			currentType = 'circular'
			drawCircular()
			useMode()

		}

		if (type == 'spinner') {
			currentType = 'spinner'
			drawSpinner()
			useMode()
		}

		isPlaying = true
		drawFrame?.()
	}

	// 监听元素尺寸
	let manualCheckTimer:number|null = null;
	const getBoundingClientRect = () => {
		if(manualCheckTimer != null){
			clearTimeout(manualCheckTimer!);
		}
		requestAnimationFrame(()=> {
			element.value?.getBoundingClientRectAsync()?.then(rect => {
				if (rect.width == 0 || rect.height == 0) return
				context.value = element.value!.getDrawableContext() as DrawableContext;
				canvasWidth.value = rect.width;
				canvasHeight.value = rect.height;
				canvasSize.value = Math.min(rect.width, rect.height);
				// startAnimation(state.type)
			})
		})
	}
	
	const resizeObserver : UniResizeObserver = new UniResizeObserver((_entries : UniResizeObserverEntry[]) => {
		getBoundingClientRect()
	});

	watchEffect(() => {
		if (element.value == null) return
		resizeObserver.observe(element.value!);
		// #ifdef APP-IOS
		// nextTick(getBoundingClientRect)
		 manualCheckTimer = setTimeout(() => {
			getBoundingClientRect();
		}, 50);
		// #endif
	})

	watchEffect(() => {
		if (context.value == null) return
		if (tick.value == 'play') {
			animation?.pause()
			isPlaying = false
			cancelAnimationFrame(animationFrameId)
			startAnimation(state.type)
		}
		if (tick.value == 'failed') {
			cancelAnimationFrame(animationFrameId)
			animation?.pause()
			animation?.cancel()
			drwaFailed()
			return
		}
		if (tick.value == 'clear') {
			cancelAnimationFrame(animationFrameId)
			animation?.pause()
			animation?.cancel()
			context.value?.reset();
			context.value?.update();
			isPlaying = false
			return
		}
		if (tick.value == 'destroy') {
			cancelAnimationFrame(animationFrameId)
			animation?.pause()
			animation?.cancel()
			context.value?.reset();
			context.value?.update();
			context.value = null
			animation = null
			isPlaying = false
			return
		}
		if (tick.value == 'pause') {
			// 首次需要绘制一帧
			if(animation == null) {
				startAnimation(state.type)
			}
			cancelAnimationFrame(animationFrameId)
			isPlaying = false
			animation?.pause()
			return
		}
	})
	
	watchEffect(()=>{
		if(state.color == '') return
		// #ifdef APP-HARMONY
		isPlaying = false
		cancelAnimationFrame(animationFrameId)
		// #endif
	})
	
	return state
}