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

package source

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

type DeclFile struct {
	Path string `yaml:"path" json:"path"`
}

func NewDeclFile() *DeclFile {
	return &DeclFile{}
}

func init() {
	SourceTypes.Register([]string{"decl"}, func(u *url.URL) DocSource {
		t := NewDeclFile()
		t.Path,_ = filepath.Abs(filepath.Join(u.Hostname(), u.RequestURI()))
		return t
	})

	SourceTypes.Register([]string{"yaml","yml","yaml.gz","yml.gz"}, func(u *url.URL) DocSource {
		t := NewDeclFile()
		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)
		}
		return t
	})

}


func (d *DeclFile) Type() string { return "decl" }

func (d *DeclFile) ExtractResources(filter ResourceSelector) ([]*resource.Document, error) {
	documents := make([]*resource.Document, 0, 100)
	//documents = append(documents, resource.NewDocument())

	GzipFileName := regexp.MustCompile(`^.*\.gz$`)
		
	file, fileErr := os.Open(d.Path)
	if fileErr != nil {
		return documents, fileErr
	}
	var fileReader io.Reader

	if GzipFileName.FindString(d.Path) == d.Path {
		slog.Info("decompressing gzip", "path", d.Path)
		zr, err := gzip.NewReader(file)
		if err != nil {
			return documents, err
		}
		fileReader = zr
	} else {
		fileReader = file
	}
	decoder := resource.NewYAMLDecoder(fileReader)
	slog.Info("ExtractResources()", "documents", documents)  
	index := 0
	for {
		doc := resource.NewDocument()
		e := decoder.Decode(doc)
		if errors.Is(e, io.EOF) {
			break
		}
		if e != nil {
			return documents, e
		}
		slog.Info("ExtractResources()", "res", doc.ResourceDecls[0].Attributes)  
		if validationErr := doc.Validate(); validationErr != nil {
			return documents, validationErr
		}
		documents = append(documents, doc)
		index++
	}
	return documents, nil
}
