// 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 swift implements Swift code generation from compiled VDL packages.
package swift

import (
	"bytes"
	"log"
	"path"
	"strings"

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

const (
	// The data passed into every template must include a FileDoc field, which
	// contains the comment for each generated file; e.g. the boilerplate copyright
	// header.
	header = `{{.FileDoc}}
	// This file was auto-generated by the vanadium vdl tool.
	`

	// fileTmpl is the template to produce a Swift generated file
	fileTmpl = header + `// Source: {{ .Source }}
{{ range $import := .ImportedModules }}
import {{ $import }}
{{ end }}
{{ range $tdef := .Tdefs }}
{{ $tdef }}
{{ end }}`
)

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

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

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

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

type swiftContext struct {
	env *compile.Env
	pkg *compile.Package
	// genPathToDir allows us to lookup the filesystem dir for any pkg.GenPath
	genPathToDir map[string]string
	// srcDirs is the combination of VDLROOT & VDLPATHs to provide a set of
	// root source directories. These directories provide a stop condition when
	// traversing a package's path's parents. In particular, we do this when
	// looking for a vdl.config to that specifies a SwiftModule.
	srcDirs map[string]bool

	// Cache
	memoizedTypeNames map[*compile.TypeDef]string
}

// Generate generates Swift files for all VDL files in the provided package,
// returning the list of generated Swift files as a slice. We generate Swift
// files to match the original VDL file layout, with the exception that
// constants are smushed into a <PackageName>.swift that consolidates the
// errors, package documentation (if any), and constants for a given package
// into a struct. This package struct provides a similar context to what
// would be provided by an import in VDL or Java.
// TODO(azinman): Run Swift formatters on the generated files.
func Generate(pkg *compile.Package, env *compile.Env, genPathToDir map[string]string) (ret []SwiftFileInfo) {
	srcDirs := map[string]bool{}
	for _, dir := range build.SrcDirs(env.Errors) {
		srcDirs[dir] = true
	}

	ctx := &swiftContext{env, pkg, genPathToDir, srcDirs, map[*compile.TypeDef]string{}}
	validateSwiftConfig(ctx)
	// One file for pkg documentation (if any), metadata, errors and constants.
	if pkgData := genSwiftPackageFile(pkg, ctx); pkgData != "" {
		ret = append(ret, SwiftFileInfo{
			Data:   []byte(pkgData),
			Name:   ctx.swiftPackageName(pkg) + "Package.swift",
			Module: ctx.swiftModule(pkg),
		})
	}
	for _, file := range pkg.Files {
		if len(file.TypeDefs) == 0 {
			// Nothing to generate
			continue
		}
		// Separate file for all typedefs.
		tdefs := []string{}
		for _, tdef := range file.TypeDefs {
			switch tdef.Type.Kind() {
			case vdl.Enum:
				tdefs = append(tdefs, genSwiftEnumTdef(tdef, ctx))
			case vdl.Union:
				tdefs = append(tdefs, genSwiftUnionTdef(tdef, ctx))
			case vdl.Struct:
				tdefs = append(tdefs, genSwiftStructTdef(tdef, ctx))
			default:
				tdefs = append(tdefs, genSwiftPrimitiveTdef(tdef, ctx))
			}
		}
		// TODO(zinman): loop through file.Interfaces for RPC generation
		source := path.Join(ctx.genPathToDir[pkg.GenPath], file.BaseName)
		vdlRoot, err := ctx.vdlRootForFilePath(source)
		if err != nil {
			log.Fatalf("vdl: couldn't find vdl root for path %v: %v", source, err)
		}
		source = strings.TrimPrefix(source, vdlRoot+"/")
		data := struct {
			FileDoc         string
			ImportedModules []string
			Tdefs           []string
			PackagePath     string
			Source          string
		}{
			FileDoc:         pkg.FileDoc,
			ImportedModules: ctx.importedModules(file.TypeDefs),
			Tdefs:           tdefs,
			PackagePath:     swiftGenPkgPath(pkg.GenPath),
			Source:          source,
		}
		var buf bytes.Buffer
		err = parseTmpl("swift file", fileTmpl).Execute(&buf, data)
		if err != nil {
			log.Fatalf("vdl: couldn't execute union template: %v", err)
		}
		baseName := strings.Replace(file.BaseName, path.Ext(file.BaseName), "", 1)
		ret = append(ret, SwiftFileInfo{
			Data:   buf.Bytes(),
			Name:   ctx.swiftPackageName(pkg) + vdlutil.FirstRuneToUpper(baseName) + ".swift",
			Module: ctx.swiftModule(pkg),
		})
	}
	return
}

// The native types feature is hard to use correctly.  E.g. the wire type
// must be statically registered in Swift 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,
}

func validateSwiftConfig(ctx *swiftContext) {
	vdlconfig := path.Join(ctx.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(ctx.pkg.Config.Swift.WireToNativeTypes) > 0 && !nativeTypePackageWhitelist[ctx.pkg.Path] {
		ctx.env.Errors.Errorf("%s: Swift.WireToNativeTypes is restricted to whitelisted VDL packages", vdlconfig)
	}
	// Look for a Swift module by walking up... if none found then panic
	if ctx.swiftModule(ctx.pkg) == "" {
		log.Fatalf("Could not find a swift module for package %v/%v; make sure to have a file named swiftmodule "+
			"defined at the root that is a text file that ONLY contains the name of your Swift module.",
			ctx.pkg.Path, ctx.pkg.Name)
	}
}
