// 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 codegen

import (
	"io"
	"os"
	"path/filepath"
	"text/template"

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

// CodeGenerationMode controls which subset of bindings code to generate.
type CodeGenerationMode int

const (
	_ CodeGenerationMode = iota

	// Monolithic generates all of HLCPP bindings in one header/source pair.
	Monolithic

	// OnlyGenerateDomainObjects generates only the domain objects
	// (structs, tables, unions, enums, bits, request/response codecs, etc.)
	OnlyGenerateDomainObjects

	// TODO(fxbug.dev/64093): Add a third generation mode which only generates
	// proxies and stubs.
)

// Config is the configuration data passed to the HLCPP generator.
type Config struct {
	// The base file name for files generated by this generator.
	OutputBase string

	// The directory to which C and C++ includes should be relative.
	IncludeBase string

	// The path suffix after the library path when referencing includes.
	IncludeStem string
}

type FidlGenerator struct {
	tmpls *template.Template
	CodeGenerationMode
}

func NewFidlGenerator(mode CodeGenerationMode) *FidlGenerator {
	tmpls := template.New("CPPTemplates").Funcs(template.FuncMap{
		"Kinds":                  func() interface{} { return cpp.Kinds },
		"Eq":                     func(a interface{}, b interface{}) bool { return a == b },
		"IncludeDomainObjects":   func() bool { return mode == Monolithic || mode == OnlyGenerateDomainObjects },
		"IncludeProxiesAndStubs": func() bool { return mode == Monolithic },
		"EnsureNamespace":        cpp.EnsureNamespace,
		"PushNamespace":          cpp.PushNamespace,
		"PopNamespace":           cpp.PopNamespace,
		"EndOfFile":              cpp.EndOfFile,
		"UseNatural":             cpp.UseNatural,
		"UseWire":                cpp.UseWire,
	})

	// Natural types templates
	template.Must(tmpls.Parse(bitsTemplate))
	template.Must(tmpls.Parse(constTemplate))
	template.Must(tmpls.Parse(enumTemplate))
	template.Must(tmpls.Parse(protocolTemplateNaturalTypes))
	template.Must(tmpls.Parse(structTemplate))
	template.Must(tmpls.Parse(tableTemplate))
	template.Must(tmpls.Parse(unionTemplate))

	// Proxies and stubs templates
	template.Must(tmpls.Parse(protocolTemplateProxiesAndStubs))
	template.Must(tmpls.Parse(serviceTemplate))

	// File templates
	template.Must(tmpls.Parse(headerTemplate))
	template.Must(tmpls.Parse(implementationTemplate))
	template.Must(tmpls.Parse(testBaseTemplate))
	return &FidlGenerator{
		tmpls:              tmpls,
		CodeGenerationMode: mode,
	}
}

// GenerateHeader generates the C++ bindings header.
func (gen *FidlGenerator) GenerateHeader(wr io.Writer, tree cpp.Root) error {
	return gen.tmpls.ExecuteTemplate(wr, "Header", tree)
}

// GenerateSource generates the C++ bindings source, i.e. implementation.
func (gen *FidlGenerator) GenerateSource(wr io.Writer, tree cpp.Root) error {
	return gen.tmpls.ExecuteTemplate(wr, "Implementation", tree)
}

func (gen *FidlGenerator) GenerateTestBase(wr io.Writer, tree cpp.Root) error {
	return gen.tmpls.ExecuteTemplate(wr, "TestBase", tree)
}

func (gen *FidlGenerator) generateFile(filepath, clangFormatPath string, generate func(w io.Writer) error) error {
	file, err := fidl.NewLazyWriter(filepath)
	if err != nil {
		return err
	}

	formatterPipe, err := cpp.NewClangFormatter(clangFormatPath).FormatPipe(file)
	if err != nil {
		return err
	}

	if err := generate(formatterPipe); err != nil {
		return err
	}

	return formatterPipe.Close()
}

// GenerateFidl generates all files required for the C++ bindings.
func (gen *FidlGenerator) GenerateFidl(fidl fidl.Root, config *Config, clangFormatPath string) error {
	tree := cpp.CompileHL(fidl)

	relStem, err := filepath.Rel(config.IncludeBase, config.OutputBase)
	if err != nil {
		return err
	}
	tree.PrimaryHeader = relStem + ".h"
	tree.IncludeStem = config.IncludeStem

	headerPath := config.OutputBase + ".h"
	sourcePath := config.OutputBase + ".cc"
	testBasePath := config.OutputBase + "_test_base.h"

	if err := os.MkdirAll(filepath.Dir(config.OutputBase), os.ModePerm); err != nil {
		return err
	}

	err = gen.generateFile(headerPath, clangFormatPath, func(w io.Writer) error {
		return gen.GenerateHeader(w, tree)
	})
	if err != nil {
		return err
	}

	err = gen.generateFile(sourcePath, clangFormatPath, func(w io.Writer) error {
		return gen.GenerateSource(w, tree)
	})
	if err != nil {
		return err
	}

	if gen.CodeGenerationMode == OnlyGenerateDomainObjects {
		// TestBase header only applies to protocols definitions.
		return nil
	}

	return gen.generateFile(testBasePath, clangFormatPath, func(w io.Writer) error {
		return gen.GenerateTestBase(w, tree)
	})
}
