package com.printer.demo.bean;

import java.text.BreakIterator;
import java.util.Locale;

/**
 * 基于 Unicode East Asian Width + Lao/Thai 组合规则
 * 0 = 不占列（组合音符）
 * 1 = 占 1 列
 * 2 = 占 2 列（全角 CJK）
 */
public final class EastAsianWidth {
    private EastAsianWidth() {}

    /* 主入口：返回字符串“视觉列数” */
    public static int visualLength(String s) {
        if (s == null || s.isEmpty()) return 0;
        int len = 0;
        BreakIterator it = BreakIterator.getCharacterInstance(Locale.ROOT);
        it.setText(s);
        int start = it.first();
        for (int end = it.next(); end != BreakIterator.DONE; start = end, end = it.next()) {
            String ch = s.substring(start, end);
            len += widthOf(ch);
        }
        return len;
    }

    /* 按视觉宽度截断 */
    public static String visualSubstring(String s, int maxCols) {
        if (s == null) return null;
        BreakIterator it = BreakIterator.getCharacterInstance(Locale.ROOT);
        it.setText(s);
        int cols = 0, last = 0;
        int start = it.first();
        for (int end = it.next(); end != BreakIterator.DONE; start = end, end = it.next()) {
            String ch = s.substring(start, end);
            cols += widthOf(ch);
            if (cols > maxCols) return s.substring(0, last);
            last = end;
        }
        return s;
    }

    /* 单字宽度 */
    private static int widthOf(String ch) {
        int cp = ch.codePointAt(0);
        // 1. 老挝文组合音符
        if (cp >= 0x0E31 && cp <= 0x0E3A) return 0;
        if (cp >= 0x0E47 && cp <= 0x0E4E) return 0;
        // 2. 泰文组合音符（顺带）
        if (cp >= 0x0E34 && cp <= 0x0E3A) return 0;
        if (cp >= 0x0E47 && cp <= 0x0E4E) return 0;
        // 3. 控制字符
        if (cp <= 0x1F || (cp >= 0x7F && cp <= 0x9F)) return 0;
        // 4. 全角区块
        if (cp >= 0x1100 && cp <= 0x115F) return 2;   // 韩文
        if (cp >= 0x2E80 && cp <= 0x9FFF) return 2;   // CJK
        if (cp >= 0xA960 && cp <= 0xA97F) return 2;
        if (cp >= 0xAC00 && cp <= 0xD7AF) return 2;
        if (cp >= 0xF900 && cp <= 0xFAFF) return 2;
        if (cp >= 0xFE10 && cp <= 0xFE19) return 2;
        if (cp >= 0xFE30 && cp <= 0xFE6F) return 2;
        if (cp >= 0xFF00 && cp <= 0xFF60) return 2;
        if (cp >= 0xFFE0 && cp <= 0xFFE6) return 2;
        // 5. 其余默认 1
        return 1;
    }
}