"""d26-d28: Detection & research."""
from diag import *
from matplotlib.patches import Circle


def d26():
    fig, ax = canvas("Telemetry coverage map", w=11.0, h=6.5,
                     caption="no single source suffices — layer them")
    cols = ["Sysmon 1", "Sysmon 3", "Sysmon 7", "Sysmon 12-14",
            "Security\n4624/4648/4672", "ETW (RPC/COM)", "Network"]
    rows = ["Lateral movement", "Privilege escalation", "UAC bypass",
            "Persistence", "Execution"]
    dots = {
        0: [0, 1, 4, 5, 6],   # LM
        1: [0, 2, 3, 4, 5],   # LPE
        2: [0, 2, 3, 5],      # UAC
        3: [0, 2, 3],         # Persistence
        4: [0, 1, 2, 5, 6],   # Execution
    }
    x0, cw = 26.0, 11.8
    ytop, rh = 45.5, 6.6
    ybot = ytop - 5 * rh
    centers_x = [x0 + (i + 0.5) * cw for i in range(7)]
    centers_y = [ytop - (j + 0.5) * rh for j in range(5)]
    for i in range(8):
        x = x0 + i * cw
        ax.plot([x, x], [ybot, ytop], color=RULE, lw=0.8, zorder=1)
    for j in range(6):
        y = ytop - j * rh
        ax.plot([x0, x0 + 7 * cw], [y, y], color=RULE, lw=0.8, zorder=1)
    for i, c in enumerate(cols):
        label(ax, centers_x[i] - 1.0, ytop + 1.2, c, fs=8.5, ha="left",
              va="bottom", zorder=4)
    for j, r in enumerate(rows):
        label(ax, x0 - 1.5, centers_y[j], r, fs=9.5, ha="right")
    for j, cidx in dots.items():
        for i in cidx:
            ax.add_patch(Circle((centers_x[i], centers_y[j]), 1.35,
                                facecolor=DEF, edgecolor="none", zorder=3))
    return save(fig, "d26-telemetry-map.png")


def d27():
    fig, ax = canvas("The zero-day pipeline", w=13.5, h=4.8)
    stages = [
        ("Enumerate", "OleViewDotNet\nregistry sweeps"),
        ("Triage", "OOP + SYSTEM\nACLs + dangerous\nmethods"),
        ("Static RE", "IDA / Ghidra\nproxy / typelib"),
        ("Dynamic harness", "clients · ProcMon\nTTD"),
        ("Fuzz", "typed mutation\nmarshal paths"),
        ("Root cause", "analysis"),
        ("Weaponize", "primitive →\nLPE chain"),
        ("Report", "MSRC / ZDI"),
    ]
    trans = ["candidates", "shortlist", "hypotheses", "harness", "crashes",
             "primitive", "chain"]
    xs = [9.3 + i * 16.5 for i in range(8)]
    boxes = []
    for (name, sub), x in zip(stages, xs):
        b = box(ax, x, 26, 14.0, 17)
        label(ax, x, 26 + 6.0 - (0.9 if "\n" not in sub else 0), name,
              fs=8.5, weight="bold")
        nlines = sub.count("\n") + 1
        label(ax, x, 26 - 1.2 - (nlines - 1) * 1.0, sub, fs=8.5, mono=True,
              color=SUB)
        boxes.append(b)
    for i in range(7):
        arrow(ax, boxes[i].side("r"), boxes[i + 1].side("l"), kind="research")
        label(ax, (boxes[i].r + boxes[i + 1].l) / 2, 35.7, trans[i], fs=8.5,
              va="bottom")
    for i, b in enumerate(boxes, 1):
        step_circle(ax, b.l, b.t, i)
    return save(fig, "d27-research-pipeline.png")


def d28():
    fig, ax = canvas("COM fuzzing harness anatomy", w=13.0, h=5.0)
    b1 = box(ax, 14, 32, 20, 9, "Create valid\nobject", fs=9)
    b2 = box(ax, 39, 32, 20, 9, "interface / method\niterator", fs=9)
    b3 = box(ax, 69, 32, 32, 13,
             "typed mutators:\nBSTR paths · SAFEARRAY bounds\nVARIANT types · IStream blobs\nfake interfaces",
             fs=8.5)
    b4 = box(ax, 99, 32, 18, 9, "call loop\nw/ HRESULT log", fs=9, mono=True)
    b5 = box(ax, 120, 32, 18, 13,
             "crash monitor:\npage heap +\nAppVerifier +\ndebugger + WER",
             fs=8.5)
    conn(ax, b1, "r", b2, "l", label="create", t=0.42, ly=1.4, fs=8.5,
         va="bottom")
    conn(ax, b2, "r", b3, "l", label="per method", ly=7.0, fs=8.5, va="bottom")
    conn(ax, b3, "r", b4, "l", label="mutated\nargs", ly=7.0, fs=8.5,
         va="bottom")
    conn(ax, b4, "r", b5, "l", label="observe", ly=7.0, fs=8.5, va="bottom")
    elbow(ax, [(120, 25.5), (120, 15), (39, 15), (39, 27.5)], kind="research",
          label="corpus / triage loop", li=1, ly=1.4, fs=8.5, va="bottom")
    return save(fig, "d28-fuzzing-harness.png")


ALL = [d26, d27, d28]
