// 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)
}
