import { computed, type ComputedRef } from "vue";
import { config } from "../config";

/**
 * 字号管理类
 * 用于处理文本大小的缩放和样式
 */
class Size {
	// 预设的字号类名
	public names = [
		"text-xs",
		"text-sm",
		"text-md",
		"text-lg",
		"text-xl",
		"text-2xl",
		"text-3xl",
		"text-4xl",
		"text-5xl",
		"text-6xl",
		"text-7xl",
		"text-8xl",
		"text-9xl"
	];

	// 对应的字号大小
	public sizes = [20, 24, 28, 32, 36, 44, 52, 60, 72, 84, 96, 120, 152];

	// 对应的行高
	public lineHeights = [28, 36, 44, 52, 52, 1, 1, 1, 1, 1, 1, 1, 1];

	// 原始类名
	public className: ComputedRef<string> = computed(() => "");

	// 计算后的类名
	public ptClassName: ComputedRef<string>;

	constructor(cb: (() => string) | null) {
		this.className = computed(cb ?? (() => ""));

		// 根据全局字号配置动态计算类名
		this.ptClassName = computed(() => {
			if (config.fontSize == null) {
				return this.className.value;
			}

			const name = this.names[this.getIndex()];
			return this.className.value.replace(`-important-${name}`, "").replace(name, "");
		});
	}

	/**
	 * 获取全局字号缩放比例
	 */
	getScale = () => {
		return config.fontSize ?? 1;
	};

	/**
	 * 根据缩放比例计算rpx值
	 * @param val - 需要转换的值
	 */
	getRpx = (val: number | string) => {
		const scale = this.getScale();

		if (typeof val == "number") {
			return val * scale + "rpx";
		} else {
			const num = parseFloat(val);
			const unit = val.replace(`${num}`, "");

			return num * scale + unit;
		}
	};

	/**
	 * 获取当前字号在预设中的索引
	 */
	getIndex = () => {
		let index = this.names.findIndex((name) => {
			if (this.className.value.includes(name)) {
				return true;
			}

			return false;
		});

		// 默认使用 text-md (14px)
		if (index < 0) {
			index = 2;
		}

		return index;
	};

	/**
	 * 获取最终的字号大小
	 * @param size - 指定字号大小，为空则使用预设值
	 */
	getSize = (size: number | string | null): null | string => {
		// 如果未设置全局字号，且未指定size，直接返回null；否则返回对应rpx值
		if (config.fontSize == null && size == null) {
			return null;
		}

		return this.getRpx(size ?? this.sizes[this.getIndex()]);
	};

	/**
	 * 获取当前行高
	 */
	getLineHeight = (): null | string => {
		// 未设置全局字号时返回null
		if (config.fontSize == null) {
			return null;
		}

		const lineHeight = this.lineHeights[this.getIndex()];
		return lineHeight == 1 ? `1` : this.getRpx(lineHeight);
	};
}

/**
 * 字号管理Hook
 * @param className - 类名
 */
export function useSize(cb: (() => string) | null = null): Size {
	return new Size(cb);
}
