// Copyright 2021 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.
//
// This file caches information about which standard library types, methods,
// and functions appeared in what version of Go
//
// Copied from
// https://go.googlesource.com/tools/+/5ab06b02d60653d5a5220fb2d99064055da3bdbd/godoc/versions.go
// with these modifications.

package symbol

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
	"unicode"

	"golang.org/x/mod/semver"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/stdlib"
)

// ParsePackageAPIInfo parses apiVersions using contents of the specified directory.
func ParsePackageAPIInfo(files []string) (_ apiVersions, err error) {
	defer derrors.Wrap(&err, "ParsePackageAPIInfo")

	// Process files in reverse semver order (vx.y.z, vz.y.z-1, ...).
	//
	// The signature of an identifier may change
	// (for example, a function that accepts a type replaced with
	// an alias), and so an existing symbol may show up again in
	// a later api/vX.Y.Z.txt file. Parsing in reverse version
	// order means we end up with the earliest version of Go
	// when the symbol was added. See golang.org/issue/44081.
	//
	ver := func(name string) string {
		base := filepath.Base(name)
		v := strings.TrimSuffix(base, ".txt")
		if strings.HasPrefix(base, "go") {
			// stdlib files have the structure goN.txt.
			// Get the semantic version.
			v = stdlib.VersionForTag(v)
		}
		return v
	}
	sort.Slice(files, func(i, j int) bool {
		return semver.Compare(ver(files[i]), ver(files[j])) > 0
	})

	vp := new(versionParser)
	for _, f := range files {
		if err := vp.parseFile(f); err != nil {
			return nil, err
		}
	}
	if len(vp.res) == 0 {
		return nil, fmt.Errorf("apiVersions should not be empty")
	}
	return vp.res, nil
}

// LoadAPIFiles loads data about the API for the given package from dir.
func LoadAPIFiles(pkgPath, dir string) ([]string, error) {
	var apiGlob string
	if stdlib.Contains(pkgPath) {
		apiGlob = filepath.Join(filepath.Clean(runtime.GOROOT()), "api", "go*.txt")
	} else {
		apiGlob = filepath.Join(dir, pkgPath, "v*.txt")
	}

	files, err := filepath.Glob(apiGlob)
	if err != nil {
		return nil, err
	}
	if len(files) == 0 {
		return nil, fmt.Errorf("no files matching %q", apiGlob)
	}
	return files, nil
}

// apiVersions is a map of packages to information about those packages'
// symbols and when they were added to Go.
//
// Only things added after Go1 are tracked. Version strings are of the
// form "1.1", "1.2", etc.
type apiVersions map[string]pkgAPIVersions // keyed by Go package ("net/http")

// pkgAPIVersions contains information about which version of Go added
// certain package symbols.
//
// Only things added after Go1 are tracked. Version strings are of the
// form "1.1", "1.2", etc.
type pkgAPIVersions struct {
	constSince  map[string]string
	varSince    map[string]string
	typeSince   map[string]string            // "Server" -> "1.7"
	methodSince map[string]map[string]string // "*Server" ->"Shutdown"->1.8
	funcSince   map[string]string            // "NewServer" -> "1.7"
	fieldSince  map[string]map[string]string // "ClientTrace" -> "Got1xxResponse" -> "1.11"
}

// versionedRow represents an API feature, a parsed line of a
// $GOROOT/api/go.*txt file.
type versionedRow struct {
	pkg        string // "net/http"
	kind       string // "type", "func", "method", "field" TODO: "const", "var"
	recv       string // for methods, the receiver type ("Server", "*Server")
	name       string // name of type, (struct) field, func, method
	structName string // for struct fields, the outer struct name
}

// versionParser parses $GOROOT/api/go*.txt files and stores them in in its rows field.
type versionParser struct {
	res apiVersions // initialized lazily
}

// parseFile parses the named <apidata>/VERSION.txt file.
//
// For each row, it updates the corresponding entry in
// vp.res to VERSION, overwriting any previous value.
func (vp *versionParser) parseFile(filename string) (err error) {
	defer derrors.Wrap(&err, "parseFile(%q)", filename)
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()
	base := filepath.Base(filename)
	ver := strings.TrimSuffix(base, ".txt")
	sc := bufio.NewScanner(f)
	for sc.Scan() {
		row, ok := parseRow(sc.Text())
		if !ok {
			continue
		}
		if vp.res == nil {
			vp.res = make(apiVersions)
		}
		pkgi, ok := vp.res[row.pkg]
		if !ok {
			pkgi = pkgAPIVersions{
				constSince:  make(map[string]string),
				varSince:    make(map[string]string),
				typeSince:   make(map[string]string),
				methodSince: make(map[string]map[string]string),
				funcSince:   make(map[string]string),
				fieldSince:  make(map[string]map[string]string),
			}
			vp.res[row.pkg] = pkgi
		}
		switch row.kind {
		case "const":
			pkgi.constSince[row.name] = ver
		case "var":
			pkgi.varSince[row.name] = ver
		case "func":
			pkgi.funcSince[row.name] = ver
		case "type":
			pkgi.typeSince[row.name] = ver
		case "method":
			if _, ok := pkgi.methodSince[row.recv]; !ok {
				pkgi.methodSince[row.recv] = make(map[string]string)
			}
			pkgi.methodSince[row.recv][row.name] = ver
		case "field":
			if _, ok := pkgi.fieldSince[row.structName]; !ok {
				pkgi.fieldSince[row.structName] = make(map[string]string)
			}
			pkgi.fieldSince[row.structName][row.name] = ver
		}
	}
	return sc.Err()
}
func parseRow(s string) (vr versionedRow, ok bool) {
	if !strings.HasPrefix(s, "pkg ") {
		// Skip comments, blank lines, etc.
		return
	}
	rest := s[len("pkg "):]
	endPkg := strings.IndexFunc(rest, func(r rune) bool {
		return !(unicode.IsLetter(r) || r == '.' || r == '/' || r == '-' || unicode.IsDigit(r))
	})
	if endPkg == -1 {
		return
	}
	vr.pkg, rest = rest[:endPkg], rest[endPkg:]
	if !strings.HasPrefix(rest, ", ") {
		// If the part after the pkg name isn't ", ", then it's a OS/ARCH-dependent line of the form:
		//   pkg syscall (darwin-amd64), const ImplementsGetwd = false
		// We skip those for now.
		return
	}
	rest = rest[len(", "):]
	switch {
	case strings.HasPrefix(rest, "type "):
		rest = rest[len("type "):]
		sp := strings.IndexByte(rest, ' ')
		if sp == -1 {
			return
		}
		vr.name, rest = rest[:sp], rest[sp+1:]
		switch {
		case strings.HasPrefix(rest, "struct, "):
			rest = rest[len("struct, "):]
			if i := strings.IndexByte(rest, ' '); i != -1 {
				vr.kind = "field"
				vr.structName = vr.name
				vr.name = rest[:i]
				return vr, true
			}
		case strings.HasPrefix(rest, "interface, "):
			rest = rest[len("interface, "):]
			if i := strings.IndexByte(rest, '('); i != -1 {
				vr.kind = "method"
				vr.recv = vr.name
				vr.name = rest[:i]
				return vr, true
			}
		default:
			vr.kind = "type"
			return vr, true
		}
	case strings.HasPrefix(rest, "const "):
		vr.kind = "const"
		rest = rest[len("const "):]
		if i := strings.IndexByte(rest, ' '); i != -1 {
			vr.name = rest[:i]
			return vr, true
		}
	case strings.HasPrefix(rest, "var "):
		vr.kind = "var"
		rest = rest[len("var "):]
		if i := strings.IndexByte(rest, ' '); i != -1 {
			vr.name = rest[:i]
			return vr, true
		}
	case strings.HasPrefix(rest, "func "):
		vr.kind = "func"
		rest = rest[len("func "):]
		if i := strings.IndexByte(rest, '('); i != -1 {
			vr.name = rest[:i]
			return vr, true
		}
	case strings.HasPrefix(rest, "method "): // "method (*File) SetModTime(time.Time)"
		vr.kind = "method"
		rest = rest[len("method "):] // "(*File) SetModTime(time.Time)"
		sp := strings.IndexByte(rest, ' ')
		if sp == -1 {
			return
		}
		vr.recv = strings.Trim(rest[:sp], "()")    // "*File"
		vr.recv = strings.TrimPrefix(vr.recv, "*") // "File"
		rest = rest[sp+1:]                         // SetMode(os.FileMode)
		paren := strings.IndexByte(rest, '(')
		if paren == -1 {
			return
		}
		vr.name = rest[:paren]
		return vr, true
	}
	return // TODO: handle more cases
}
