"""ServiceSim のレポート（報告動画・パネル付き動画・詰まりの地図）の色と字。決まりは STYLE.md（2026-11-08 エイイチ了承）。
3つのスクリプトはここから色と字を読む。スクリプトの中で色や字を決めない。変えるときはエイイチに確かめてから。
字：日本語は Noto Sans（Noto Sans CJK JP）、英数字は Inter（サイト pixelstomotors.com と同じ組み合わせ）。
"""
import os

HERE = os.path.dirname(os.path.abspath(__file__))

# ---- 下地（サイトの Base.astro と同じ）----
PAPER = "#f7f7f7"   # 背景
SHEET = "#ffffff"   # 白い面
INK = "#242424"     # 字・Unity の線・「次にやること」の札・字幕帯
MUTED = "#555555"   # 補足の字
FAINT = "#888888"   # 目盛り・卓の枠など、目立たせない線と字
RULE = "#e6e6e6"    # 罫線・グリッド
BAND = "#ececec"    # 範囲の帯（パネルの「今見ている所」など）
MAP_WALL = "#c8c8c8"  # 地図の通れない所（狭い道だけの所は RULE、通れる所は SHEET）

# ---- 立体の色（Unity の録画と同じ。最優先。この3つの意味にしか使わない）----
GUEST = "#e8c520"   # お客さん＝黄
STAFF = "#2a55c8"   # スタッフ＝青
ROBOT = "#ffffff"   # ロボット＝白（白い面に置くときは INK の縁を付ける）
ROBOT_SWATCH = "#f2f2f2"  # 色の説明の丸だけ（白だと背景に溶けるため）

# ---- 役割の色 ----
# 青＝その画面の主役（一番見てほしいもの）。何が主役かは図ごとに決め、凡例か線の横の名前で必ず書く。
# ただしスタッフが出る画面（録画・パネル）では青はスタッフ。その画面では主役に青を使わない。1つの画面で青に2つの意味を持たせない
MAIN = "#2f6fdf"       # 主役の線・点・枠
MAIN_SOFT = "#e8f0ff"  # 主役の面（地図の待機点など）

# ---- 意味の色（意味を固定）----
BAD = "#d85a30"     # 悪い・詰まり・待ち・止まり・助けが要る
GOOD = "#1d9e75"    # 良くなった・合格
QUIET = "#9a9a9a"   # 比べる相手・基準（サイトの試算の点線など）・記録だけ・取りやめ

# 報告動画の札：意味の名前 → 色。ここにない名前は使わない
TAG = {"good": GOOD, "bad": BAD, "quiet": QUIET, "next": INK}
# グラフの線：主役（ふつうは Unity）は MAIN の実線、比べる相手（サイトの試算）は QUIET の点線
SERIES = {"unity": MAIN, "main": MAIN, "site": QUIET, "bad": BAD}
# 古い spec の名前の読み替え（acc は青だった。良し悪しのない札・次にやることなので next にする）
TAG_ALIAS = {"acc": "next"}
SERIES_ALIAS = {"acc": "unity", "good": "unity"}

# ---- 字 ----
INTER = os.path.join(HERE, "fonts", "Inter-Regular.ttf")
INTER_B = os.path.join(HERE, "fonts", "Inter-Bold.ttf")
_NOTO_R = ["/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
           os.path.expanduser("~/Library/Fonts/NotoSansCJKjp-Regular.otf"),
           os.path.expanduser("~/Library/Fonts/NotoSansCJK-Regular.ttc"),
           "/Library/Fonts/NotoSansCJKjp-Regular.otf"]
_NOTO_B = ["/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc",
           os.path.expanduser("~/Library/Fonts/NotoSansCJKjp-Bold.otf"),
           os.path.expanduser("~/Library/Fonts/NotoSansCJK-Bold.ttc"),
           "/Library/Fonts/NotoSansCJKjp-Bold.otf"]


def _first(paths, what):
    for p in paths:
        if os.path.exists(p):
            return p
    raise SystemExit("字が見つからない（%s）。Noto Sans CJK JP を入れてから作る: %s" % (what, paths))


NOTO = _first(_NOTO_R, "Noto Sans CJK JP Regular")
NOTO_B = _first(_NOTO_B, "Noto Sans CJK JP Bold")
for _p in (INTER, INTER_B):
    if not os.path.exists(_p):
        raise SystemExit("字が見つからない: %s" % _p)

CSS_FONT = "'Inter','Noto Sans CJK JP','Noto Sans JP',sans-serif"
# Inter は英数字と半角の記号だけ（unicode-range）。①・→ などは Noto で描き、Pillow の is_latin と同じ分け方にする
_RANGE = "unicode-range:U+0000-00D6,U+00D8-024F"
CSS_FACE = ("@font-face{font-family:'Inter';font-weight:400;src:url('file://%s');%s}"
            "@font-face{font-family:'Inter';font-weight:700;src:url('file://%s');%s}") % (INTER, _RANGE, INTER_B, _RANGE)


def is_latin(ch):
    """英数字と半角の記号は Inter。それ以外（かな・漢字・全角の記号・①など）は Noto"""
    return ord(ch) < 0x250 and ch != "×"


# ---- Pillow：1つの文字列を Inter と Noto に分けて描く ----
_cache = {}


def _font(size, bold, latin):
    from PIL import ImageFont
    k = (size, bold, latin)
    if k not in _cache:
        path = (INTER_B if bold else INTER) if latin else (NOTO_B if bold else NOTO)
        _cache[k] = ImageFont.truetype(path, size, index=0)
    return _cache[k]


def _runs(s):
    out = []
    for ch in s:
        lat = is_latin(ch)
        if out and out[-1][0] == lat:
            out[-1][1] += ch
        else:
            out.append([lat, ch])
    return out


def text_width(s, size, bold=False):
    return sum(_font(size, bold, lat).getlength(t) for lat, t in _runs(s))


def text(d, xy, s, size, fill, bold=False, anchor="la"):
    """d.text の代わり。anchor は横 l/m/r と縦 a/m/s（Pillow と同じ書き方）。高さは Noto の字で決める"""
    x, y = xy
    w = text_width(s, size, bold)
    h, v = anchor[0], anchor[1]
    x = x - (w / 2 if h == "m" else w if h == "r" else 0)
    asc, desc = _font(size, bold, False).getmetrics()
    base = y + (asc if v == "a" else (asc - desc) / 2 if v == "m" else 0)
    for lat, t in _runs(s):
        f = _font(size, bold, lat)
        d.text((x, base), t, font=f, fill=fill, anchor="ls")
        x += f.getlength(t)


# ---- matplotlib ----
def mpl_setup():
    import matplotlib
    from matplotlib import font_manager as fm
    for p in (INTER, INTER_B, NOTO, NOTO_B):
        fm.fontManager.addfont(p)
    jp = fm.FontProperties(fname=NOTO).get_name()
    matplotlib.rcParams["font.family"] = ["Inter", jp]   # 英数字は Inter、無い字は Noto（matplotlib 3.6 以降）
    matplotlib.rcParams["text.color"] = INK
    matplotlib.rcParams["axes.labelcolor"] = INK
    matplotlib.rcParams["axes.edgecolor"] = FAINT
    matplotlib.rcParams["xtick.color"] = MUTED
    matplotlib.rcParams["ytick.color"] = MUTED
    matplotlib.rcParams["figure.facecolor"] = PAPER
    matplotlib.rcParams["savefig.facecolor"] = PAPER
