package ora

import (
	"archive/zip"
	"encoding/xml"
	"os"
)

type ORALayer struct {
	Name     string
	Filename string // relative to data/
	Visible  bool
	Opacity  float32 // 0..1
	Blend    string  // svg:src-over, svg:multiply, etc
}

type imageXML struct {
	XMLName xml.Name `xml:"image"`
	W       int      `xml:"w,attr"`
	H       int      `xml:"h,attr"`
	Stack   stackXML `xml:"stack"`
}

type stackXML struct {
	Layers []layerXML `xml:"layer"`
}

type layerXML struct {
	Name       string  `xml:"name,attr"`
	Src        string  `xml:"src,attr"`
	Opacity    float32 `xml:"opacity,attr"`
	Visible    bool    `xml:"visible,attr"`
	Composite  string  `xml:"composite-op,attr"`
}

func WriteORA(
	outPath string,
	width, height int,
	layers []ORALayer,
	pngLoader func(name string) ([]byte, error),
) error {

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

	zw := zip.NewWriter(f)
	defer zw.Close()

	// 1. mimetype (must be first, uncompressed)
	h := &zip.FileHeader{
		Name:   "mimetype",
		Method: zip.Store,
	}
	w, _ := zw.CreateHeader(h)
	w.Write([]byte("image/openraster"))

	// 2. stack.xml
	var stack []layerXML
	for _, l := range layers {
		stack = append(stack, layerXML{
			Name:      l.Name,
			Src:       "data/" + l.Filename,
			Opacity:   l.Opacity,
			Visible:   l.Visible,
			Composite: l.Blend,
		})
	}

	img := imageXML{
		W: width,
		H: height,
		Stack: stackXML{
			Layers: stack,
		},
	}

	xmlBytes, _ := xml.MarshalIndent(img, "", "  ")
	xmlBuf := append([]byte(xml.Header), xmlBytes...)

	w, _ = zw.Create("stack.xml")
	w.Write(xmlBuf)

	// 3. layer PNGs
	for _, l := range layers {
		data, err := pngLoader(l.Filename)
		if err != nil {
			return err
		}
		w, _ = zw.Create("data/" + l.Filename)
		w.Write(data)
	}

	return nil
}

