// mkicon.swift — draws Lid Creak.app's icon with CoreGraphics. No assets needed.
import AppKit

let canvas: CGFloat = 1024

func drawIcon(size: CGFloat) -> NSBitmapImageRep {
    let rep = NSBitmapImageRep(bitmapDataPlanes: nil,
                              pixelsWide: Int(size), pixelsHigh: Int(size),
                              bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true,
                              isPlanar: false, colorSpaceName: .deviceRGB,
                              bytesPerRow: 0, bitsPerPixel: 0)!
    rep.size = NSSize(width: size, height: size)
    NSGraphicsContext.saveGraphicsState()
    NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep)
    guard let ctx = NSGraphicsContext.current?.cgContext else { return rep }

    let s = size / canvas
    ctx.scaleBy(x: s, y: s)
    ctx.setAllowsAntialiasing(true)

    // rounded-square background
    let bg = CGPath(roundedRect: CGRect(x: 112, y: 112, width: 800, height: 800),
                    cornerWidth: 190, cornerHeight: 190, transform: nil)
    ctx.saveGState()
    ctx.addPath(bg)
    ctx.clip()
    let top = CGColor(red: 0.22, green: 0.26, blue: 0.34, alpha: 1)
    let bottom = CGColor(red: 0.07, green: 0.09, blue: 0.13, alpha: 1)
    if let g = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(),
                          colors: [top, bottom] as CFArray, locations: [0, 1]) {
        ctx.drawLinearGradient(g, start: CGPoint(x: 512, y: 912),
                               end: CGPoint(x: 512, y: 112), options: [])
    }
    ctx.restoreGState()

    // faint lid line so the icon says "lid", not just "speaker"
    ctx.saveGState()
    ctx.setStrokeColor(CGColor(red: 1, green: 1, blue: 1, alpha: 0.16))
    ctx.setLineWidth(16)
    ctx.setLineCap(.round)
    ctx.move(to: CGPoint(x: 262, y: 300))
    ctx.addLine(to: CGPoint(x: 762, y: 300))
    ctx.strokePath()
    ctx.restoreGState()

    // speaker
    let ink = CGColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1)
    ctx.setFillColor(ink)
    let body = CGPath(roundedRect: CGRect(x: 250, y: 434, width: 92, height: 156),
                      cornerWidth: 16, cornerHeight: 16, transform: nil)
    ctx.addPath(body)
    ctx.fillPath()

    ctx.beginPath()
    ctx.move(to: CGPoint(x: 342, y: 512))
    ctx.addLine(to: CGPoint(x: 512, y: 660))
    ctx.addLine(to: CGPoint(x: 512, y: 364))
    ctx.closePath()
    ctx.setLineJoin(.round)
    ctx.fillPath()

    // sound waves
    let center = CGPoint(x: 540, y: 512)
    let waves: [(CGFloat, CGFloat, CGColor)] = [
        (96, 0.95, CGColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 0.95)),
        (170, 0.62, CGColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 0.62)),
        (244, 0.34, CGColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 0.34)),
    ]
    ctx.setLineCap(.round)
    ctx.setLineWidth(34)
    for (r, _, c) in waves {
        ctx.setStrokeColor(c)
        ctx.beginPath()
        ctx.addArc(center: center, radius: r,
                   startAngle: -58 * .pi / 180, endAngle: 58 * .pi / 180, clockwise: false)
        ctx.strokePath()
    }
    _ = waves.map { $0.1 }

    NSGraphicsContext.restoreGraphicsState()
    return rep
}

let outDir = CommandLine.arguments.count > 1 ? CommandLine.arguments[1] : "LidCreak.iconset"
try? FileManager.default.createDirectory(atPath: outDir, withIntermediateDirectories: true)

let entries: [(String, CGFloat)] = [
    ("icon_16x16.png", 16), ("icon_16x16@2x.png", 32),
    ("icon_32x32.png", 32), ("icon_32x32@2x.png", 64),
    ("icon_128x128.png", 128), ("icon_128x128@2x.png", 256),
    ("icon_256x256.png", 256), ("icon_256x256@2x.png", 512),
    ("icon_512x512.png", 512), ("icon_512x512@2x.png", 1024),
]
var written = 0
for (name, px) in entries {
    let rep = drawIcon(size: px)
    guard let png = rep.representation(using: .png, properties: [:]) else { continue }
    let path = outDir + "/" + name
    do {
        try png.write(to: URL(fileURLWithPath: path))
        written += 1
    } catch {
        print("failed \(name): \(error)")
        exit(1)
    }
}
print("wrote \(written)/\(entries.count) icon sizes into \(outDir)")
