// 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"
	"log"
	"os"
	"path/filepath"
	"text/template"

	"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 interface {
	Header() string
	Source() string
	TestBase() 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(cpp.MergeFuncMaps(cpp.CommonTemplateFuncs,
		template.FuncMap{
			"IncludeDomainObjects": func() bool {
				return mode == Monolithic ||
					mode == OnlyGenerateDomainObjects
			},
			"IncludeProxiesAndStubs": func() bool { return mode == Monolithic },
		}))

	// 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 := fidlgen.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 fidlgen.Root, opts Config, clangFormatPath string) error {
	primaryHeader, err := cpp.CalcPrimaryHeader(opts, fidl.Name.Parts())
	if err != nil {
		log.Fatal(err)
	}
	tree := cpp.CompileHL(fidl, cpp.HeaderOptions{
		PrimaryHeader: primaryHeader,
		IncludeStem:   opts.IncludeStem(),
	})

	if err := os.MkdirAll(filepath.Dir(opts.Header()), os.ModePerm); err != nil {
		return err
	}
	err = gen.generateFile(opts.Header(), clangFormatPath, func(w io.Writer) error {
		return gen.GenerateHeader(w, tree)
	})
	if err != nil {
		return err
	}

	if err := os.MkdirAll(filepath.Dir(opts.Source()), os.ModePerm); err != nil {
		return err
	}
	err = gen.generateFile(opts.Source(), 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
	}

	if err := os.MkdirAll(filepath.Dir(opts.TestBase()), os.ModePerm); err != nil {
		return err
	}
	return gen.generateFile(opts.TestBase(), clangFormatPath, func(w io.Writer) error {
		return gen.GenerateTestBase(w, tree)
	})
}
