// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Package template wraps the golang "text/template" package to provide an
// enhanced template generator.
package template

import (
	"fmt"
	"io"
	"path/filepath"
	"reflect"
	"strings"
	"text/template"

	"dawn.googlesource.com/dawn/tools/src/container"
	"dawn.googlesource.com/dawn/tools/src/fileutils"
	"dawn.googlesource.com/dawn/tools/src/oswrapper"
	"dawn.googlesource.com/dawn/tools/src/text"
	"dawn.googlesource.com/dawn/tools/src/transform"
)

// The template function binding table
type Functions = template.FuncMap

type Template struct {
	name    string
	content string
}

// FromFile loads the template file at path using the provided FilesystemReader
// and builds and returns a Template using the file content
func FromFile(path string, fs oswrapper.FilesystemReader) (*Template, error) {
	content, err := fs.ReadFile(path)
	if err != nil {
		return nil, err
	}
	return FromString(path, string(content)), nil
}

// FromString returns a Template with the given name from content
func FromString(name, content string) *Template {
	return &Template{name: name, content: content}
}

// Run executes the template tmpl, writing the output to w.
// funcs are the functions provided to the template.
// See https://golang.org/pkg/text/template/ for documentation on the template
// syntax.
func (t *Template) Run(w io.Writer, data any, funcs Functions) error {
	g := generator{
		template: template.New(t.name),
	}

	globals := newMap()

	// Add a bunch of generic useful functions
	g.funcs = Functions{
		"Append":     listAppend,
		"Concat":     listConcat,
		"Contains":   strings.Contains,
		"Eval":       g.eval,
		"Globals":    func() Map { return globals },
		"HasPrefix":  strings.HasPrefix,
		"HasSuffix":  strings.HasSuffix,
		"Import":     g.importTmpl,
		"Index":      index,
		"Is":         is,
		"Iterate":    iterate,
		"Join":       strings.Join,
		"List":       list,
		"Map":        newMap,
		"PascalCase": text.PascalCase,
		"Repeat":     strings.Repeat,
		"Replace":    replace,
		"SortUnique": listSortUnique,
		"Split":      strings.Split,
		"Sum":        sum,
		"Title":      strings.Title,
		"ToLower":    strings.ToLower,
		"ToUpper":    strings.ToUpper,
		"TrimLeft":   strings.TrimLeft,
		"TrimPrefix": strings.TrimPrefix,
		"TrimRight":  strings.TrimRight,
		"TrimSuffix": strings.TrimSuffix,
		"Error":      func(err string, args ...any) string { panic(fmt.Errorf(err, args...)) },
	}

	// Append custom functions
	for name, fn := range funcs {
		g.funcs[name] = fn
	}

	if err := g.bindAndParse(g.template, t.content); err != nil {
		return err
	}

	return g.template.Execute(w, data)
}

type generator struct {
	template *template.Template
	funcs    Functions
}

func (g *generator) bindAndParse(t *template.Template, tmpl string) error {
	_, err := t.
		Funcs(g.funcs).
		Option("missingkey=error").
		Parse(tmpl)
	return err
}

// eval executes the sub-template with the given name and argument, returning
// the generated output
func (g *generator) eval(template string, args ...any) (string, error) {
	target := g.template.Lookup(template)
	if target == nil {
		return "", fmt.Errorf("template '%v' not found", template)
	}
	sb := strings.Builder{}

	var err error
	if len(args) == 1 {
		err = target.Execute(&sb, args[0])
	} else {
		m := newMap()
		if len(args)%2 != 0 {
			return "", fmt.Errorf("Eval expects a single argument or list name-value pairs")
		}
		for i := 0; i < len(args); i += 2 {
			name, ok := args[i].(string)
			if !ok {
				return "", fmt.Errorf("Eval argument %v is not a string", i)
			}
			m.Put(name, args[i+1])
		}
		err = target.Execute(&sb, m)
	}

	if err != nil {
		return "", fmt.Errorf("while evaluating '%v' with args '%v'\n%v", template, args, err)
	}
	return sb.String(), nil
}

// TODO(crbug.com/344014313): Add unittest coverage.
// importTmpl parses the template at the given project-relative path, merging
// the template definitions into the global namespace.
// Note: The body of the template is not executed.
func (g *generator) importTmpl(path string) (string, error) {
	// TODO(crbug.com/344014313): Use a properly injected interface instead of
	// hard-coding the real wrapper. We cannot easily take it as an argument due
	// to "tools/src/cmd/gen/main.go --check-stale" complaining about a
	// mismatched number of arguments despite all relevant Go code being updated.
	fsReader := oswrapper.GetRealOSWrapper()
	if strings.Contains(path, "..") {
		return "", fmt.Errorf("import path must not contain '..'")
	}
	path = filepath.Join(fileutils.DawnRoot(fsReader), path)
	data, err := fsReader.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("failed to open '%v': %w", path, err)
	}
	t := g.template.New("")
	if err := g.bindAndParse(t, string(data)); err != nil {
		return "", fmt.Errorf("failed to parse '%v': %w", path, err)
	}
	if err := t.Execute(io.Discard, nil); err != nil {
		return "", fmt.Errorf("failed to execute '%v': %w", path, err)
	}
	return "", nil
}

// Map is a simple generic key-value map, which can be used in the template
type Map map[any]any

func newMap() Map { return Map{} }

// Put adds the key-value pair into the map.
// Put always returns an empty string so nothing is printed in the template.
func (m Map) Put(key, value any) string {
	m[key] = value
	return ""
}

// Get looks up and returns the value with the given key. If the map does not
// contain the given key, then nil is returned.
func (m Map) Get(key any) any {
	return m[key]
}

// is returns true if the type of object is ty
func is(object any, ty string) bool {
	if object == nil {
		return false
	}
	val := reflect.ValueOf(object)
	for val.Kind() == reflect.Pointer {
		val = val.Elem()
	}
	return ty == val.Type().Name()
}

// sum returns the sum of provided values
func sum(numbers ...int) int {
	n := 0
	for _, i := range numbers {
		n += i
	}
	return n
}

// iterate returns a slice of length 'n', with each element equal to its index.
// Useful for: {{- range Iterate $n -}}<this will be looped $n times>{{end}}
func iterate(n int) []int {
	out := make([]int, n)
	for i := range out {
		out[i] = i
	}
	return out
}

// listAppend returns the slice list with items appended
func listAppend(list any, items ...any) any {
	itemValues := transform.SliceNoErr(items, reflect.ValueOf)
	return reflect.Append(reflect.ValueOf(list), itemValues...).Interface()
}

// listConcat returns a slice formed from concatenating all the elements of all
// the slice arguments
func listConcat(firstList any, otherLists ...any) any {
	out := reflect.ValueOf(firstList)
	for _, list := range otherLists {
		out = reflect.AppendSlice(out, reflect.ValueOf(list))
	}
	return out.Interface()
}

// listSortUnique returns items sorted by the string-formatted value of each element, with
// items with the same strings deduplicated.
func listSortUnique(items []any) []any {
	m := make(container.Map[string, any], len(items))
	for _, item := range items {
		m.Add(fmt.Sprint(item), item)
	}
	return m.Values()
}

// list returns a new slice of elements from the argument list
// Useful for: {{- range List "a" "b" "c" -}}{{.}}{{end}}
func list(elements ...any) []any { return elements }

func index(obj any, indices ...any) (any, error) {
	v := reflect.ValueOf(obj)
	for _, idx := range indices {
		for v.Kind() == reflect.Interface || v.Kind() == reflect.Pointer {
			v = v.Elem()
		}
		if !v.IsValid() || v.IsZero() || v.IsNil() {
			return nil, nil
		}
		switch v.Kind() {
		case reflect.Array, reflect.Slice:
			v = v.Index(idx.(int))
		case reflect.Map:
			v = v.MapIndex(reflect.ValueOf(idx))
		default:
			return nil, fmt.Errorf("cannot index %T (%v)", obj, v.Kind())
		}
	}
	if !v.IsValid() || v.IsZero() || v.IsNil() {
		return nil, nil
	}
	return v.Interface(), nil
}

func replace(s string, oldNew ...string) string {
	return strings.NewReplacer(oldNew...).Replace(s)
}
