// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Command genopts generates JSON describing gopls' user options.
package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"go/ast"
	"go/types"
	"os"
	"reflect"
	"strings"

	"golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/lsp/source"
)

var (
	output = flag.String("output", "", "output file")
)

func main() {
	flag.Parse()
	if err := doMain(); err != nil {
		fmt.Fprintf(os.Stderr, "Generation failed: %v\n", err)
		os.Exit(1)
	}
}

func doMain() error {
	out := os.Stdout
	if *output != "" {
		var err error
		out, err = os.OpenFile(*output, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
		if err != nil {
			return err
		}
		defer out.Close()
	}

	content, err := generate()
	if err != nil {
		return err
	}
	if _, err := out.Write(content); err != nil {
		return err
	}

	return out.Close()
}

func generate() ([]byte, error) {
	pkgs, err := packages.Load(
		&packages.Config{
			Mode: packages.NeedTypes | packages.NeedSyntax | packages.NeedDeps,
		},
		"golang.org/x/tools/internal/lsp/source",
	)
	if err != nil {
		return nil, err
	}
	pkg := pkgs[0]

	defaults := source.DefaultOptions()
	categories := map[string][]option{}
	for _, cat := range []reflect.Value{
		reflect.ValueOf(defaults.DebuggingOptions),
		reflect.ValueOf(defaults.UserOptions),
		reflect.ValueOf(defaults.ExperimentalOptions),
	} {
		opts, err := loadOptions(cat, pkg)
		if err != nil {
			return nil, err
		}
		catName := strings.TrimSuffix(cat.Type().Name(), "Options")
		categories[catName] = opts
	}

	marshaled, err := json.Marshal(categories)
	if err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(nil)
	fmt.Fprintf(buf, "// Code generated by \"golang.org/x/tools/internal/lsp/source/genopts\"; DO NOT EDIT.\n\npackage source\n\nconst OptionsJson = %q\n", string(marshaled))
	return buf.Bytes(), nil
}

type option struct {
	Name       string
	Type       string
	Doc        string
	EnumValues []string
	Default    string
}

func loadOptions(category reflect.Value, pkg *packages.Package) ([]option, error) {
	// Find the type information and ast.File corresponding to the category.
	optsType := pkg.Types.Scope().Lookup(category.Type().Name())
	if optsType == nil {
		return nil, fmt.Errorf("could not find %v in scope %v", category.Type().Name(), pkg.Types.Scope())
	}

	fset := pkg.Fset
	var file *ast.File
	for _, f := range pkg.Syntax {
		if fset.Position(f.Pos()).Filename == fset.Position(optsType.Pos()).Filename {
			file = f
		}
	}
	if file == nil {
		return nil, fmt.Errorf("no file for opts type %v", optsType)
	}

	enums := loadEnums(pkg)

	var opts []option
	optsStruct := optsType.Type().Underlying().(*types.Struct)
	for i := 0; i < optsStruct.NumFields(); i++ {
		// The types field gives us the type.
		typesField := optsStruct.Field(i)
		path, _ := astutil.PathEnclosingInterval(file, typesField.Pos(), typesField.Pos())
		if len(path) < 2 {
			return nil, fmt.Errorf("could not find AST node for field %v", typesField)
		}
		// The AST field gives us the doc.
		astField, ok := path[1].(*ast.Field)
		if !ok {
			return nil, fmt.Errorf("unexpected AST path %v", path)
		}

		// The reflect field gives us the default value.
		reflectField := category.FieldByName(typesField.Name())
		if !reflectField.IsValid() {
			return nil, fmt.Errorf("could not find reflect field for %v", typesField.Name())
		}

		// Format the default value. VSCode exposes settings as JSON, so showing them as JSON is reasonable.
		// Nil values format as "null" so print them as hardcoded empty values.
		def := reflectField.Interface()
		defBytes, err := json.Marshal(def)
		if err != nil {
			return nil, err
		}

		switch reflectField.Type().Kind() {
		case reflect.Map:
			if reflectField.IsNil() {
				defBytes = []byte("{}")
			}
		case reflect.Slice:
			if reflectField.IsNil() {
				defBytes = []byte("[]")
			}
		}

		typ := typesField.Type().String()
		if _, ok := enums[typesField.Type()]; ok {
			typ = "enum"
		}

		opts = append(opts, option{
			Name:       lowerFirst(typesField.Name()),
			Type:       typ,
			Doc:        lowerFirst(astField.Doc.Text()),
			Default:    string(defBytes),
			EnumValues: enums[typesField.Type()],
		})
	}
	return opts, nil
}

func loadEnums(pkg *packages.Package) map[types.Type][]string {
	enums := map[types.Type][]string{}
	for _, name := range pkg.Types.Scope().Names() {
		obj := pkg.Types.Scope().Lookup(name)
		cnst, ok := obj.(*types.Const)
		if !ok {
			continue
		}
		enums[obj.Type()] = append(enums[obj.Type()], cnst.Val().ExactString())
	}
	return enums
}

func lowerFirst(x string) string {
	if x == "" {
		return x
	}
	return strings.ToLower(x[:1]) + x[1:]
}
