// Copyright 2020 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 (
	"flag"
	"fmt"
	"log"
	"os"

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

type flagsDef struct {
	cpp.CommonFlags

	// Note: this option is not exercised in-tree.
	// Whenever changing the handling for outputBase, some SDK presubmit testing
	// is encouraged.
	outputBase *string

	testBase *string

	// TODO(fxbug.dev/45483): Until all SDK consumers are moved off to using dedicated
	// flags to invoke HLCPP fidlgen, we must preserve this legacy flag.
	generatorsUnused *string

	// If true, only generate the domain objects.
	splitGenerationDomainObjects *bool
}

var flags = flagsDef{
	CommonFlags: cpp.CommonFlags{
		Json: flag.String("json", "",
			"relative path to the FIDL intermediate representation."),
		Header: flag.String("header", "",
			"the output path for the generated header. "+
				"It cannot be supplied together with outputBase."),
		Source: flag.String("source", "",
			"the output path for the generated C++ implementation. "+
				"It cannot be supplied together with outputBase."),
		IncludeBase: flag.String("include-base", "",
			"the directory to which C and C++ includes should be relative."),
		IncludeStem: flag.String("include-stem", "cpp/fidl",
			"[optional] the suffix after library path when referencing includes. "+
				"Includes will be of the form <my/library/{include-stem}.h>. "),
		ClangFormatPath: flag.String("clang-format-path", "",
			"path to the clang-format tool."),
	},
	outputBase: flag.String("output-base", "",
		"the base file name for files generated by this generator. "+
			"It cannot be supplied together with header/source/test-base."),
	testBase: flag.String("test-base", "",
		"the output path for the generated test base header. "+
			"It cannot be supplied together with outputBase."),
	generatorsUnused: flag.String("generators", "",
		"unused"),
	splitGenerationDomainObjects: flag.Bool("experimental-split-generation-domain-objects", false,
		"[optional] only generate the domain object definitions for the data types in this library."),
}

// intoOptions validates the incoming flags and computes the generated file paths
// from a valid flag combination.
func (f flagsDef) intoOptions() (codegenOptions, error) {
	if *f.Json == "" {
		return codegenOptions{}, fmt.Errorf("-json is required")
	}
	if *f.IncludeBase == "" {
		return codegenOptions{}, fmt.Errorf("-include-base is required")
	}
	mode := codegen.Monolithic
	if *flags.splitGenerationDomainObjects {
		mode = codegen.OnlyGenerateDomainObjects
	}
	if *f.splitGenerationDomainObjects && *f.testBase != "" {
		return codegenOptions{}, fmt.Errorf("there is no test base header when generating only the " +
			"domain objects")
	}
	if *f.outputBase == "" {
		if *f.Header == "" || *f.Source == "" ||
			(*f.testBase == "" && !*f.splitGenerationDomainObjects) {
			return codegenOptions{}, fmt.Errorf("must specify either -output-base, or all of " +
				"-header, -source, -test-base, unless -experimental-split-generation-domain-objects " +
				"is specified in which case -test-base must be omitted")
		}
		return codegenOptions{
			jsonPath:    *f.Json,
			header:      *f.Header,
			source:      *f.Source,
			testBase:    *f.testBase,
			includeBase: *f.IncludeBase,
			includeStem: *f.IncludeStem,
			mode:        mode,
		}, nil
	} else {
		if *f.Header != "" || *f.Source != "" || *f.testBase != "" {
			return codegenOptions{}, fmt.Errorf("cannot specify both -output-base, and any of " +
				"-header, -source, -test-base")
		}
		var testBase string
		if !*f.splitGenerationDomainObjects {
			testBase = *f.outputBase + "_test_base.h"
		}
		return codegenOptions{
			jsonPath:    *f.Json,
			header:      *f.outputBase + ".h",
			source:      *f.outputBase + ".cc",
			testBase:    testBase,
			includeBase: *f.IncludeBase,
			includeStem: *f.IncludeStem,
			mode:        mode,
		}, nil
	}
}

// codegenOptions is a processed version of flagsDef. In particular, it resolves
// `-output-base` into header/source file paths, if that option was specified.
type codegenOptions struct {
	jsonPath    string
	header      string
	source      string
	testBase    string
	includeBase string
	includeStem string
	mode        codegen.CodeGenerationMode
}

var _ cpp.CodegenOptions = (*codegenOptions)(nil)
var _ codegen.Config = (*codegenOptions)(nil)

func (c codegenOptions) Header() string {
	return c.header
}

func (c codegenOptions) Source() string {
	return c.source
}

func (c codegenOptions) HasTestBase() bool {
	return c.testBase != ""
}

func (c codegenOptions) TestBase() string {
	if !c.HasTestBase() {
		panic("Missing test base")
	}
	return c.testBase
}

func (c codegenOptions) IncludeBase() string {
	return c.includeBase
}

func (c codegenOptions) IncludeStem() string {
	return c.includeStem
}

func main() {
	flag.Parse()
	if !flag.Parsed() {
		flag.PrintDefaults()
		os.Exit(1)
	}

	opts, err := flags.intoOptions()
	if err != nil {
		log.Fatal(err)
	}

	ir, err := fidlgen.ReadJSONIr(opts.jsonPath)
	if err != nil {
		log.Fatal(err)
	}

	generator := codegen.NewFidlGenerator(opts.mode)
	if err := generator.GenerateFidl(ir, opts, *flags.ClangFormatPath); err != nil {
		log.Fatalf("Error running generator: %v", err)
	}
}
