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

type Generator struct {
	tmpls *template.Template
}

func NewGenerator() *Generator {
	tmpls := template.New("RustTemplates")
	template.Must(tmpls.Parse(sourceFileTmpl))
	template.Must(tmpls.Parse(bitsTmpl))
	template.Must(tmpls.Parse(constTmpl))
	template.Must(tmpls.Parse(enumTmpl))
	template.Must(tmpls.Parse(protocolTmpl))
	template.Must(tmpls.Parse(handleMetadataWrapperTmpl))
	template.Must(tmpls.Parse(serviceTmpl))
	template.Must(tmpls.Parse(structTmpl))
	template.Must(tmpls.Parse(unionTmpl))
	template.Must(tmpls.Parse(tableTmpl))
	template.Must(tmpls.Parse(resultTmpl))
	template.Must(tmpls.Parse(bitsTmpl))
	return &Generator{
		tmpls: tmpls,
	}
}

func (gen *Generator) GenerateImpl(wr io.Writer, tree Root) error {
	return gen.tmpls.ExecuteTemplate(wr, "GenerateSourceFile", tree)
}

func (gen *Generator) GenerateFidl(ir fidl.Root, outputFilename, rustfmtPath, rustfmtConfigPath string) error {
	tree := Compile(ir)
	if err := os.MkdirAll(filepath.Dir(outputFilename), os.ModePerm); err != nil {
		return err
	}

	generated, err := os.Create(outputFilename)
	if err != nil {
		return err
	}

	var args []string
	if rustfmtConfigPath != "" {
		args = append(args, "--config-path", rustfmtConfigPath)
	}
	generatedPipe, err := fidl.NewFormatter(rustfmtPath, args...).FormatPipe(generated)
	if err != nil {
		return err
	}

	if err := gen.GenerateImpl(generatedPipe, tree); err != nil {
		return err
	}

	return generatedPipe.Close()
}
