package main

import (
	"encoding/binary"
	"fmt"
	"image"
	"image/png"
	"os"
	"path/filepath"

	"golang.org/x/image/draw"
)

func main() {
	in := filepath.Join("assets", "navis-icon.png")
	out := filepath.Join("assets", "navis.ico")
	f, err := os.Open(in)
	if err != nil {
		fatal(err)
	}
	defer f.Close()
	src, err := png.Decode(f)
	if err != nil {
		fatal(err)
	}

	sizes := []int{16, 32, 48, 64, 128, 256}
	type entry struct {
		size int
		png  []byte
	}
	var entries []entry
	for _, size := range sizes {
		dst := image.NewRGBA(image.Rect(0, 0, size, size))
		draw.CatmullRom.Scale(dst, dst.Bounds(), src, src.Bounds(), draw.Over, nil)
		tmp := filepath.Join(os.TempDir(), fmt.Sprintf("navis-%d.png", size))
		tf, err := os.Create(tmp)
		if err != nil {
			fatal(err)
		}
		if err := png.Encode(tf, dst); err != nil {
			tf.Close()
			fatal(err)
		}
		tf.Close()
		b, err := os.ReadFile(tmp)
		_ = os.Remove(tmp)
		if err != nil {
			fatal(err)
		}
		entries = append(entries, entry{size: size, png: b})
	}

	var blob []byte
	offset := 6 + 16*len(entries)
	for _, e := range entries {
		blob = append(blob, e.png...)
	}

	buf := make([]byte, offset+len(blob))
	binary.LittleEndian.PutUint16(buf[0:], 0) // reserved
	binary.LittleEndian.PutUint16(buf[2:], 1) // icon
	binary.LittleEndian.PutUint16(buf[4:], uint16(len(entries)))
	dataOff := offset
	for i, e := range entries {
		dir := buf[6+i*16:]
		w, h := e.size, e.size
		if w >= 256 {
			dir[0], dir[1] = 0, 0
		} else {
			dir[0], dir[1] = byte(w), byte(h)
		}
		dir[2] = 0 // colors
		dir[3] = 0
		binary.LittleEndian.PutUint16(dir[4:], 1) // planes
		binary.LittleEndian.PutUint16(dir[6:], 32)
		binary.LittleEndian.PutUint32(dir[8:], uint32(len(e.png)))
		binary.LittleEndian.PutUint32(dir[12:], uint32(dataOff))
		copy(buf[dataOff:], e.png)
		dataOff += len(e.png)
	}
	if err := os.WriteFile(out, buf, 0o644); err != nil {
		fatal(err)
	}
	fmt.Println("wrote", out)
}

func fatal(err error) {
	fmt.Fprintln(os.Stderr, err)
	os.Exit(1)
}
