import { IconUrl } from "../../data/const/ResConst";
import { ResBaseAsset } from "./ResBaseAsset";

const { ccclass, menu, disallowMultiple, requireComponent } = cc._decorator;

/**
 * spine组件，自动管理资源的引用计数
 */
@ccclass
@disallowMultiple
@requireComponent(sp.Skeleton)
@menu("UI/ResSpine")
export default class ResSpine extends ResBaseAsset<sp.SkeletonData> {
	private _spSkeleton: sp.Skeleton = null;
	private _url: string = '';
	get spSkeleton() {
		return this._spSkeleton || (this._spSkeleton = this.node?.getComponent(sp.Skeleton) || this.node?.addComponent(sp.Skeleton));
	}
	public get skeletonData() {
		return this.spSkeleton.skeletonData;
	}
	// private m_CompleteFunc: Function;
	/**
	 * 通过 url 设置Spine
	 * @param bundle
	 * @param url spine动画 的json文件 路径
	 * @param extraData
	 * @returns
	 */
	setSpineData<EXTRA_DATA = any>(bundle: string, url: string, cb?: (asset: sp.SkeletonData) => void, isPremultipliedAlpha: boolean = true, animationName: string = "standby", loop: boolean = true, speed: number = 1) {
		this._url = url;
		this.loadAsset(bundle, url, sp.SkeletonData, (asset: sp.SkeletonData) => {
			if (asset && this.spSkeleton && this.spSkeleton.isValid) {
				this.spSkeleton.skeletonData = asset;
				this.spSkeleton.enableBatch = true;
				this.spSkeleton.premultipliedAlpha = isPremultipliedAlpha;
				this.spSkeleton.loop = loop;
				if (this.spSkeleton.findAnimation(animationName) != null) {
					this.spSkeleton.animation = animationName;
				}
				this.spSkeleton.timeScale = speed;
				cb && cb(asset);
			} else {
				console.warn(`加载 Spine 失败: ${bundle} ${url}`);
				cb && cb(null);
			}
		});
	}

	setRoleSpine(url1: IconUrl, url2: string, cb?: (asset: sp.SkeletonData) => void, isPremultipliedAlpha: boolean = true, animationName: string = "standby", loop: boolean = true, speed: number = 1) {
		this.setSpineData("spine", url1 + url2 + "/" + url2, cb, isPremultipliedAlpha, animationName, loop, speed);
	}

	setAnimation(animationName: string) {
		if (this.spSkeleton) {
			this.spSkeleton.animation = animationName;
		}
	}

	/**
	 * 播放动作
	 * @param aniName 动画名称
	 * @param loop 是否循环
	 * @param showLast 显示最后一帧
	 */
	playAnimation(aniName: string, loop: boolean, showLast?: boolean) {
		if (this.spSkeleton) {
			if (this.spSkeleton.findAnimation(aniName)) {
				this.spSkeleton.setAnimation(0, aniName, loop);
				if (showLast) {
					this.spSkeleton.timeScale = 100000;
				}
			} else {
				// console.error("动画名称不存在", this._url, aniName);
			}
		}
	}

	/** 是否存在动画 */
	isExistAnimation(aniName: string): boolean {
		return this.spSkeleton.findAnimation(aniName) ? true : false;
	}

	setTimeScale(speed: number) {
		if (this.spSkeleton) {
			this.spSkeleton.timeScale = speed;
		}
	}

	enableBatch() {
		this.spSkeleton.enableBatch = true;
	}

	clearTracks() {
		if (this.spSkeleton) {
			this.spSkeleton.clearTracks()
		}
	}
	clearRes() {
		this.spSkeleton.skeletonData = null;
		this.resetRes();
	}

	/** 设置渲染模式 */
	setCacheMode(mode: sp.Skeleton.AnimationCacheMode) {
		this.spSkeleton.setAnimationCacheMode(mode);
	}

	/** 后续废弃
	 * 添加播放完成监听 
	 */
	addCompleteListener(callback: Function) {
		// this.m_CompleteFunc = callback;
		this.spSkeleton.setCompleteListener((trackEntry, loopCount) => {
			// this.spSkeleton.setCompleteListener(null);
			// if (this.m_CompleteFunc) this.m_CompleteFunc();
			// this.m_CompleteFunc = null;
			callback(trackEntry, loopCount);
		});
	}

	/** 
	 * 添加播放完成监听 
	 */
	AddSpineCompleteListener(callback: Function) {
		// this.m_CompleteFunc = callback;
		this.spSkeleton.setCompleteListener((trackEntry, loopCount) => {
			let name = trackEntry.animation ? trackEntry.animation.name : '';
			callback(name);
		});
	}

	/** 移除完成监听 */
	removeCompleteListener() {
		this.spSkeleton?.setCompleteListener(null);
	}

	/** 添加事件帧监听 */
	addEventListener(callback: Function): void {
		this.spSkeleton.setEventListener((trackIndex, event: any) => {
			let name = event.data.name;
			callback(name);
		});
	}

	/** 移除事件帧监听 */
	removeEventListener() {
		this.spSkeleton.setEventListener(null);
	}

	/** 获取插槽节点世界坐标 */
	getSlotWorldPos(slotName: string): cc.Vec2 {
		if (!slotName) return null;
		let slot: sp.spine.Slot = this.spSkeleton.findSlot(slotName);
		// 输出骨骼点的信息
		if (slot) {
			// 获取骨骼点的世界变换信息
			const worldX = slot.bone.worldX;
			const worldY = slot.bone.worldY;
			return this.node.convertToWorldSpaceAR(cc.v2(worldX, worldY)); //转换世界坐标
		} else {
			// console.error("未找到骨骼点: ", slotName);
			return null;
		}
	}

	/** 获取骨骼节点世界坐标 */
	getBoneWorldPos(boneName: string): cc.Vec2 {
		if (!boneName) return null;
		let bone: sp.spine.Bone = this.spSkeleton.findBone(boneName);
		// 输出骨骼点的信息
		if (bone) {
			// 获取骨骼点的世界变换信息
			const worldX = bone.worldX;
			const worldY = bone.worldY;
			return this.node.convertToWorldSpaceAR(cc.v2(worldX, worldY)); //转换世界坐标
		} else {
			// console.error("未找到骨骼点: ", boneName);
			return null;
		}
	}

	PauseAction() {
		if (this.spSkeleton && this.spSkeleton.isValid)
			this.spSkeleton.paused = true;
	}

	ResumeAction() {
		if (this.spSkeleton && this.spSkeleton.isValid)
			this.spSkeleton.paused = false;
	}

	StopAction() {
		if (this.spSkeleton && this.spSkeleton.isValid)
			this.spSkeleton.clearTracks();
	}
}
