//! Geometric Shapes | U+25A0...U+25FF
//! https://en.wikipedia.org/wiki/Geometric_Shapes_(Unicode_block)
//!
//! ■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯
//! ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿
//! ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ●
//! ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟
//! ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯
//! ◰ ◱ ◲ ◳ ◴ ◵ ◶ ◷ ◸ ◹ ◺ ◻ ◼ ◽︎◾︎◿
//!
//! Only a subset of this block is viable for sprite drawing; filling
//! out this file to have full coverage of this block is not the goal.
//!

const std = @import("std");
const Allocator = std.mem.Allocator;

const common = @import("common.zig");
const Thickness = common.Thickness;
const Corner = common.Corner;
const Shade = common.Shade;

const font = @import("../../main.zig");

/// ◢ ◣ ◤ ◥
pub fn draw25E2_25E5(
    cp: u32,
    canvas: *font.sprite.Canvas,
    width: u32,
    height: u32,
    metrics: font.Metrics,
) !void {
    _ = width;
    _ = height;
    switch (cp) {
        // ◢
        0x25e2 => try cornerTriangleShade(metrics, canvas, .br, .on),
        // ◣
        0x25e3 => try cornerTriangleShade(metrics, canvas, .bl, .on),
        // ◤
        0x25e4 => try cornerTriangleShade(metrics, canvas, .tl, .on),
        // ◥
        0x25e5 => try cornerTriangleShade(metrics, canvas, .tr, .on),

        else => unreachable,
    }
}

/// ◸ ◹ ◺
pub fn draw25F8_25FA(
    cp: u32,
    canvas: *font.sprite.Canvas,
    width: u32,
    height: u32,
    metrics: font.Metrics,
) !void {
    _ = width;
    _ = height;
    switch (cp) {
        // ◸
        0x25f8 => try cornerTriangleOutline(metrics, canvas, .tl),
        // ◹
        0x25f9 => try cornerTriangleOutline(metrics, canvas, .tr),
        // ◺
        0x25fa => try cornerTriangleOutline(metrics, canvas, .bl),

        else => unreachable,
    }
}

/// ◿
pub fn draw25FF(
    cp: u32,
    canvas: *font.sprite.Canvas,
    width: u32,
    height: u32,
    metrics: font.Metrics,
) !void {
    _ = cp;
    _ = width;
    _ = height;
    try cornerTriangleOutline(metrics, canvas, .br);
}

pub fn cornerTriangleShade(
    metrics: font.Metrics,
    canvas: *font.sprite.Canvas,
    comptime corner: Corner,
    comptime shade: Shade,
) !void {
    const float_width: f64 = @floatFromInt(metrics.cell_width);
    const float_height: f64 = @floatFromInt(metrics.cell_height);

    const x0, const y0, const x1, const y1, const x2, const y2 =
        switch (corner) {
            .tl => .{
                0,
                0,
                0,
                float_height,
                float_width,
                0,
            },
            .tr => .{
                0,
                0,
                float_width,
                float_height,
                float_width,
                0,
            },
            .bl => .{
                0,
                0,
                0,
                float_height,
                float_width,
                float_height,
            },
            .br => .{
                0,
                float_height,
                float_width,
                float_height,
                float_width,
                0,
            },
        };

    var path = canvas.staticPath(5); // nodes.len = 0
    path.moveTo(x0, y0); // +1, nodes.len = 1
    path.lineTo(x1, y1); // +1, nodes.len = 2
    path.lineTo(x2, y2); // +1, nodes.len = 3
    path.close(); // +2, nodes.len = 5

    try canvas.fillPath(
        path.wrapped_path,
        .{},
        @enumFromInt(@intFromEnum(shade)),
    );
}

pub fn cornerTriangleOutline(
    metrics: font.Metrics,
    canvas: *font.sprite.Canvas,
    comptime corner: Corner,
) !void {
    const float_thick: f64 = @floatFromInt(Thickness.light.height(metrics.box_thickness));
    const float_width: f64 = @floatFromInt(metrics.cell_width);
    const float_height: f64 = @floatFromInt(metrics.cell_height);

    const x0, const y0, const x1, const y1, const x2, const y2 =
        switch (corner) {
            .tl => .{
                0,
                0,
                0,
                float_height,
                float_width,
                0,
            },
            .tr => .{
                0,
                0,
                float_width,
                float_height,
                float_width,
                0,
            },
            .bl => .{
                0,
                0,
                0,
                float_height,
                float_width,
                float_height,
            },
            .br => .{
                0,
                float_height,
                float_width,
                float_height,
                float_width,
                0,
            },
        };

    var path = canvas.staticPath(5); // nodes.len = 0
    path.moveTo(x0, y0); // +1, nodes.len = 1
    path.lineTo(x1, y1); // +1, nodes.len = 2
    path.lineTo(x2, y2); // +1, nodes.len = 3
    path.close(); // +2, nodes.len = 5

    try canvas.innerStrokePath(path.wrapped_path, .{
        .line_cap_mode = .butt,
        .line_width = float_thick,
    }, .on);
}
