// The MIT License (MIT)
//
// Copyright (C) 2026 Scott Duensing
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// mkicon.c  -- Generate simple 32x32 BMP icons for DVX apps
//
// Usage: mkicon <output.bmp> <type>
// Types: clock, notepad, cpanel, dvxdemo, imgview
//
// Generates recognizable pixel-art icons at 32x32 24-bit BMP.

#include "bmpDraw.h"

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#define ICON_W       32
#define ICON_H       32
#define PI           3.14159265
#define CLOCK_RIM    360
#define CLOCK_HOURS  12
#define DEG_PER_HOUR 30.0

static BmpCanvasT canvas;

// ============================================================
// Prototypes
// ============================================================

static void iconBasic(void);
static void iconClock(void);
static void iconCpanel(void);
static void iconDvxdemo(void);
static void iconHelp(void);
static void iconIconEd(void);
static void iconImgview(void);
static void iconNoIcon(void);
static void iconNotepad(void);
static void iconResedit(void);


// DVX BASIC icon: code brackets with "B" letterform
static void iconBasic(void) {
    bmpClear(&canvas, 192, 192, 192);

    // Blue background rectangle (code editor feel)
    bmpFillRect(&canvas, 2, 2, 28, 28, 0, 0, 128);

    // Left bracket {
    bmpVLine(&canvas, 6, 6, 20, 255, 255, 0);
    bmpHLine(&canvas, 7, 6, 3, 255, 255, 0);
    bmpHLine(&canvas, 7, 25, 3, 255, 255, 0);
    bmpHLine(&canvas, 4, 15, 2, 255, 255, 0);
    bmpPixel(&canvas, 5, 14, 255, 255, 0);
    bmpPixel(&canvas, 5, 16, 255, 255, 0);

    // "B" letter in white (bold, centered)
    // Vertical stroke
    bmpVLine(&canvas, 14, 7, 18, 255, 255, 255);

    // Top horizontal
    bmpHLine(&canvas, 14, 7, 7, 255, 255, 255);
    bmpHLine(&canvas, 14, 8, 7, 255, 255, 255);

    // Middle horizontal
    bmpHLine(&canvas, 14, 15, 7, 255, 255, 255);
    bmpHLine(&canvas, 14, 16, 7, 255, 255, 255);

    // Bottom horizontal
    bmpHLine(&canvas, 14, 23, 7, 255, 255, 255);
    bmpHLine(&canvas, 14, 24, 7, 255, 255, 255);

    // Right curves of B (top bump)
    bmpVLine(&canvas, 21, 8, 7, 255, 255, 255);
    bmpPixel(&canvas, 20, 8, 255, 255, 255);
    bmpPixel(&canvas, 20, 14, 255, 255, 255);

    // Right curves of B (bottom bump)
    bmpVLine(&canvas, 21, 17, 6, 255, 255, 255);
    bmpPixel(&canvas, 20, 17, 255, 255, 255);
    bmpPixel(&canvas, 20, 23, 255, 255, 255);

    // Right bracket }
    bmpVLine(&canvas, 25, 6, 20, 255, 255, 0);
    bmpHLine(&canvas, 22, 6, 3, 255, 255, 0);
    bmpHLine(&canvas, 22, 25, 3, 255, 255, 0);
    bmpHLine(&canvas, 26, 15, 2, 255, 255, 0);
    bmpPixel(&canvas, 26, 14, 255, 255, 0);
    bmpPixel(&canvas, 26, 16, 255, 255, 0);
}


// Clock icon: circle with hands
static void iconClock(void) {
    bmpClear(&canvas, 192, 192, 192);
    bmpFillCircle(&canvas, 15, 15, 13, 255, 255, 255);
    bmpFillCircle(&canvas, 15, 15, 12, 240, 240, 255);

    // Rim
    for (int a = 0; a < CLOCK_RIM; a++) {
        double rad = a * PI / 180.0;
        int x = 15 + (int)(13.0 * __builtin_cos(rad));
        int y = 15 + (int)(13.0 * __builtin_sin(rad));
        bmpPixel(&canvas, x, y, 0, 0, 128);
    }

    // Hour marks
    for (int i = 0; i < CLOCK_HOURS; i++) {
        double rad = i * DEG_PER_HOUR * PI / 180.0;
        int x = 15 + (int)(11.0 * __builtin_cos(rad));
        int y = 15 + (int)(11.0 * __builtin_sin(rad));
        bmpPixel(&canvas, x, y, 0, 0, 128);
    }

    // Hour hand (pointing ~10 o'clock)
    bmpVLine(&canvas, 15, 7, 8, 0, 0, 128);

    // Minute hand (pointing ~2 o'clock)
    for (int i = 0; i < 10; i++) {
        bmpPixel(&canvas, 15 + i * 2 / 3, 15 - i * 2 / 3, 0, 0, 200);
    }

    // Center dot
    bmpPixel(&canvas, 15, 15, 200, 0, 0);
}


// Control Panel icon: gear/wrench
static void iconCpanel(void) {
    bmpClear(&canvas, 192, 192, 192);

    // Gear body
    bmpFillCircle(&canvas, 15, 15, 8, 128, 128, 128);
    bmpFillCircle(&canvas, 15, 15, 5, 192, 192, 192);

    // Gear teeth (N/S/E/W and diagonals)
    bmpFillRect(&canvas, 13, 2, 5, 4, 128, 128, 128);
    bmpFillRect(&canvas, 13, 26, 5, 4, 128, 128, 128);
    bmpFillRect(&canvas, 2, 13, 4, 5, 128, 128, 128);
    bmpFillRect(&canvas, 26, 13, 4, 5, 128, 128, 128);
    bmpFillRect(&canvas, 4, 4, 4, 4, 128, 128, 128);
    bmpFillRect(&canvas, 24, 4, 4, 4, 128, 128, 128);
    bmpFillRect(&canvas, 4, 24, 4, 4, 128, 128, 128);
    bmpFillRect(&canvas, 24, 24, 4, 4, 128, 128, 128);

    // Inner circle (hole)
    bmpFillCircle(&canvas, 15, 15, 3, 64, 64, 64);
}


// DVX Demo icon: colorful diamond
static void iconDvxdemo(void) {
    bmpClear(&canvas, 192, 192, 192);

    // Diamond shape with color gradient
    for (int y = 0; y < 16; y++) {
        int hw = y + 1;

        for (int x = -hw; x <= hw; x++) {
            int px = 15 + x;
            int py = 2 + y;
            uint8_t r = (uint8_t)(128 + y * 8);
            uint8_t g = (uint8_t)(64 + (hw - (x < 0 ? -x : x)) * 8);
            uint8_t b = (uint8_t)(200 - y * 4);
            bmpPixel(&canvas, px, py, r, g, b);
        }
    }

    for (int y = 0; y < 14; y++) {
        int hw = 14 - y;

        for (int x = -hw; x <= hw; x++) {
            int px = 15 + x;
            int py = 18 + y;
            uint8_t r = (uint8_t)(255 - y * 8);
            uint8_t g = (uint8_t)(128 - y * 4);
            uint8_t b = (uint8_t)(100 + y * 8);
            bmpPixel(&canvas, px, py, r, g, b);
        }
    }
}


static void iconHelp(void) {
    // Blue book with white "?" on it
    bmpClear(&canvas, 192, 192, 192);

    // Book body (blue)
    bmpFillRect(&canvas, 6, 4, 20, 24, 0, 0, 180);

    // Book spine (darker blue)
    bmpFillRect(&canvas, 6, 4, 3, 24, 0, 0, 130);

    // Book pages (white edge)
    bmpVLine(&canvas, 25, 5, 22, 255, 255, 255);

    // Question mark in white
    // Top curve
    bmpHLine(&canvas, 14, 9, 5, 255, 255, 255);
    bmpPixel(&canvas, 13, 10, 255, 255, 255);
    bmpPixel(&canvas, 19, 10, 255, 255, 255);
    bmpPixel(&canvas, 19, 11, 255, 255, 255);
    bmpPixel(&canvas, 18, 12, 255, 255, 255);
    bmpPixel(&canvas, 17, 13, 255, 255, 255);
    // Stem
    bmpPixel(&canvas, 16, 14, 255, 255, 255);
    bmpPixel(&canvas, 16, 15, 255, 255, 255);
    bmpPixel(&canvas, 16, 16, 255, 255, 255);
    // Dot
    bmpPixel(&canvas, 16, 19, 255, 255, 255);
    bmpPixel(&canvas, 16, 20, 255, 255, 255);
}


// Icon editor: pixel grid with pencil drawing a pixel
static void iconIconEd(void) {
    bmpClear(&canvas, 220, 220, 220);

    // Draw a 5x5 grid of colored pixels (the "canvas")
    int gx = 3;
    int gy = 3;
    int cs = 5;

    // Grid lines
    for (int i = 0; i <= 5; i++) {
        bmpHLine(&canvas, gx, gy + i * cs, 5 * cs + 1, 160, 160, 160);
        bmpVLine(&canvas, gx + i * cs, gy, 5 * cs + 1, 160, 160, 160);
    }

    // Some colored pixels in the grid
    bmpFillRect(&canvas, gx + 1,       gy + 1,       cs - 1, cs - 1, 255, 0,   0);
    bmpFillRect(&canvas, gx + cs + 1,  gy + 1,       cs - 1, cs - 1, 0,   0,   255);
    bmpFillRect(&canvas, gx + 1,       gy + cs + 1,  cs - 1, cs - 1, 0,   180, 0);
    bmpFillRect(&canvas, gx + cs + 1,  gy + cs + 1,  cs - 1, cs - 1, 255, 255, 0);
    bmpFillRect(&canvas, gx + 2*cs+1,  gy + 2*cs+1,  cs - 1, cs - 1, 255, 128, 0);
    bmpFillRect(&canvas, gx + 3*cs+1,  gy + 1,       cs - 1, cs - 1, 128, 0,   255);

    // Pencil (diagonal, bottom-right area)
    for (int i = 0; i < 12; i++) {
        bmpPixel(&canvas, 18 + i, 28 - i, 230, 200, 80);
        bmpPixel(&canvas, 19 + i, 28 - i, 230, 200, 80);
        bmpPixel(&canvas, 18 + i, 29 - i, 230, 200, 80);
    }

    // Pencil tip
    bmpPixel(&canvas, 17, 29, 40, 40, 40);
    bmpPixel(&canvas, 17, 30, 40, 40, 40);
    bmpPixel(&canvas, 18, 30, 40, 40, 40);

    // Eraser end
    bmpPixel(&canvas, 29, 17, 240, 150, 150);
    bmpPixel(&canvas, 30, 16, 240, 150, 150);
    bmpPixel(&canvas, 30, 17, 240, 150, 150);
    bmpPixel(&canvas, 29, 16, 240, 150, 150);

    // Border
    bmpFillRect(&canvas, 0, 0, 32, 1, 128, 128, 128);
    bmpFillRect(&canvas, 0, 31, 32, 1, 128, 128, 128);
    bmpFillRect(&canvas, 0, 0, 1, 32, 128, 128, 128);
    bmpFillRect(&canvas, 31, 0, 1, 32, 128, 128, 128);
}


// Image Viewer icon: landscape in a frame
static void iconImgview(void) {
    bmpClear(&canvas, 192, 192, 192);

    // Frame
    bmpFillRect(&canvas, 3, 5, 26, 22, 100, 80, 60);
    bmpFillRect(&canvas, 5, 7, 22, 18, 135, 200, 235);

    // Sun
    bmpFillCircle(&canvas, 21, 11, 3, 255, 220, 50);

    // Mountain
    for (int y = 0; y < 10; y++) {
        int w = y * 2 + 1;
        bmpHLine(&canvas, 15 - y, 15 + y, w, 80, 140, 80);
    }

    // Ground
    bmpFillRect(&canvas, 5, 22, 22, 3, 60, 120, 60);
}


// No-icon placeholder: grey square with red diagonal X
static void iconNoIcon(void) {
    bmpClear(&canvas, 192, 192, 192);

    // Border
    bmpFillRect(&canvas, 0, 0, 32, 1, 128, 128, 128);
    bmpFillRect(&canvas, 0, 31, 32, 1, 128, 128, 128);
    bmpFillRect(&canvas, 0, 0, 1, 32, 128, 128, 128);
    bmpFillRect(&canvas, 31, 0, 1, 32, 128, 128, 128);

    // Red X (two diagonal lines, 2px thick)
    for (int i = 4; i < 28; i++) {
        bmpPixel(&canvas, i, i, 200, 40, 40);
        bmpPixel(&canvas, i + 1, i, 200, 40, 40);
        bmpPixel(&canvas, 31 - i, i, 200, 40, 40);
        bmpPixel(&canvas, 30 - i, i, 200, 40, 40);
    }

    // "?" in the center
    for (int x = 13; x <= 18; x++) { bmpPixel(&canvas, x, 8, 80, 80, 80); }
    bmpPixel(&canvas, 19, 9, 80, 80, 80);
    bmpPixel(&canvas, 19, 10, 80, 80, 80);
    for (int x = 15; x <= 18; x++) { bmpPixel(&canvas, x, 11, 80, 80, 80); }
    bmpPixel(&canvas, 15, 12, 80, 80, 80);
    bmpPixel(&canvas, 15, 13, 80, 80, 80);
    bmpPixel(&canvas, 15, 15, 80, 80, 80);
    bmpPixel(&canvas, 16, 15, 80, 80, 80);
}


// Notepad icon: page with lines
static void iconNotepad(void) {
    bmpClear(&canvas, 192, 192, 192);
    bmpFillRect(&canvas, 6, 3, 20, 26, 255, 255, 240);

    // Border
    bmpHLine(&canvas, 6, 3, 20, 0, 0, 0);
    bmpHLine(&canvas, 6, 28, 20, 0, 0, 0);
    bmpVLine(&canvas, 6, 3, 26, 0, 0, 0);
    bmpVLine(&canvas, 25, 3, 26, 0, 0, 0);

    // Folded corner
    for (int i = 0; i < 5; i++) {
        bmpHLine(&canvas, 21 + i, 3 + i, 5 - i, 200, 200, 180);
    }

    // Text lines
    for (int i = 0; i < 7; i++) {
        int lineW = (i == 3) ? 12 : (i == 6) ? 8 : 16;
        bmpHLine(&canvas, 9, 8 + i * 3, lineW, 0, 0, 128);
    }
}


// Resource editor: box with stacked resource entries
static void iconResedit(void) {
    bmpClear(&canvas, 220, 220, 220);

    // Outer box (document frame)
    bmpFillRect(&canvas, 3, 2, 26, 28, 255, 255, 255);
    bmpFillRect(&canvas, 3, 2, 26, 1, 80, 80, 80);
    bmpFillRect(&canvas, 3, 29, 26, 1, 80, 80, 80);
    bmpFillRect(&canvas, 3, 2, 1, 28, 80, 80, 80);
    bmpFillRect(&canvas, 28, 2, 1, 28, 80, 80, 80);

    // Title bar
    bmpFillRect(&canvas, 4, 3, 24, 4, 0, 0, 128);

    // Resource entry rows (alternating light shading)
    bmpFillRect(&canvas, 4, 8, 24, 4, 240, 240, 255);
    bmpFillRect(&canvas, 4, 12, 24, 1, 180, 180, 200);
    bmpFillRect(&canvas, 4, 13, 24, 4, 255, 255, 255);
    bmpFillRect(&canvas, 4, 17, 24, 1, 180, 180, 200);
    bmpFillRect(&canvas, 4, 18, 24, 4, 240, 240, 255);
    bmpFillRect(&canvas, 4, 22, 24, 1, 180, 180, 200);
    bmpFillRect(&canvas, 4, 23, 24, 4, 255, 255, 255);

    // Type indicator colored dots in each row
    bmpFillCircle(&canvas, 8, 10, 1, 0, 160, 0);      // icon (green)
    bmpFillCircle(&canvas, 8, 15, 1, 0, 0, 200);      // text (blue)
    bmpFillCircle(&canvas, 8, 20, 1, 200, 0, 0);      // binary (red)
    bmpFillCircle(&canvas, 8, 25, 1, 0, 0, 200);      // text (blue)

    // Short "name" bars in each row
    bmpFillRect(&canvas, 11, 9, 10, 2, 60, 60, 60);
    bmpFillRect(&canvas, 11, 14, 14, 2, 60, 60, 60);
    bmpFillRect(&canvas, 11, 19, 8, 2, 60, 60, 60);
    bmpFillRect(&canvas, 11, 24, 12, 2, 60, 60, 60);

    // Border
    bmpFillRect(&canvas, 0, 0, 32, 1, 128, 128, 128);
    bmpFillRect(&canvas, 0, 31, 32, 1, 128, 128, 128);
    bmpFillRect(&canvas, 0, 0, 1, 32, 128, 128, 128);
    bmpFillRect(&canvas, 31, 0, 1, 32, 128, 128, 128);
}


int main(int argc, char **argv) {
    if (argc < 3) {
        fprintf(stderr, "Usage: mkicon <output.bmp> <type>\n");
        fprintf(stderr, "Types: noicon, clock, notepad, cpanel, dvxdemo, imgview, basic, help, iconed, resedit\n");
        return 1;
    }

    const char *path = argv[1];
    const char *type = argv[2];

    if (!bmpInit(&canvas, ICON_W, ICON_H)) {
        fprintf(stderr, "Out of memory\n");
        return 1;
    }

    if (strcmp(type, "noicon") == 0) {
        iconNoIcon();
    } else if (strcmp(type, "clock") == 0) {
        iconClock();
    } else if (strcmp(type, "notepad") == 0) {
        iconNotepad();
    } else if (strcmp(type, "cpanel") == 0) {
        iconCpanel();
    } else if (strcmp(type, "dvxdemo") == 0) {
        iconDvxdemo();
    } else if (strcmp(type, "basic") == 0) {
        iconBasic();
    } else if (strcmp(type, "imgview") == 0) {
        iconImgview();
    } else if (strcmp(type, "help") == 0) {
        iconHelp();
    } else if (strcmp(type, "iconed") == 0) {
        iconIconEd();
    } else if (strcmp(type, "resedit") == 0) {
        iconResedit();
    } else {
        fprintf(stderr, "Unknown icon type: %s\n", type);
        bmpFree(&canvas);
        return 1;
    }

    bmpWrite(&canvas, path);
    bmpFree(&canvas);
    printf("Generated %s (%s)\n", path, type);
    return 0;
}
