// 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.

package frontend

import (
	"fmt"
	"sort"
	"strings"

	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/stdlib"
)

// Symbol is an element in the package API. A symbol can be a constant,
// variable, function, type, field or method.
type Symbol struct {
	// Name is name of the symbol. At a given package version, name must be
	// unique.
	Name string

	// Synopsis is the one line description of the symbol that is displayed.
	Synopsis string

	// Section is the section that a symbol appears in.
	Section internal.SymbolSection

	// Kind is the type of a symbol, which is either a constant, variable,
	// function, type, field or method.
	Kind internal.SymbolKind

	// Link is the link to the symbol name on pkg.go.dev.
	Link string

	// Children contain the child symbols for this symbol. This will
	// only be populated when the SymbolType is "Type". For example, the
	// children of net/http.Handler are FileServer, NotFoundHandler,
	// RedirectHandler, StripPrefix, and TimeoutHandler. Each child
	// symbol will have ParentName set to the Name of this type.
	Children []*Symbol

	// Builds lists all of the build contexts supported by the symbol, it is
	// only available for limited set of builds. If the symbol supports all
	// build contexts, Builds will be nil.
	Builds []string

	// builds keeps track of build contexts used to generate Builds.
	builds map[internal.BuildContext]bool

	// New indicates that the symbol is new as of the version where it is
	// present. For example, if type Client was introduced in v1.0.0 and
	// Client.Timeout was introduced in v1.1.0, New will be false for Client
	// and true for Client.Timeout if this Symbol corresponds to v1.1.0.
	New bool
}

func (s *Symbol) addBuilds(builds ...internal.BuildContext) {
	if s.builds == nil {
		s.builds = map[internal.BuildContext]bool{}
	}
	for _, b := range builds {
		s.builds[b] = true
	}
}

// symbolsForVersion returns an array of symbols for use in the VersionSummary
// of the specified version.
func symbolsForVersion(pkgURLPath string, symbolsAtVersion map[string]map[internal.SymbolMeta]*internal.SymbolBuildContexts) [][]*Symbol {
	nameToMetaToSymbol := map[string]map[internal.SymbolMeta]*Symbol{}
	children := map[internal.SymbolMeta]*internal.SymbolBuildContexts{}
	for _, smToUs := range symbolsAtVersion {
		for sm, us := range smToUs {
			if sm.ParentName != sm.Name {
				// For the children, keep track of them for later.
				children[sm] = us
				continue
			}

			metaToSym, ok := nameToMetaToSymbol[sm.Name]
			if !ok {
				metaToSym = map[internal.SymbolMeta]*Symbol{}
				nameToMetaToSymbol[sm.Name] = metaToSym
			}
			s, ok := metaToSym[sm]
			if !ok {
				s = &Symbol{
					Name:     sm.Name,
					Synopsis: sm.Synopsis,
					Section:  sm.Section,
					Kind:     sm.Kind,
					Link:     symbolLink(pkgURLPath, sm.Name, us.BuildContexts()),
					New:      true,
				}
				nameToMetaToSymbol[s.Name][sm] = s
			}
			s.addBuilds(us.BuildContexts()...)
		}
	}

	for cm, cus := range children {
		// For each child symbol, 1 of 3 things can occur:
		//
		// Option 1: If no parent exists for this child symbol, make one
		// and add the parent to the map.
		//
		// Option 2: A parent exists and does not support the build context
		// of the child. This occurs when the parent type is introduced for
		// another build context, but was introduced at the previous version
		// for the current child. Create a new parent for this child.
		//
		// Option 3: A parent exists and does support the build context of
		// the child. Add the child to the parent.
		cs := &Symbol{
			Name:     cm.Name,
			Synopsis: cm.Synopsis,
			Section:  cm.Section,
			Kind:     cm.Kind,
			Link:     symbolLink(pkgURLPath, cm.Name, cus.BuildContexts()),
			New:      true,
		}

		ps := findParent(cm.ParentName, cus, nameToMetaToSymbol)
		if ps != nil {
			// Option 3: found a relevant parent.
			ps.Children = append(ps.Children, cs)
			continue
		}

		// Option 1 and 2: We did not find a relevant parent, so create
		// one.
		//
		// Since this parent is not introduced at this version, create
		// a distinct type for each group of symbols.
		// To do so, we make up a synopsis for the SymbolMeta below, since it
		// is only used as a key in nameToMetaToSymbol.
		//
		// Example case:
		// http://pkg.go.dev/internal/poll?tab=versions for go1.10 should show:
		//
		// type FD -- windows/amd64
		//		FD.ReadMsg
		//		FD.WriteMsg
		// type FD -- darwin/amd64, linux/amd64
		//		FD.SetBlocking
		//		FD.WriteOnce
		ps = createParent(cm.ParentName, pkgURLPath, cus.BuildContexts()...)
		pm := internal.SymbolMeta{
			Name:       ps.Name,
			ParentName: ps.Name,
			Synopsis:   fmt.Sprintf("type %s (%v)", ps.Name, cus.BuildContexts()),
			Section:    ps.Section,
			Kind:       ps.Kind,
		}
		ps.Children = append(ps.Children, cs)
		if _, ok := nameToMetaToSymbol[pm.Name]; !ok {
			nameToMetaToSymbol[pm.Name] = map[internal.SymbolMeta]*Symbol{}
		}
		nameToMetaToSymbol[pm.Name][pm] = ps
	}

	var symbols []*Symbol
	for _, mts := range nameToMetaToSymbol {
		for _, s := range mts {
			if len(s.builds) != len(internal.BuildContexts) {
				for b := range s.builds {
					s.Builds = append(s.Builds, fmt.Sprintf("%s/%s", b.GOOS, b.GOARCH))
				}
				sort.Strings(s.Builds)
			}
			symbols = append(symbols, s)
		}
	}
	return sortSymbols(symbols)
}

func findParent(parentName string, cus *internal.SymbolBuildContexts,
	nameToMetaToSymbol map[string]map[internal.SymbolMeta]*Symbol) *Symbol {
	parents, ok := nameToMetaToSymbol[parentName]
	if !ok {
		return nil
	}
	for _, ps := range parents {
		for build := range ps.builds {
			if cus.SupportsBuild(build) {
				return ps
			}
		}
	}
	return nil
}

func symbolLink(pkgURLPath, name string, builds []internal.BuildContext) string {
	if len(builds) == len(internal.BuildContexts) {
		return fmt.Sprintf("%s#%s", pkgURLPath, name)
	}

	// When a symbol is introduced for a specific GOOS/GOARCH at a version,
	// linking to an unspecified GOOS/GOARCH page might not take the user to
	// the symbol. Instead, link to one of the supported build contexts.
	return fmt.Sprintf("%s?GOOS=%s#%s", pkgURLPath, builds[0].GOOS, name)
}

// createParent creates a parent symbol for the provided unit symbol. This is
// used when us is a child of a symbol that may have been introduced at a
// different version. The symbol created will have New set to false, since this
// function is only used when a parent symbol is not found for the unit symbol,
// which means it was not introduced at the same version.
func createParent(parentName, pkgURLPath string, builds ...internal.BuildContext) *Symbol {
	s := &Symbol{
		Name:     parentName,
		Synopsis: fmt.Sprintf("type %s", parentName),
		Section:  internal.SymbolSectionTypes,
		Kind:     internal.SymbolKindType,
		Link:     symbolLink(pkgURLPath, parentName, builds),
	}
	s.addBuilds(builds...)
	return s
}

// sortSymbols returns an array of symbols in order of
// (1) Constants (2) Variables (3) Functions and (4) Types.
// Within each section, symbols are sorted alphabetically by name.
// In the types sections, aside from interfaces, child symbols are sorted in
// order of (1) Fields (2) Constants (3) Variables (4) Functions and (5)
// Methods. For interfaces, child symbols are sorted in order of
// (1) Methods (2) Constants (3) Variables and (4) Functions.
func sortSymbols(symbols []*Symbol) [][]*Symbol {
	sm := map[internal.SymbolSection][]*Symbol{}
	for _, parent := range symbols {
		sm[parent.Section] = append(sm[parent.Section], parent)
		cm := map[internal.SymbolKind][]*Symbol{}
		parent.Synopsis = strings.TrimSuffix(strings.TrimSuffix(parent.Synopsis, "{ ... }"), "{}")
		for _, c := range parent.Children {
			cm[c.Kind] = append(cm[c.Kind], c)
		}
		for _, syms := range cm {
			sortSymbolsGroup(syms)
		}
		symbols := append(append(append(
			cm[internal.SymbolKindField],
			cm[internal.SymbolKindConstant]...),
			cm[internal.SymbolKindVariable]...),
			cm[internal.SymbolKindFunction]...)
		if strings.Contains(parent.Synopsis, "interface") {
			parent.Children = append(cm[internal.SymbolKindMethod], symbols...)
		} else {
			parent.Children = append(symbols, cm[internal.SymbolKindMethod]...)
		}
	}
	for _, syms := range sm {
		sortSymbolsGroup(syms)
	}

	var out [][]*Symbol
	for _, section := range []internal.SymbolSection{
		internal.SymbolSectionConstants,
		internal.SymbolSectionVariables,
		internal.SymbolSectionFunctions,
		internal.SymbolSectionTypes} {
		if sm[section] != nil {
			out = append(out, sm[section])
		}
	}
	return out
}

func sortSymbolsGroup(syms []*Symbol) {
	sort.Slice(syms, func(i, j int) bool {
		s1 := syms[i]
		s2 := syms[j]
		if s1.Synopsis != s2.Synopsis {
			return s1.Synopsis < s2.Synopsis
		}
		return compareStringSlices(s1.Builds, s2.Builds) < 0
	})
}

func compareStringSlices(ss1, ss2 []string) int {
	for i, s1 := range ss1 {
		if i >= len(ss2) { // first slice is longer, so greater
			return 1
		}
		if c := strings.Compare(s1, ss2[i]); c != 0 {
			return c
		}
	}
	if len(ss1) == len(ss2) {
		return 0
	}
	// first slice is shorter
	return -1
}

// ParseVersionsDetails returns a map of versionToNameToUnitSymbol based on
// data from the provided VersionDetails.
func ParseVersionsDetails(vd *VersionsDetails) (_ *internal.SymbolHistory, err error) {
	sh := internal.NewSymbolHistory()
	for _, vl := range vd.ThisModule {
		for _, vs := range vl.Versions {
			v := vs.Version
			if vd.ThisModule[0].ModulePath == stdlib.ModulePath {
				v = stdlib.VersionForTag(v)
			}
			for _, syms := range vs.Symbols {
				for _, s := range syms {
					if s.New {
						addSymbol(s, v, sh, s.Builds)
					}
					for _, c := range s.Children {
						addSymbol(c, v, sh, s.Builds)
					}
				}
			}
		}
	}
	return sh, nil
}

func addSymbol(s *Symbol, v string, sh *internal.SymbolHistory, builds []string) {
	sm := internal.SymbolMeta{
		Name: s.Name,
	}
	if len(builds) == 0 {
		sh.AddSymbol(sm, v, internal.BuildContextAll)
		return
	}
	for _, b := range builds {
		goos, _, _ := strings.Cut(b, "/")
		var build internal.BuildContext
		switch goos {
		case "linux":
			build = internal.BuildContextLinux
		case "darwin":
			build = internal.BuildContextDarwin
		case "windows":
			build = internal.BuildContextWindows
		case "js":
			build = internal.BuildContextJS
		}
		sh.AddSymbol(sm, v, build)
	}
}
