# -*- coding: utf-8 -*-
"""NYT のデジタル図版の作法に寄せた版。

参照した作法:
- 記事の地（白〜ごく薄い灰）をそのまま図版の地にする。図版だけ別の紙色を持たない
- データが画面で最も濃い（または最も明るい）ものになるよう地を決める
- 陸・境界・経緯線は灰に退く。線は点線ではなく極細の実線
- 凡例より直接の注記。ただし今回は文字なしの指定なので注記は入れない
"""
import os, sys
import numpy as np
sys.path.insert(0, '/home/claude/forest')
import forest1 as F, sylvania as S
from PIL import Image
OUT = '/home/claude/forest/out'

PAL = {
 # name: (地＝海, 陸, 森の最上位, 線の寄せ先)
 'N1': ((255, 255, 255), (238, 238, 235), (26, 74, 46), 'ink'),    # 白地・灰の陸・深い緑（NYT の標準形）
 'N2': ((247, 246, 243), (234, 232, 227), (26, 74, 46), 'ink'),    # ごく薄い暖灰の地（紙に見せない程度）
 'N3': ((255, 255, 255), (238, 238, 235), (70, 117, 80), 'ink'),   # 白地に SYLVANIA の緑
 'N4': ((16, 16, 16), (38, 38, 38), (126, 217, 87), 'paper'),      # 黒地・発光する緑（衛星画像系の作法）
}

def solid_grat(sc):
    def fn(d, s):
        for lat in (-60, -30, 0, 30, 60):
            F.dashed(d, [(x*s, y*s) for x, y in (sc.to_px(lon, lat) for lon in np.arange(-180, 180.1, 1))], 1.0, s, (1e9, 0))
        for lon in range(-180, 180, 30):
            F.dashed(d, [(x*s, y*s) for x, y in (sc.to_px(lon, la) for la in np.arange(-88, 88.1, 0.5))], 1.0, s, (1e9, 0))
    return fn

def build(name, year=2020, bands=8, size=(1350, 1080), bbox=(-180, -58, 180, 83), ds=8, lines=True, ss=3):
    out_size = size; size = (size[0]*ss, size[1]*ss)   # 3 倍で描いてから縮小（帯の境目と海岸線の階段を消す）
    paper, landc, ink, toward = PAL[name]
    paper = np.array(paper, np.float32); landc = np.array(landc, np.float32); ink = np.array(ink, np.float32)
    sc = F.Scene(bbox, size, proj='pc')
    lon, lat, ok = sc.lonlat_grid()
    land = F.land_mask(sc) > 0.5
    fr = F.sample_bilinear(F.frac(year, ds)[0], lon, lat, ok)
    img = np.zeros((sc.H, sc.W, 3), np.uint8); img[:] = paper.astype(np.uint8)
    img[land] = landc.astype(np.uint8)
    a, b = S.to_lab(landc), S.to_lab(ink)
    cols = [S.from_lab(a + (b - a) * (k + 0.5) / bands).astype(np.uint8) for k in range(bands)]
    on = land & (fr > 1.0 / bands / 2)
    for k in range(bands):
        m = on & (fr > k/bands) & (fr <= (k+1)/bands + (1 if k == bands-1 else 0))
        img[m] = cols[k]
    im = Image.fromarray(img)
    F.NAVY = ink if toward == 'ink' else paper
    F.WHITE = paper if toward == 'ink' else ink
    if lines:
        s = (sc.W, sc.H)
        im = F.comp_rel(im, F.aa_mask(s, solid_grat(sc)), 0.14, 0.10)   # 実線・さらに弱く
    if ss > 1: im = im.resize(out_size, Image.LANCZOS)
    im.save(f'{OUT}/{name}.png'); print(name, out_size, int(on.sum()), flush=True)
    return im

if __name__ == '__main__':
    for n in PAL: build(n)
