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

// Support for custom domains.

package modfetch

import (
	"encoding/xml"
	"fmt"
	"io"
	"net/url"
	"os"
	"strings"

	"cmd/go/internal/modfetch/codehost"
	web "cmd/go/internal/web2"
)

// metaImport represents the parsed <meta name="go-import"
// content="prefix vcs reporoot" /> tags from HTML files.
type metaImport struct {
	Prefix, VCS, RepoRoot string
}

func lookupCustomDomain(path string) (Repo, error) {
	var body io.ReadCloser
	err := web.Get(
		"https://"+path+"?go-get=1",
		web.Non200OK(),
		web.Body(&body),
	)
	if body != nil {
		defer body.Close()
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "FindRepo: %v\n", err)
		return nil, err
	}
	// Note: accepting a non-200 OK here, so people can serve a
	// meta import in their http 404 page.
	imports, err := parseMetaGoImports(body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "findRepo: %v\n", err)
		return nil, err
	}
	if len(imports) == 0 {
		return nil, fmt.Errorf("unknown module %s: no go-import tags", path)
	}

	// First look for new module definition.
	for _, imp := range imports {
		if path == imp.Prefix || strings.HasPrefix(path, imp.Prefix+"/") {
			if imp.VCS == "mod" {
				u, err := url.Parse(imp.RepoRoot)
				if err != nil {
					return nil, fmt.Errorf("invalid module URL %q", imp.RepoRoot)
				} else if u.Scheme != "https" {
					// TODO: Allow -insecure flag as a build flag?
					return nil, fmt.Errorf("invalid module URL %q: must be HTTPS", imp.RepoRoot)
				}
				return newProxyRepo(imp.RepoRoot, imp.Prefix), nil
			}
		}
	}

	// Fall back to redirections to known hosting services.
	for _, imp := range imports {
		if path == imp.Prefix {
			if !strings.HasPrefix(imp.RepoRoot, "https://") {
				// TODO: Allow -insecure flag as a build flag?
				return nil, fmt.Errorf("invalid server URL %q: must be HTTPS", imp.RepoRoot)
			}
			codePath := strings.TrimPrefix(imp.RepoRoot, "https://")
			if code, err := lookupCodeHost(codePath, true); err != errNotHosted {
				if err != nil {
					return nil, err
				}
				return newCodeRepo(&customPrefix{code, imp.Prefix}, imp.Prefix)
			}
			return nil, fmt.Errorf("unknown VCS, Repo: %s, %s", imp.VCS, imp.RepoRoot)
		}
		if strings.HasPrefix(path, imp.Prefix+"/") {
			return nil, &ModuleSubdirError{imp.Prefix}
		}
	}
	return nil, fmt.Errorf("unknown module %s: no matching go-import tags", path)
}

type ModuleSubdirError struct {
	ModulePath string
}

func (e *ModuleSubdirError) Error() string {
	return fmt.Sprintf("module root is %q", e.ModulePath)
}

type customPrefix struct {
	codehost.Repo
	root string
}

func (c *customPrefix) Root() string {
	return c.root
}

// parseMetaGoImports returns meta imports from the HTML in r.
// Parsing ends at the end of the <head> section or the beginning of the <body>.
func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) {
	d := xml.NewDecoder(r)
	d.CharsetReader = charsetReader
	d.Strict = false
	var t xml.Token
	for {
		t, err = d.RawToken()
		if err != nil {
			if err == io.EOF || len(imports) > 0 {
				err = nil
			}
			return
		}
		if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
			return
		}
		if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
			return
		}
		e, ok := t.(xml.StartElement)
		if !ok || !strings.EqualFold(e.Name.Local, "meta") {
			continue
		}
		if attrValue(e.Attr, "name") != "go-import" {
			continue
		}
		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {
			imports = append(imports, metaImport{
				Prefix:   f[0],
				VCS:      f[1],
				RepoRoot: f[2],
			})
		}
	}
}

// attrValue returns the attribute value for the case-insensitive key
// `name', or the empty string if nothing is found.
func attrValue(attrs []xml.Attr, name string) string {
	for _, a := range attrs {
		if strings.EqualFold(a.Name.Local, name) {
			return a.Value
		}
	}
	return ""
}

// charsetReader returns a reader for the given charset. Currently
// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful
// error which is printed by go get, so the user can find why the package
// wasn't downloaded if the encoding is not supported. Note that, in
// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters
// greater than 0x7f are not rejected).
func charsetReader(charset string, input io.Reader) (io.Reader, error) {
	switch strings.ToLower(charset) {
	case "ascii":
		return input, nil
	default:
		return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
	}
}
