package main

import (
	"fmt"
	"html"
	"log"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"text/template"

    {{- range $key, $value := .}}
    pkg{{$key}} "{{$value}}"
    {{- end}})

type ConfigField struct {
	Name         string
	DefaultValue string
	Type         string
	Description  string
}

func main() {
fmt.Println("Generating documentation for environment variables:")
content, err := os.ReadFile("../../docs/templates/CONFIGURATION.tmpl")
if err != nil {
    log.Fatal(err)
}
replacer := strings.NewReplacer(
		"github.com/owncloud/ocis/v2/services/", "",
		"/pkg/config/defaults", "",
	)
var fields []ConfigField
var targetFile *os.File
tpl := template.Must(template.New("").Parse(string(content)))

m := map[string]interface{}{
{{- range $key, $value := .}}
	"{{$value}}": *pkg{{$key}}.FullDefaultConfig(),
{{- end }}
}

    targetFolder := "../../docs/services/_includes/"
    for pkg, conf := range m {
	fields = GetAnnotatedVariables(conf)
	if len(fields) > 0 {
	fmt.Printf("... %s\n", pkg)
		targetFile, err = os.Create(filepath.Join(targetFolder, replacer.Replace(pkg) + "_configvars.md"))
		if err != nil {
			log.Fatalf("Failed to create target file: %s", err)
		}
		defer targetFile.Close()
		if err := tpl.Execute(targetFile, fields); err != nil {
			log.Fatalf("Failed to execute template: %s", err)
		}
	}
    }
	fmt.Println("done")
}

func GetAnnotatedVariables(s interface{}) []ConfigField {
	t := reflect.TypeOf(s)
	v := reflect.ValueOf(s)

	var fields []ConfigField
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		value := v.Field(i)

		switch value.Kind() {
		default:
			desc := field.Tag.Get("desc")
			env, ok := field.Tag.Lookup("env")
			if !ok {
				continue
			}
			v := fmt.Sprintf("%v", value.Interface())
			typeName := value.Type().Name()
			if typeName == "" {
				typeName = value.Type().String()
			}
			fields = append(fields, ConfigField{Name: strings.ReplaceAll(env, ";", "<br/>"), DefaultValue: html.EscapeString(strings.Replace(v, "|", "\\|", -1)), Description: desc, Type: typeName})
		case reflect.Ptr:
			// PolicySelectors in the Proxy are being skipped atm
			// they are not configurable via env vars, if that changes
			// they are probably added to the Sanitize() function
			// and this should not be an issue then
			if !value.IsZero() && value.Elem().CanInterface() {
				fields = append(fields, GetAnnotatedVariables(value.Elem().Interface())...)
			}
		case reflect.Struct:
			fields = append(fields, GetAnnotatedVariables(value.Interface())...)
		}
	}
	return fields
}
