// Copyright 2018 The CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/constant"
	"go/format"
	"go/parser"
	"go/printer"
	"go/token"
	"io"
	"io/ioutil"
	"log"
	"math/big"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/errors"
	cueformat "cuelang.org/go/cue/format"
	"cuelang.org/go/cue/load"
	"cuelang.org/go/internal"
)

const prefix = "../pkg/"

const header = `// Code generated by go generate. DO NOT EDIT.

package cue

`

const initFunc = `
func init() {
	initBuiltins(builtinPackages)
}

var _ io.Reader
`

func main() {
	flag.Parse()
	log.SetFlags(log.Lshortfile)
	log.SetOutput(os.Stdout)

	g := generator{
		w:     &bytes.Buffer{},
		decls: &bytes.Buffer{},
		fset:  token.NewFileSet(),
	}

	fmt.Fprintln(g.w, "var builtinPackages = map[string]*builtinPkg{")
	filepath.Walk(prefix, func(dir string, info os.FileInfo, err error) error {
		if err != nil {
			log.Fatal(err)
		}
		if info.Name() == "testdata" {
			return filepath.SkipDir
		}
		if info.IsDir() {
			g.processDir(dir)
		}
		return nil
	})
	fmt.Fprintln(g.w, "}")

	w := &bytes.Buffer{}
	fmt.Fprintln(w, header)

	m := map[string]*ast.ImportSpec{}
	keys := []string{}
	for _, spec := range g.imports {
		if spec.Path.Value == `"cuelang.org/go/cue"` {
			// Don't add this package.
			continue
		}
		if prev, ok := m[spec.Path.Value]; ok {
			if importName(prev) != importName(spec) {
				log.Fatalf("inconsistent name for import %s: %q != %q",
					spec.Path.Value, importName(prev), importName(spec))
			}
			continue
		}
		m[spec.Path.Value] = spec
		keys = append(keys, spec.Path.Value)
	}
	fmt.Fprintln(w, "import (")
	sort.Strings(keys)
	for _, k := range keys {
		printer.Fprint(w, g.fset, m[k])
		fmt.Fprintln(w)
	}
	fmt.Fprintln(w, ")")
	fmt.Fprintln(w, initFunc)
	io.Copy(w, g.decls)
	io.Copy(w, g.w)

	b, err := format.Source(w.Bytes())
	if err != nil {
		b = w.Bytes() // write the unformatted source
	}
	// TODO: do this in a more principled way. The best is probably to
	// put all builtins in a separate package.
	b = bytes.Replace(b, []byte("cue."), []byte(""), -1)
	b = bytes.Replace(b, []byte("{{}}"), []byte("{}"), -1)

	if err := ioutil.WriteFile("builtins.go", b, 0644); err != nil {
		log.Fatal(err)
	}
	if err != nil {
		log.Fatal(err)
	}
}

type generator struct {
	w          *bytes.Buffer
	decls      *bytes.Buffer
	name       string
	fset       *token.FileSet
	defaultPkg string
	first      bool
	iota       int

	imports []*ast.ImportSpec
}

func (g *generator) processDir(dir string) {
	goFiles, err := filepath.Glob(filepath.Join(dir, "*.go"))
	if err != nil {
		log.Fatal(err)
	}

	cueFiles, err := filepath.Glob(filepath.Join(dir, "*.cue"))
	if err != nil {
		log.Fatal(err)
	}

	if len(goFiles)+len(cueFiles) == 0 {
		return
	}

	pkg := dir[len(prefix):]
	fmt.Fprintf(g.w, "%q: &builtinPkg{\nnative: []*builtin{{\n", pkg)
	g.first = true
	for _, filename := range goFiles {
		g.processGo(filename)
	}
	fmt.Fprintf(g.w, "}},\n")
	g.processCUE(dir)
	fmt.Fprintf(g.w, "},\n")
}

func (g *generator) sep() {
	if g.first {
		g.first = false
		return
	}
	fmt.Fprintln(g.w, "}, {")
}

func importName(s *ast.ImportSpec) string {
	if s.Name != nil {
		return s.Name.Name
	}
	pkg, err := strconv.Unquote(s.Path.Value)
	if err != nil {
		log.Fatal(err)
	}
	return path.Base(pkg)
}

// processCUE mixes in CUE definitions defined in the package directory.
func (g *generator) processCUE(dir string) {
	instances := cue.Build(load.Instances([]string{dir}, &load.Config{
		StdRoot: "../pkg",
	}))

	if err := instances[0].Err; err != nil {
		if !strings.Contains(err.Error(), "no CUE files") {
			errors.Print(os.Stderr, err, nil)
			log.Fatalf("error processing %s: %v", dir, err)
		}
		return
	}

	n := internal.ToExpr(instances[0].Value().Syntax(cue.Raw()))
	b, err := cueformat.Node(n)
	if err != nil {
		log.Fatal(err)
	}
	b = bytes.ReplaceAll(b, []byte("\n\n"), []byte("\n"))
	// body = strings.ReplaceAll(body, "\t", "")
	// TODO: escape backtick
	fmt.Fprintf(g.w, "cue: `%s`,\n", string(b))
}

func (g *generator) processGo(filename string) {
	if strings.HasSuffix(filename, "_test.go") {
		return
	}
	f, err := parser.ParseFile(g.fset, filename, nil, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}
	g.defaultPkg = ""
	g.name = f.Name.Name
	if g.name == "structs" {
		g.name = "struct"
	}

	for _, d := range f.Decls {
		switch x := d.(type) {
		case *ast.GenDecl:
			switch x.Tok {
			case token.CONST:
				for _, spec := range x.Specs {
					if !ast.IsExported(spec.(*ast.ValueSpec).Names[0].Name) {
						continue
					}
					g.genConst(spec.(*ast.ValueSpec))
				}
			case token.IMPORT:
				for _, s := range x.Specs {
					spec := s.(*ast.ImportSpec)
					g.imports = append(g.imports, spec)
				}
				if g.defaultPkg == "" {
					g.defaultPkg = importName(x.Specs[0].(*ast.ImportSpec))
				}
			case token.VAR:
				for _, spec := range x.Specs {
					if ast.IsExported(spec.(*ast.ValueSpec).Names[0].Name) {
						log.Fatal("gen %s: var declarations not supported", filename)
					}
				}
				printer.Fprint(g.decls, g.fset, x)
				fmt.Fprint(g.decls, "\n\n")
				continue
			case token.TYPE:
				// TODO: support type declarations.
				for _, spec := range x.Specs {
					if ast.IsExported(spec.(*ast.TypeSpec).Name.Name) {
						log.Fatal("gen %s: type declarations not supported", filename)
					}
				}
				continue
			default:
				log.Fatalf("gen %s: unexpected spec of type %s", filename, x.Tok)
			}
		case *ast.FuncDecl:
			g.genFun(x)
		}
	}
}

func (g *generator) genConst(spec *ast.ValueSpec) {
	name := spec.Names[0].Name
	value := ""
	switch v := g.toValue(spec.Values[0]); v.Kind() {
	case constant.Bool, constant.Int, constant.String:
		// TODO: convert octal numbers
		value = v.ExactString()
	case constant.Float:
		var rat big.Rat
		rat.SetString(v.ExactString())
		var float big.Float
		float.SetRat(&rat)
		value = float.Text('g', -1)
	default:
		fmt.Printf("Dropped entry %s.%s (%T: %v)\n", g.defaultPkg, name, v.Kind(), v.ExactString())
		return
	}
	g.sep()
	fmt.Fprintf(g.w, "Name: %q,\n Const: %q,\n", name, value)
}

func (g *generator) toValue(x ast.Expr) constant.Value {
	switch x := x.(type) {
	case *ast.BasicLit:
		return constant.MakeFromLiteral(x.Value, x.Kind, 0)
	case *ast.BinaryExpr:
		return constant.BinaryOp(g.toValue(x.X), x.Op, g.toValue(x.Y))
	case *ast.UnaryExpr:
		return constant.UnaryOp(x.Op, g.toValue(x.X), 0)
	default:
		log.Fatalf("%s: unsupported expression type %T: %#v", g.defaultPkg, x, x)
	}
	return constant.MakeUnknown()
}

func (g *generator) genFun(x *ast.FuncDecl) {
	if x.Body == nil {
		return
	}
	types := []string{}
	if x.Type.Results != nil {
		for _, f := range x.Type.Results.List {
			if len(f.Names) > 0 {
				for range f.Names {
					types = append(types, g.goKind(f.Type))
				}
			} else {
				types = append(types, g.goKind(f.Type))
			}
		}
	}
	if n := len(types); n != 1 && (n != 2 || types[1] != "error") {
		fmt.Printf("Dropped func %s.%s: must have one return value or a value and an error %v\n", g.defaultPkg, x.Name.Name, types)
		return
	}

	if !ast.IsExported(x.Name.Name) || x.Recv != nil {
		if strings.HasPrefix(x.Name.Name, g.name) {
			printer.Fprint(g.decls, g.fset, x)
			fmt.Fprint(g.decls, "\n\n")
		}
		return
	}

	g.sep()
	fmt.Fprintf(g.w, "Name: %q,\n", x.Name.Name)

	args := []string{}
	vals := []string{}
	kind := []string{}
	for _, f := range x.Type.Params.List {
		for _, name := range f.Names {
			typ := g.goKind(f.Type)
			argKind := g.goToCUE(f.Type)
			vals = append(vals, fmt.Sprintf("c.%s(%d)", typ, len(args)))
			args = append(args, name.Name)
			kind = append(kind, argKind)
		}
	}

	fmt.Fprintf(g.w, "Params: []kind{%s},\n", strings.Join(kind, ", "))
	result := g.goToCUE(x.Type.Results.List[0].Type)
	fmt.Fprintf(g.w, "Result: %s,\n", result)
	argList := strings.Join(args, ", ")
	valList := strings.Join(vals, ", ")
	init := ""
	if len(args) > 0 {
		init = fmt.Sprintf("%s := %s", argList, valList)
	}

	fmt.Fprintf(g.w, "Func: func(c *callCtxt) {")
	defer fmt.Fprintln(g.w, "},")
	fmt.Fprintln(g.w)
	if init != "" {
		fmt.Fprintln(g.w, init)
	}
	fmt.Fprintln(g.w, "if c.do() {")
	defer fmt.Fprintln(g.w, "}")
	if len(types) == 1 {
		fmt.Fprint(g.w, "c.ret = func() interface{} ")
	} else {
		fmt.Fprint(g.w, "c.ret, c.err = func() (interface{}, error) ")
	}
	printer.Fprint(g.w, g.fset, x.Body)
	fmt.Fprintln(g.w, "()")
}

func (g *generator) goKind(expr ast.Expr) string {
	if star, isStar := expr.(*ast.StarExpr); isStar {
		expr = star.X
	}
	w := &bytes.Buffer{}
	printer.Fprint(w, g.fset, expr)
	switch str := w.String(); str {
	case "big.Int":
		return "bigInt"
	case "big.Float":
		return "bigFloat"
	case "big.Rat":
		return "bigRat"
	case "internal.Decimal":
		return "decimal"
	case "[]*internal.Decimal":
		return "decimalList"
	case "cue.Struct":
		return "structVal"
	case "cue.Value":
		return "value"
	case "cue.List":
		return "list"
	case "[]string":
		return "strList"
	case "[]byte":
		return "bytes"
	case "[]cue.Value":
		return "list"
	case "io.Reader":
		return "reader"
	case "time.Time":
		return "string"
	default:
		return str
	}
}

func (g *generator) goToCUE(expr ast.Expr) (cueKind string) {
	// TODO: detect list and structs types for return values.
	switch k := g.goKind(expr); k {
	case "error":
		cueKind += "bottomKind"
	case "bool":
		cueKind += "boolKind"
	case "bytes", "reader":
		cueKind += "bytesKind|stringKind"
	case "string":
		cueKind += "stringKind"
	case "int", "int8", "int16", "int32", "rune", "int64",
		"uint", "byte", "uint8", "uint16", "uint32", "uint64",
		"bigInt":
		cueKind += "intKind"
	case "float64", "bigRat", "bigFloat", "decimal":
		cueKind += "numKind"
	case "list", "decimalList", "strList":
		cueKind += "listKind"
	case "structVal":
		cueKind += "structKind"
	case "value":
		// Must use callCtxt.value method for these types and resolve manually.
		cueKind += "topKind" // TODO: can be more precise
	default:
		switch {
		case strings.HasPrefix(k, "[]"):
			cueKind += "listKind"
		case strings.HasPrefix(k, "map["):
			cueKind += "structKind"
		default:
			// log.Println("Unknown type:", k)
			// Must use callCtxt.value method for these types and resolve manually.
			cueKind += "topKind" // TODO: can be more precise
		}
	}
	return cueKind
}
