//+build ignore

// Copyright 2016-2020, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
// goconst linter's warning.
//
// nolint: lll, goconst
package main

import (
	"bytes"
	"fmt"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"text/template"
)

const (
	basePath          = "."
	docsTemplatesPath = basePath + "/templates"
	generatedFileName = basePath + "/packaged.go"
)

var conv = map[string]interface{}{"conv": fmtByteSlice}
var tmpl = template.Must(template.New("").Funcs(conv).Parse(`
	// AUTO-GENERATED FILE! DO NOT EDIT THIS FILE MANUALLY.

	// Copyright 2016-2020, Pulumi Corporation.
	//
	// Licensed under the Apache License, Version 2.0 (the "License");
	// you may not use this file except in compliance with the License.
	// You may obtain a copy of the License at
	//
	//     http://www.apache.org/licenses/LICENSE-2.0
	//
	// Unless required by applicable law or agreed to in writing, software
	// distributed under the License is distributed on an "AS IS" BASIS,
	// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	// See the License for the specific language governing permissions and
	// limitations under the License.

	// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
	// goconst linter's warning.
	//
	// nolint: lll, goconst
	package docs

	func init() {
		packagedTemplates = make(map[string][]byte)
		{{ range $key, $value := . }}
		packagedTemplates["{{ $key }}"] = []byte{ {{ conv $value }} }
		{{ println }}
		{{- end }}
	}
`))

// fmtByteSlice returns a formatted byte string for a given slice of bytes.
// We embed the raw bytes to avoid any formatting errors that can occur due to saving
// raw strings in a file.
func fmtByteSlice(s []byte) string {
	builder := strings.Builder{}

	for _, v := range s {
		builder.WriteString(fmt.Sprintf("%d,", int(v)))
	}

	return builder.String()
}

// main reads files under the templates directory, and builds a map of filename to byte slice.
// Each file's contents are then written to a generated file.
//
// NOTE: Sub-directories are currently not supported.
func main() {
	files, err := ioutil.ReadDir(docsTemplatesPath)
	if err != nil {
		log.Fatalf("Error reading the templates dir: %v", err)
	}

	contents := make(map[string][]byte)
	for _, f := range files {
		if f.IsDir() {
			fmt.Printf("%q is a dir. Skipping...\n", f.Name())
		}
		b, err := ioutil.ReadFile(docsTemplatesPath + "/" + f.Name())
		if err != nil {
			log.Fatalf("Error reading file %s: %v", f.Name(), err)
		}
		if len(b) == 0 {
			fmt.Printf("%q is empty. Skipping...\n", f.Name())
			continue
		}
		contents[f.Name()] = b
	}

	// We overwrite the file every time the `go generate ...` command is run.
	f, err := os.Create(generatedFileName)
	if err != nil {
		log.Fatal("Error creating blob file:", err)
	}
	defer f.Close()

	builder := &bytes.Buffer{}
	if err = tmpl.Execute(builder, contents); err != nil {
		log.Fatal("Error executing template", err)
	}

	data, err := format.Source(builder.Bytes())
	if err != nil {
		log.Fatal("Error formatting generated code", err)
	}

	if err = ioutil.WriteFile(generatedFileName, data, os.ModePerm); err != nil {
		log.Fatal("Error writing file", err)
	}
}
