// Copyright 2019 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 source

import (
	"context"
	"encoding/xml"
	"fmt"
	"io"
	"strings"

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

// This code adapted from https://go.googlesource.com/gddo/+/refs/heads/master/gosrc/gosrc.go.

// sourceMeta represents the values in a go-source meta tag, or as a fallback,
// values from a go-import meta tag.
// The go-source spec is at https://github.com/golang/gddo/wiki/Source-Code-Links.
// The go-import spec is in "go help importpath".
type sourceMeta struct {
	repoRootPrefix string // import path prefix corresponding to repo root
	repoURL        string // URL of the repo root
	// The next two are only present in a go-source tag.
	dirTemplate  string // URL template for a directory
	fileTemplate string // URL template for a file and line
}

// fetchMeta retrieves go-import and go-source meta tag information, using the import path to construct
// a URL as described in "go help importpath".
//
// The importPath argument, as the name suggests, could be any package import
// path. But we only pass module paths.
//
// The discovery site only cares about linking to source, not fetching it (we
// already have it in the module zip file). So we merge the go-import and
// go-source meta tag information, preferring the latter.
func fetchMeta(ctx context.Context, client *Client, importPath string) (_ *sourceMeta, err error) {
	defer derrors.Wrap(&err, "fetchMeta(ctx, client, %q)", importPath)

	uri := importPath
	if !strings.Contains(uri, "/") {
		// Add slash for root of domain.
		uri = uri + "/"
	}
	uri = uri + "?go-get=1"

	resp, err := client.doURL(ctx, "GET", "https://"+uri, true)
	if err != nil {
		resp, err = client.doURL(ctx, "GET", "http://"+uri, false)
		if err != nil {
			return nil, err
		}
	}
	defer resp.Body.Close()
	return parseMeta(importPath, resp.Body)
}

func parseMeta(importPath string, r io.Reader) (sm *sourceMeta, err error) {
	errorMessage := "go-import and go-source meta tags not found"
	// gddo uses an xml parser, and this code is adapted from it.
	d := xml.NewDecoder(r)
	d.Strict = false
metaScan:
	for {
		t, tokenErr := d.Token()
		if tokenErr != nil {
			break metaScan
		}
		switch t := t.(type) {
		case xml.EndElement:
			if strings.EqualFold(t.Name.Local, "head") {
				break metaScan
			}
		case xml.StartElement:
			if strings.EqualFold(t.Name.Local, "body") {
				break metaScan
			}
			if !strings.EqualFold(t.Name.Local, "meta") {
				continue metaScan
			}
			nameAttr := attrValue(t.Attr, "name")
			if nameAttr != "go-import" && nameAttr != "go-source" {
				continue metaScan
			}
			fields := strings.Fields(attrValue(t.Attr, "content"))
			if len(fields) < 1 {
				continue metaScan
			}
			repoRootPrefix := fields[0]
			if !strings.HasPrefix(importPath, repoRootPrefix) ||
				!(len(importPath) == len(repoRootPrefix) || importPath[len(repoRootPrefix)] == '/') {
				// Ignore if root is not a prefix of the  path. This allows a
				// site to use a single error page for multiple repositories.
				continue metaScan
			}
			switch nameAttr {
			case "go-import":
				if len(fields) != 3 {
					errorMessage = "go-import meta tag content attribute does not have three fields"
					continue metaScan
				}
				if fields[1] == "mod" {
					// We can't make source links from a "mod" vcs type, so skip it.
					continue
				}
				if sm != nil {
					sm = nil
					errorMessage = "more than one go-import meta tag found"
					break metaScan
				}
				sm = &sourceMeta{
					repoRootPrefix: repoRootPrefix,
					repoURL:        fields[2],
				}
				// Keep going in the hope of finding a go-source tag.
			case "go-source":
				if len(fields) != 4 {
					errorMessage = "go-source meta tag content attribute does not have four fields"
					continue metaScan
				}
				if sm != nil && sm.repoRootPrefix != repoRootPrefix {
					errorMessage = fmt.Sprintf("import path prefixes %q for go-import and %q for go-source disagree", sm.repoRootPrefix, repoRootPrefix)
					sm = nil
					break metaScan
				}
				// If go-source repo is "_", then default to the go-import repo.
				repoURL := fields[1]
				if repoURL == "_" {
					if sm == nil {
						errorMessage = `go-source repo is "_", but no previous go-import tag`
						break metaScan
					}
					repoURL = sm.repoURL
				}
				sm = &sourceMeta{
					repoRootPrefix: repoRootPrefix,
					repoURL:        repoURL,
					dirTemplate:    fields[2],
					fileTemplate:   fields[3],
				}
				break metaScan
			}
		}
	}
	if sm == nil {
		return nil, fmt.Errorf("%s: %w", errorMessage, derrors.NotFound)
	}
	return sm, nil
}

func attrValue(attrs []xml.Attr, name string) string {
	for _, a := range attrs {
		if strings.EqualFold(a.Name.Local, name) {
			return a.Value
		}
	}
	return ""
}
