// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.

package target

import (
_	"context"
_	"encoding/json"
_	"fmt"
_	"gopkg.in/yaml.v3"
	"net/url"
	"path/filepath"
	"decl/internal/resource"
	"compress/gzip"
	"archive/tar"
_	"regexp"
	"os"
	"io"
	"log"
	"log/slog"
)

type Tar struct {
	Path string `yaml:"path" json:"path"`
	Gzip bool `yaml:"gzip" json:"gzip"`
}

func NewTar() *Tar {
	return &Tar{ Gzip: false }
}

func init() {
	TargetTypes.Register([]string{"tar"}, func(u *url.URL) DocTarget {
		t := NewTar()
		t.Path,_ = filepath.Abs(filepath.Join(u.Hostname(), u.Path))
		return t
	})

	TargetTypes.Register([]string{"tar.gz", "tgz"}, func(u *url.URL) DocTarget {
		t := NewTar()
		if u.Scheme == "file" {
			fileAbsolutePath, _ := filepath.Abs(filepath.Join(u.Hostname(), u.RequestURI()))
			t.Path = fileAbsolutePath
		} else {
			t.Path = filepath.Join(u.Hostname(), u.Path)
		}
		t.Gzip = true
		return t
	})

}


func (t *Tar) Type() string { return "tar" }

func (t *Tar) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) error {
	file, fileErr := os.Create(t.Path)
	if fileErr != nil {
		return fileErr
	}
	var fileWriter io.WriteCloser
	if t.Gzip {
		fileWriter = gzip.NewWriter(file)
	} else {
		fileWriter = file
	}

	tarWriter := tar.NewWriter(fileWriter)
	defer func() {
		tarWriter.Close()
		fileWriter.Close()
		file.Close()
	}()

	for _,document := range documents {
		for _,res := range document.Filter(func(d *resource.Declaration) bool {
			return d.Type == "file"
		}) {
			var f *resource.File = res.Attributes.(*resource.File)
			slog.Info("Tar.EmitResources", "file", f)
			hdr, fiErr := tar.FileInfoHeader(f.FileInfo(), "")
			slog.Info("Tar.EmitResources", "header", hdr, "err", fiErr)
			if err := tarWriter.WriteHeader(hdr); err != nil {
				log.Fatal(err)
			}
			if _, err := tarWriter.Write([]byte(f.Content)); err != nil {
				log.Fatal(err)
			}
		}
	}
	return nil
}
