// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"text/template"

	"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
)

var primitiveTypes = map[fidlgen.PrimitiveSubtype]string{
	fidlgen.Bool:    "bool",
	fidlgen.Int8:    "int8_t",
	fidlgen.Int16:   "int16_t",
	fidlgen.Int32:   "int32_t",
	fidlgen.Int64:   "int64_t",
	fidlgen.Uint8:   "uint8_t",
	fidlgen.Uint16:  "uint16_t",
	fidlgen.Uint32:  "uint32_t",
	fidlgen.Uint64:  "uint64_t",
	fidlgen.Float32: "float",
	fidlgen.Float64: "double",
}

func mustReadJSONIr(filename string) fidlgen.Root {
	root, err := fidlgen.ReadJSONIr(filename)
	if err != nil {
		log.Fatal(err)
	}
	return root
}

func main() {
	cmdlineflags := GetFlags()
	options := make(Options)
	flag.Var(&options, "options",
		"comma-separated list if name=value pairs.")
	flag.Parse()

	if !cmdlineflags.Valid() {
		flag.PrintDefaults()
		os.Exit(1)
	}

	results := GenerateFidl(*cmdlineflags.templatePath,
		cmdlineflags.FidlAmendments().Amend(mustReadJSONIr(*cmdlineflags.jsonPath)),
		cmdlineflags.outputBase,
		options)

	if results != nil {
		log.Printf("Error running generator: %v", results)
		os.Exit(1)
	}
}

// Amendments to be applied to a fidl.Root
type Amendments struct {
	ExcludedDecls []fidlgen.EncodedCompoundIdentifier `json:"exclusions,omitempty"`
}

func (a Amendments) Amend(root fidlgen.Root) fidlgen.Root {
	return a.ApplyExclusions(root)
}

func (a Amendments) ApplyExclusions(root fidlgen.Root) fidlgen.Root {
	if len(a.ExcludedDecls) == 0 {
		return root
	}

	excludeMap := make(map[fidlgen.EncodedCompoundIdentifier]struct{})
	for _, excludedDecl := range a.ExcludedDecls {
		excludeMap[excludedDecl] = struct{}{}
		delete(root.Decls, excludedDecl)
	}

	newConsts := root.Consts[:0]
	for _, element := range root.Consts {
		_, found := excludeMap[element.Name]
		if !found {
			newConsts = append(newConsts, element)
		}
	}
	root.Consts = newConsts

	newEnums := root.Enums[:0]
	for _, element := range root.Enums {
		_, found := excludeMap[element.Name]
		if !found {
			newEnums = append(newEnums, element)
		}
	}
	root.Enums = newEnums

	newProtocols := root.Protocols[:0]
	for _, element := range root.Protocols {
		_, found := excludeMap[element.Name]
		if !found {
			newProtocols = append(newProtocols, element)
		}
	}
	root.Protocols = newProtocols

	newStructs := root.Structs[:0]
	for _, element := range root.Structs {
		_, found := excludeMap[element.Name]
		if !found {
			newStructs = append(newStructs, element)
		}
	}
	root.Structs = newStructs

	newTables := root.Tables[:0]
	for _, element := range root.Tables {
		_, found := excludeMap[element.Name]
		if !found {
			newTables = append(newTables, element)
		}
	}
	root.Tables = newTables

	newUnions := root.Unions[:0]
	for _, element := range root.Unions {
		_, found := excludeMap[element.Name]
		if !found {
			newUnions = append(newUnions, element)
		}
	}
	root.Unions = newUnions

	newDeclOrder := root.DeclOrder[:0]
	for _, element := range root.DeclOrder {
		_, found := excludeMap[element]
		if !found {
			newDeclOrder = append(newDeclOrder, element)
		}
	}
	root.DeclOrder = newDeclOrder

	return root
}

// Root struct passed as the initial 'dot' for the template.
type Root struct {
	fidlgen.Root
	OutputBase      string
	templates       *template.Template
	options         Options
	constsByName    map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Const
	enumsByName     map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Enum
	protocolsByName map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Protocol
	structsByName   map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Struct
	tablesByName    map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Table
	unionsByName    map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Union
	librariesByName map[fidlgen.EncodedLibraryIdentifier]*fidlgen.Library
}

func NewRoot(ir fidlgen.Root, outputBase string, templates *template.Template, options Options) *Root {
	constsByName := make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Const)
	for index, member := range ir.Consts {
		constsByName[member.Name] = &ir.Consts[index]
	}

	enumsByName := make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Enum)
	for index, member := range ir.Enums {
		enumsByName[member.Name] = &ir.Enums[index]
	}

	protocolsByName := make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Protocol)
	for index, member := range ir.Protocols {
		protocolsByName[member.Name] = &ir.Protocols[index]
	}

	// Store all structs in structsByName so that getParams can access them.
	structsByName := make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Struct)
	for index, member := range ir.Structs {
		structsByName[member.Name] = &ir.Structs[index]
	}

	tablesByName := make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Table)
	for index, member := range ir.Tables {
		tablesByName[member.Name] = &ir.Tables[index]
	}

	unionsByName := make(map[fidlgen.EncodedCompoundIdentifier]*fidlgen.Union)
	for index, member := range ir.Unions {
		unionsByName[member.Name] = &ir.Unions[index]
	}

	librariesByName := make(map[fidlgen.EncodedLibraryIdentifier]*fidlgen.Library)
	for index, member := range ir.Libraries {
		librariesByName[member.Name] = &ir.Libraries[index]
	}

	return &Root{
		ir,
		outputBase,
		templates,
		options,
		constsByName,
		enumsByName,
		protocolsByName,
		structsByName,
		tablesByName,
		unionsByName,
		librariesByName,
	}
}

// Applies the specified template to the specified data and writes the output
// to outputPath.
func (root Root) Generate(outputPath string, template string, data interface{}) (string, error) {
	if err := os.MkdirAll(filepath.Dir(outputPath), os.ModePerm); err != nil {
		return "", err
	}

	f, err := os.Create(outputPath)
	if err != nil {
		return "", err
	}
	defer f.Close()

	err = root.templates.ExecuteTemplate(f, template, data)
	if err != nil {
		return "", err
	}

	return "", nil
}

// Returns an output file path with the specified extension.
func (root Root) Output(ext string) string {
	return root.OutputBase + ext
}

// Gets a constant by name.
func (root Root) GetConst(name fidlgen.EncodedCompoundIdentifier) *fidlgen.Const {
	return root.constsByName[name]
}

// Gets an enum by name.
func (root Root) GetEnum(name fidlgen.EncodedCompoundIdentifier) *fidlgen.Enum {
	return root.enumsByName[name]
}

// Gets a protocol by name.
func (root Root) GetProtocol(name fidlgen.EncodedCompoundIdentifier) *fidlgen.Protocol {
	return root.protocolsByName[name]
}

// Gets a struct by name.
func (root Root) GetStruct(name fidlgen.EncodedCompoundIdentifier) *fidlgen.Struct {
	return root.structsByName[name]
}

// Gets a struct by name.
func (root Root) GetTable(name fidlgen.EncodedCompoundIdentifier) *fidlgen.Table {
	return root.tablesByName[name]
}

// Gets a union by name.
func (root Root) GetUnion(name fidlgen.EncodedCompoundIdentifier) *fidlgen.Union {
	return root.unionsByName[name]
}

// Gets a library by name.
func (root Root) GetLibrary(name fidlgen.EncodedLibraryIdentifier) *fidlgen.Library {
	return root.librariesByName[name]
}

// Generates code using the specified template.
func GenerateFidl(templatePath string, ir fidlgen.Root, outputBase *string, options Options) error {
	returnBytes, err := os.ReadFile(templatePath)
	if err != nil {
		log.Fatalf("Error reading from %s: %v", templatePath, err)
	}

	tmpls := template.New("tmpls")

	root := NewRoot(ir, *outputBase, tmpls, options)

	funcMap := template.FuncMap{
		// Gets the decltype for an EncodedCompoundIdentifier.
		"declType": func(eci fidlgen.EncodedCompoundIdentifier) fidlgen.DeclType {
			if root.Name == eci.LibraryName() {
				return root.Decls[eci]
			}
			library := root.GetLibrary(eci.LibraryName())
			return library.Decls[eci].Type
		},
		// Determines if an EncodedCompoundIdentifier refers to a local definition.
		"isLocal": func(eci fidlgen.EncodedCompoundIdentifier) bool {
			return root.Name == eci.LibraryName()
		},
		// Converts an identifier to snake case.
		"toSnakeCase": func(id fidlgen.Identifier) string {
			return fidlgen.ToSnakeCase(string(id))
		},
		// Converts an identifier to upper camel case.
		"toUpperCamelCase": func(id fidlgen.Identifier) string {
			return fidlgen.ToUpperCamelCase(string(id))
		},
		// Converts an identifier to lower camel case.
		"toLowerCamelCase": func(id fidlgen.Identifier) string {
			return fidlgen.ToLowerCamelCase(string(id))
		},
		// Converts an identifier to friendly case.
		"toFriendlyCase": func(id fidlgen.Identifier) string {
			return fidlgen.ToFriendlyCase(string(id))
		},
		// Removes a leading 'k' from an identifier.
		"removeLeadingK": func(id fidlgen.Identifier) string {
			return fidlgen.RemoveLeadingK(string(id))
		},
		// Gets an option value (as a string) by name.
		"getOption": func(name string) string {
			return root.options[name]
		},
		// Gets an option (as an Identifier) by name.
		"getOptionAsIdentifier": func(name string) fidlgen.Identifier {
			return fidlgen.Identifier(root.options[name])
		},
		// Gets an option (as an EncodedLibraryIdentifier) by name.
		"getOptionAsEncodedLibraryIdentifier": func(name string) fidlgen.EncodedLibraryIdentifier {
			return fidlgen.EncodedLibraryIdentifier(root.options[name])
		},
		// Gets an option (as an EncodedCompoundIdentifier) by name.
		"getOptionAsEncodedCompoundIdentifier": func(name string) fidlgen.EncodedCompoundIdentifier {
			return fidlgen.EncodedCompoundIdentifier(root.options[name])
		},
		// Returns the template executed
		"execTmpl": func(template string, data interface{}) (string, error) {
			buffer := &bytes.Buffer{}
			err = root.templates.ExecuteTemplate(buffer, template, data)
			return buffer.String(), err
		},
		// Determines if a protocol is discoverable.
		"isDiscoverable": func(i fidlgen.Protocol) bool {
			return i.HasAttribute("discoverable")
		},
		// Converts a primitive subtype to its C equivalent.
		"toCType": func(p fidlgen.PrimitiveSubtype) string {
			return primitiveTypes[p]
		},
		// Gets a flat list of parameters for a request/response payload.
		"getParams": func(t *fidlgen.Type) []fidlgen.StructMember {
			if t == nil {
				return nil
			}
			if t.Kind != fidlgen.IdentifierType {
				panic(fmt.Sprintf("expected IdentifierType, got %s", t.Kind))
			}
			if s, ok := root.structsByName[t.Identifier]; ok {
				return s.Members
			}
			panic(fmt.Sprintf("%s: fidlmerge only supports struct requests/responses", t.Identifier))
		},
	}

	template.Must(tmpls.Funcs(funcMap).Parse(string(returnBytes[:])))

	err = tmpls.ExecuteTemplate(os.Stdout, "Main", root)
	if err != nil {
		return err
	}

	return nil
}
