// Copyright 2015 The Vanadium 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 java implements Java code generation from compiled VDL packages.
package java

import (
	"path"

	"v.io/v23/vdl"
	"v.io/x/ref/lib/vdl/compile"
)

// pkgPathXlator is the function used to translate a VDL package path
// into a Java package path.  If nil, no translation takes place.
var pkgPathXlator func(path string) string

// SetPkgPathXlator sets the function used to translate a VDL package
// path into a Java package path.
func SetPkgPathXlator(xlator func(path string) string) {
	pkgPathXlator = xlator
}

// javaGenPkgPath returns the Java package path given the VDL package path.
func javaGenPkgPath(vdlPkgPath string) string {
	if pkgPathXlator == nil {
		return vdlPkgPath
	}
	return pkgPathXlator(vdlPkgPath)
}

// JavaFileInfo stores the name and contents of the generated Java file.
type JavaFileInfo struct {
	Dir  string
	Name string
	Data []byte
}

// Generate generates Java files for all VDL files in the provided package,
// returning the list of generated Java files as a slice.  Since Java requires
// that each public class/interface gets defined in a separate file, this method
// will return one generated file per struct.  (Interfaces actually generate
// two files because we create separate interfaces for clients and servers.)
// In addition, since Java doesn't support global variables (i.e., variables
// defined outside of a class), all constants are moved into a special "Consts"
// class and stored in a separate file.  All client bindings are stored in a
// separate Client.java file. Finally, package documentation (if any) is stored
// in a "package-info.java" file.
//
// TODO(spetrovic): Run Java formatters on the generated files.
func Generate(pkg *compile.Package, env *compile.Env) (ret []JavaFileInfo) {
	validateJavaConfig(pkg, env)
	// One file for package documentation (if any).
	if g := genJavaPackageFile(pkg, env); g != nil {
		ret = append(ret, *g)
	}
	// Single file for all constants' definitions.
	if g := genJavaConstFile(pkg, env); g != nil {
		ret = append(ret, *g)
	}
	// Single file for all errors' definitions.
	if g := genJavaErrorFile(pkg, env); g != nil {
		ret = append(ret, *g)
	}
	for _, file := range pkg.Files {
		// Separate file for all typedefs.
		for _, tdef := range file.TypeDefs {
			switch tdef.Type.Kind() {
			case vdl.Array:
				ret = append(ret, genJavaArrayFile(tdef, env))
			case vdl.Complex64, vdl.Complex128:
				ret = append(ret, genJavaComplexFile(tdef, env))
			case vdl.Enum:
				ret = append(ret, genJavaEnumFile(tdef, env))
			case vdl.List:
				ret = append(ret, genJavaListFile(tdef, env))
			case vdl.Map:
				ret = append(ret, genJavaMapFile(tdef, env))
			case vdl.Union:
				ret = append(ret, genJavaUnionFile(tdef, env))
			case vdl.Set:
				ret = append(ret, genJavaSetFile(tdef, env))
			case vdl.Struct:
				ret = append(ret, genJavaStructFile(tdef, env))
			default:
				ret = append(ret, genJavaPrimitiveFile(tdef, env))
			}
		}
		// Separate file for all interface definitions.
		for _, iface := range file.Interfaces {
			ret = append(ret, genJavaClientFactoryFile(iface, env))
			ret = append(ret, genJavaClientInterfaceFile(iface, env)) // client interface
			ret = append(ret, genJavaClientStubFile(iface, env))
			ret = append(ret, genJavaServerInterfaceFile(iface, env)) // server interface
			ret = append(ret, genJavaServerWrapperFile(iface, env))
		}
	}
	return
}

// The native types feature is hard to use correctly.  E.g. the wire type
// must be statically registered in Java vdl package in order for the
// wire<->native conversion to work, which is hard to ensure.
//
// Restrict the feature to these whitelisted VDL packages for now.
var nativeTypePackageWhitelist = map[string]bool{
	"time":                                   true,
	"v.io/v23/security":                      true,
	"v.io/x/ref/lib/vdl/testdata/nativetest": true,
}

func validateJavaConfig(pkg *compile.Package, env *compile.Env) {
	vdlconfig := path.Join(pkg.GenPath, "vdl.config")
	// Validate native type configuration.  Since native types are hard to use, we
	// restrict them to a built-in whitelist of packages for now.
	if len(pkg.Config.Java.WireToNativeTypes) > 0 && !nativeTypePackageWhitelist[pkg.Path] {
		env.Errors.Errorf("%s: Java.WireToNativeTypes is restricted to whitelisted VDL packages", vdlconfig)
	}
	// Make sure each wire type is actually defined in the package.
	for wire, _ := range pkg.Config.Java.WireToNativeTypes {
		if def := pkg.ResolveType(wire); def == nil {
			env.Errors.Errorf("%s: type %s specified in Java.WireToNativeTypes undefined", vdlconfig, wire)
		}
	}
}
