package main

import (
	"archive/tar"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
)

func rmTempFile(f *os.File) {
	f.Close()
	if err := os.Remove(f.Name()); err != nil {
		log.Print("failed to remove ", f.Name(), ": ", err)
	}
}

func buildBootTar(out io.Writer, ctx *renderContext) (err error) {
	arch := tar.NewWriter(out)
	defer arch.Close()

	archAdd := func(path string, ba []byte) (err error) {
		err = arch.WriteHeader(&tar.Header{Name: path, Size: int64(len(ba))})
		if err != nil {
			return
		}
		_, err = arch.Write(ba)
		return
	}

	// config
	cfgBytes, cfg, err := ctx.Config()
	if err != nil {
		return err
	}

	archAdd("config.yaml", cfgBytes)

	// add "current" elements
	type distCopy struct {
		Src []string
		Dst string
	}

	// kernel and initrd
	copies := []distCopy{
		{Src: []string{"kernels", ctx.Host.Kernel}, Dst: "current/vmlinuz"},
		{Src: []string{"initrd", ctx.Host.Initrd}, Dst: "current/initrd"},
	}

	// layers
	for _, layer := range cfg.Layers {
		layerVersion := ctx.Host.Versions[layer]
		if layerVersion == "" {
			return fmt.Errorf("layer %q not mapped to a version", layer)
		}

		copies = append(copies,
			distCopy{
				Src: []string{"layers", layer, layerVersion},
				Dst: filepath.Join("current", "layers", layer+".fs"),
			})
	}

	for _, copy := range copies {
		outPath, err := ctx.distFetch(copy.Src...)
		if err != nil {
			return err
		}

		f, err := os.Open(outPath)
		if err != nil {
			return err
		}

		defer f.Close()

		stat, err := f.Stat()
		if err != nil {
			return err
		}

		if err = arch.WriteHeader(&tar.Header{
			Name: copy.Dst,
			Size: stat.Size(),
		}); err != nil {
			return err
		}

		_, err = io.Copy(arch, f)
		if err != nil {
			return err
		}
	}

	return nil
}
