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

// Golangorg serves the golang.org web sites.
package main

import (
	"archive/zip"
	"bytes"
	"context"
	"embed"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"go/format"
	"html/template"
	"io"
	"io/fs"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"cloud.google.com/go/datastore"
	"golang.org/x/build/relnote"
	"golang.org/x/build/repos"
	"golang.org/x/website"
	"golang.org/x/website/internal/blog"
	"golang.org/x/website/internal/codewalk"
	"golang.org/x/website/internal/dl"
	"golang.org/x/website/internal/gitfs"
	"golang.org/x/website/internal/history"
	"golang.org/x/website/internal/memcache"
	"golang.org/x/website/internal/pkgdoc"
	"golang.org/x/website/internal/play"
	"golang.org/x/website/internal/redirect"
	"golang.org/x/website/internal/short"
	"golang.org/x/website/internal/talks"
	"golang.org/x/website/internal/tour"
	"golang.org/x/website/internal/web"
	"golang.org/x/website/internal/webtest"
	"rsc.io/markdown"
)

var (
	httpAddr   = flag.String("http", "localhost:6060", "HTTP service address")
	verbose    = flag.Bool("v", false, "verbose mode")
	goroot     = flag.String("goroot", runtime.GOROOT(), "Go root directory")
	contentDir = flag.String("content", "", "path to _content directory")

	runningOnAppEngine = os.Getenv("PORT") != ""

	tipFlag  = flag.Bool("tip", runningOnAppEngine, "load git content for tip.golang.org")
	wikiFlag = flag.Bool("wiki", runningOnAppEngine, "load git content for go.dev/wiki")

	googleAnalytics string
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: golangorg\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	// Running locally, find the local _content directory,
	// so that updates to those files appear on the local dev instance without restarting.
	// On App Engine, leave contentDir empty, so we use the embedded copy,
	// which is much faster to access than the simulated file system.
	if *contentDir == "" && !runningOnAppEngine {
		repoRoot := "../.."
		if _, err := os.Stat("_content"); err == nil {
			repoRoot = "."
		}
		*contentDir = filepath.Join(repoRoot, "_content")
	}

	if runningOnAppEngine {
		log.Print("golang.org server starting")
		*goroot = "_goroot.zip"
		log.SetFlags(log.Lshortfile | log.LstdFlags)
		port := "8080"
		if p := os.Getenv("PORT"); p != "" {
			port = p
		}
		*httpAddr = ":" + port
	}

	flag.Usage = usage
	flag.Parse()

	// Check usage.
	if flag.NArg() > 0 {
		fmt.Fprintln(os.Stderr, "Unexpected arguments.")
		usage()
	}
	if *httpAddr == "" {
		fmt.Fprintln(os.Stderr, "-http must be set")
		usage()
	}

	handler := NewHandler(*contentDir, *goroot)
	handler = webtest.HandlerWithCheck(handler, "/_readycheck",
		testdataFS, "testdata/*.txt")

	if *verbose {
		log.Printf("golang.org server:")
		log.Printf("\tversion = %s", runtime.Version())
		log.Printf("\taddress = %s", *httpAddr)
		log.Printf("\tgoroot = %s", *goroot)
		handler = loggingHandler(handler)
	}

	// Start http server.
	fmt.Fprintf(os.Stderr, "serving http://%s\n", *httpAddr)
	if err := http.ListenAndServe(*httpAddr, handler); err != nil {
		log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
	}
}

//go:embed testdata
var testdataFS embed.FS

// NewHandler returns the http.Handler for the web site,
// given the directory where the content can be found
// (can be "", in which case an internal copy is used)
// and the directory or zip file of the GOROOT.
func NewHandler(contentDir, goroot string) http.Handler {
	mux := http.NewServeMux()

	// Serve files from _content, falling back to GOROOT.

	// Use explicit contentDir if specified, otherwise embedded copy.
	var contentFS fs.FS
	if contentDir != "" {
		contentFS = os.DirFS(contentDir)
	} else {
		contentFS = website.Content()
	}

	var gorootFS fs.FS
	if strings.HasSuffix(goroot, ".zip") {
		z, err := zip.OpenReader(goroot)
		if err != nil {
			log.Fatal(err)
		}
		gorootFS = &seekableFS{z}
	} else {
		gorootFS = os.DirFS(goroot)
	}

	// go.dev/wiki serves content from the very latest Git commit of the wiki repo.
	// Start with the _content/wiki directory as placeholder until Git loads.
	var wikiFS atomicFS
	wikiDefault, err := fs.Sub(contentFS, "wiki")
	if err != nil {
		log.Fatalf("loading default wiki content: %v", err)
	}
	wikiFS.Set(wikiDefault)
	if *wikiFlag {
		go watchGit(&wikiFS, "https://go.googlesource.com/wiki")
	}
	contentFS = &mountFS{contentFS, "wiki", &wikiFS}

	// tip.golang.org serves content from the very latest Git commit
	// of the main Go repo, instead of the one the app is bundled with.
	var tipGoroot atomicFS
	if _, err := newSite(mux, "tip.golang.org", contentFS, &tipGoroot); err != nil {
		log.Fatalf("loading tip site: %v", err)
	}
	if *tipFlag {
		go watchGit(&tipGoroot, "https://go.googlesource.com/go")
	}

	// beta.golang.org is an old name for tip.
	mux.Handle("beta.golang.org/", redirectPrefix("https://tip.golang.org/"))

	// By default, golang.org/foo redirects to go.dev/foo.
	// All the user-facing golang.org subdomains have moved to go.dev subdirectories.
	// There are some exceptions below, like for golang.org/x.
	mux.Handle("golang.org/", redirectPrefix("https://go.dev/"))
	mux.Handle("blog.golang.org/", redirectPrefix("https://go.dev/blog/"))
	mux.Handle("learn.go.dev/", redirectPrefix("https://go.dev/learn/"))
	mux.Handle("talks.golang.org/", redirectPrefix("https://go.dev/talks/"))
	mux.Handle("tour.golang.org/", redirectPrefix("https://go.dev/tour/"))

	// Redirect subdirectory-like domains to the actual subdirectories,
	// for people whose fingers learn to type go.dev instead of golang.org
	// but not the rest of the URL schema change.
	// Note that these domains have to be listed in knownHosts below as well.
	mux.Handle("blog.go.dev/", redirectPrefix("https://go.dev/blog/"))
	mux.Handle("play.go.dev/", redirectPrefix("https://go.dev/play/"))
	mux.Handle("talks.go.dev/", redirectPrefix("https://go.dev/talks/"))
	mux.Handle("tour.go.dev/", redirectPrefix("https://go.dev/tour/"))

	// m.golang.org is an old shortcut for golang.org mail.
	// Gmail itself can serve this redirect, but only on HTTP (not HTTPS).
	// Golang.org's HSTS header tells browsers to use HTTPS for all subdomains,
	// which broke the redirect.
	mux.Handle("m.golang.org/", http.RedirectHandler("https://mail.google.com/a/golang.org/", http.StatusMovedPermanently))

	// Register a redirect handler for tip.golang.org/dl/ to the golang.org download page.
	// (golang.org/dl and golang.google.cn/dl are registered separately.)
	mux.Handle("tip.golang.org/dl/", http.RedirectHandler("https://go.dev/dl/", http.StatusFound))

	// TODO(rsc): The unionFS is a hack until we move the files in a followup CL.
	siteMux := http.NewServeMux()
	godevSite, err := newSite(siteMux, "", contentFS, gorootFS)
	if err != nil {
		log.Fatalf("newSite go.dev: %v", err)
	}
	chinaSite, err := newSite(siteMux, "golang.google.cn", contentFS, gorootFS)
	if err != nil {
		log.Fatalf("newSite golang.google.cn: %v", err)
	}
	if runningOnAppEngine {
		appEngineSetup(mux)
	}
	dl.RegisterHandlers(siteMux, godevSite, "", datastoreClient, memcacheClient)
	dl.RegisterHandlers(siteMux, chinaSite, "golang.google.cn", datastoreClient, memcacheClient)
	mux.Handle("/", siteMux)

	play.RegisterHandlers(mux, godevSite, chinaSite)

	mux.Handle("/explore/", http.StripPrefix("/explore/", redirectPrefix("https://pkg.go.dev/")))
	if err := blog.RegisterFeeds(mux, "", godevSite); err != nil {
		log.Fatalf("blog: %v", err)
	}

	// Note: Only golang.org/x/, no go.dev/x/.
	mux.Handle("golang.org/x/", http.HandlerFunc(xHandler))
	mux.Handle("golang.org/toolchain", http.HandlerFunc(toolchainHandler))

	redirect.Register(mux)

	// Note: Using godevSite (non-China) for global mux registration because there's no sharing in talks.
	// Don't need the hassle of two separate registrations for different domains in siteMux.
	if err := talks.RegisterHandlers(mux, godevSite, contentFS); err != nil {
		log.Fatalf("talks: %v", err)
	}
	if err := tour.RegisterHandlers(mux); err != nil {
		log.Fatalf("tour: %v", err)
	}

	var h http.Handler = mux
	h = addCSP(mux)
	h = hostEnforcerHandler(h)
	h = hostPathHandler(h)
	return h
}

var gorebuild = NewCachedURL("https://gorebuild.storage.googleapis.com/gorebuild.json", 5*time.Minute)

// newSite creates a new site for a given content and goroot file system pair
// and registers it in mux to handle requests for host.
// If host is the empty string, the registrations are for the wildcard host.
func newSite(mux *http.ServeMux, host string, content, goroot fs.FS) (*web.Site, error) {
	fsys := unionFS{content, &hideRootMDFS{&fixSpecsFS{goroot}}}
	site := web.NewSite(fsys)
	site.Funcs(template.FuncMap{
		"googleAnalytics": func() string { return googleAnalytics },
		"googleCN":        func() bool { return host == "golang.google.cn" },
		"gorebuild":       gorebuild.Get,
		"json":            jsonUnmarshal,
		"newest":          newest,
		"now":             func() time.Time { return time.Now() },
		"releases":        func() []*history.Major { return history.Majors },
		"rfc3339":         parseRFC3339,
		"section":         section,
		"version":         func() string { return runtime.Version() },
		"docNext":         releaseNotePreview{goroot}.MergedFragments,
	})
	docs, err := pkgdoc.NewServer(fsys, site, googleCN)
	if err != nil {
		return nil, err
	}

	mux.Handle(host+"/", site)
	mux.Handle(host+"/cmd/", docs)
	mux.Handle(host+"/pkg/", docs)
	mux.Handle(host+"/doc/codewalk/", codewalk.NewServer(fsys, site))
	return site, nil
}

// releaseNotePreview implements a preview of upcoming release notes.
type releaseNotePreview struct {
	goroot fs.FS // goroot provides the doc/next content to use, if any.
}

// MergedFragments returns Markdown obtained by merging release note fragments
// found in the doc/next directory in goroot, to preview relnote generate output.
// An empty string and no error is returned if the doc/next directory doesn't exist.
func (p releaseNotePreview) MergedFragments() (markdownWithEmbeddedHTML template.HTML, _ error) {
	next, err := fs.Sub(p.goroot, "doc/next")
	if err != nil {
		return "", err
	}
	if _, err := fs.Stat(next, "."); os.IsNotExist(err) || errors.Is(err, errNoFileSystem) {
		// No next release note fragments.
		return "", nil
	}
	doc, err := relnote.Merge(next)
	if err != nil {
		return "", fmt.Errorf("relnote.Merge: %v", err)
	}
	// Note: It's possible to render doc, a parsed Markdown document with embedded HTML,
	// into Markdown or HTML. We choose to render to Markdown and let x/website/internal/web
	// handle the remaining conversion to HTML. This means the rendering is more consistent
	// with what'll happen when relnote generate output is added as _content/doc/go1.N.md.
	return template.HTML(markdown.ToMarkdown(doc)), nil
}

func parseRFC3339(s string) (time.Time, error) {
	return time.Parse(time.RFC3339, s)
}

// watchGit is a background goroutine that watches a Git repo for updates.
// When a new commit is available, watchGit downloads the new tree and calls
// fsys.Set to install the new file system.
func watchGit(fsys *atomicFS, repo string) {
	for {
		// watchGit1 runs until it panics (hopefully never).
		// If that happens, sleep 5 minutes and try again.
		watchGit1(fsys, repo)
		time.Sleep(5 * time.Minute)
	}
}

// watchGit1 does the actual work of watchGit and recovers from panics.
func watchGit1(afs *atomicFS, repo string) {
	defer func() {
		if e := recover(); e != nil {
			log.Printf("watchGit %s panic: %v\n%s", repo, e, debug.Stack())
		}
	}()

	var r *gitfs.Repo
	for {
		var err error
		r, err = gitfs.NewRepo(repo)
		if err != nil {
			log.Printf("watchGit %s: %v", repo, err)
			time.Sleep(1 * time.Minute)
			continue
		}
		break
	}

	var h gitfs.Hash
	for {
		var fsys fs.FS
		var err error
		h, fsys, err = r.Clone("HEAD")
		if err != nil {
			log.Printf("watchGit %s: %v", repo, err)
			time.Sleep(1 * time.Minute)
			continue
		}
		afs.Set(fsys)
		break
	}

	for {
		time.Sleep(5 * time.Minute)
		h2, err := r.Resolve("HEAD")
		if err != nil {
			log.Printf("watchGit %s: %v", repo, err)
			continue
		}
		if h2 != h {
			fsys, err := r.CloneHash(h2)
			if err != nil {
				log.Printf("watchGit %s: %v", repo, err)
				time.Sleep(1 * time.Minute)
				continue
			}
			afs.Set(fsys)
			h = h2
		}
	}
}

var datastoreClient *datastore.Client
var memcacheClient *memcache.Client

func appEngineSetup(mux *http.ServeMux) {
	googleAnalytics = os.Getenv("GOLANGORG_ANALYTICS")

	ctx := context.Background()

	var err error
	datastoreClient, err = datastore.NewClient(ctx, "")
	if err != nil {
		if strings.Contains(err.Error(), "missing project") {
			log.Fatalf("Missing datastore project. Set the DATASTORE_PROJECT_ID env variable. Use `gcloud beta emulators datastore` to start a local datastore.")
		}
		log.Fatalf("datastore.NewClient: %v.", err)
	}

	redisAddr := os.Getenv("GOLANGORG_REDIS_ADDR")
	if redisAddr == "" {
		log.Fatalf("Missing redis server for golangorg in production mode. set GOLANGORG_REDIS_ADDR environment variable.")
	}
	memcacheClient = memcache.New(redisAddr)

	short.RegisterHandlers(mux, "", datastoreClient, memcacheClient)

	log.Println("AppEngine initialization complete")
}

type fmtResponse struct {
	Body  string
	Error string
}

// fmtHandler takes a Go program in its "body" form value, formats it with
// standard gofmt formatting, and writes a fmtResponse as a JSON object.
func fmtHandler(w http.ResponseWriter, r *http.Request) {
	resp := new(fmtResponse)
	body, err := format.Source([]byte(r.FormValue("body")))
	if err != nil {
		resp.Error = err.Error()
	} else {
		resp.Body = string(body)
	}
	w.Header().Set("Content-type", "application/json; charset=utf-8")
	json.NewEncoder(w).Encode(resp)
}

var validHosts = map[string]bool{
	"golang.org":       true,
	"golang.google.cn": true,
	"beta.golang.org":  true,
	"blog.golang.org":  true,
	"m.golang.org":     true,
	"talks.golang.org": true,
	"tip.golang.org":   true,
	"tour.golang.org":  true,

	"go.dev":       true,
	"blog.go.dev":  true,
	"learn.go.dev": true,
	"play.go.dev":  true,
	"talks.go.dev": true,
	"tour.go.dev":  true,
}

// hostEnforcerHandler redirects http://foo.golang.org/bar to https://golang.org/bar.
// It also forces all requests coming from China for golang.org to use golang.google.cn.
func hostEnforcerHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		isHTTPS := r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" || r.URL.Scheme == "https"
		defaultHost := "go.dev"
		host := strings.ToLower(r.Host)
		isValidHost := validHosts[host]

		if googleCN(r) && !strings.HasSuffix(host, "google.cn") {
			// golang.google.cn is the only web site in China.
			defaultHost = "golang.google.cn"
			isValidHost = strings.ToLower(r.Host) == defaultHost
		}

		if !isHTTPS || !isValidHost {
			r.URL.Scheme = "https"
			if isValidHost {
				r.URL.Host = r.Host
			} else {
				r.URL.Host = defaultHost
			}
			http.Redirect(w, r, r.URL.String(), http.StatusFound)
			return
		}

		w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
		h.ServeHTTP(w, r)
	})
}

// hostPathHandler infers the host from the first element of the URL path
// when the actual host is a testing domain (localhost or *.appspot.com).
// It also rewrites the output HTML and Location headers in that case to
// link back to URLs on the test site.
func hostPathHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Host != "localhost" && !strings.HasPrefix(r.Host, "localhost:") && !strings.HasSuffix(r.Host, ".appspot.com") {
			h.ServeHTTP(w, r)
			return
		}

		elem, rest := strings.TrimPrefix(r.URL.Path, "/"), ""
		if i := strings.Index(elem, "/"); i >= 0 {
			if elem[:i] == "tour" {
				// The Angular router serving /tour/ fails badly when it sees /go.dev/tour/.
				// Just take http://localhost/tour/ as meaning /go.dev/tour/ instead of redirecting.
				elem, rest = "go.dev", elem
			} else {
				elem, rest = elem[:i], elem[i+1:]
			}
		}
		if !validHosts[elem] {
			u := "/go.dev" + r.URL.EscapedPath()
			if r.URL.RawQuery != "" {
				u += "?" + r.URL.RawQuery
			}
			http.Redirect(w, r, u, http.StatusTemporaryRedirect)
			return
		}

		r.Host = elem
		r.URL.Scheme = "https"
		r.URL.Host = elem
		r.URL.Path = "/" + rest

		log.Print(r.URL.String())

		lw := &linkRewriter{ResponseWriter: w, host: r.Host, tour: strings.HasPrefix(r.URL.Path, "/tour/")}
		h.ServeHTTP(lw, r)
		lw.Flush()
	})
}

// A linkRewriter is a ResponseWriter that rewrites links in HTML output.
// It rewrites relative links /foo to be /host/foo, and it rewrites any link
// https://h/foo, where h is in validHosts, to be /h/foo. This corrects the
// links to have the right form for the test server.
type linkRewriter struct {
	http.ResponseWriter
	host string
	tour bool // is this go.dev/tour/?
	buf  []byte
	ct   string // content-type
}

func (r *linkRewriter) WriteHeader(code int) {
	loc := r.Header().Get("Location")
	delete(r.Header(), "Content-Length") // we might change the content
	if strings.HasPrefix(loc, "/") && !strings.HasPrefix(loc, "/tour/") {
		r.Header().Set("Location", "/"+r.host+loc)
	} else if u, _ := url.Parse(loc); u != nil && validHosts[u.Host] {
		r.Header().Set("Location", "/"+u.Host+"/"+strings.TrimPrefix(u.Path, "/")+u.RawQuery)
	}
	r.ResponseWriter.WriteHeader(code)
}

func (r *linkRewriter) Write(data []byte) (int, error) {
	if r.ct == "" {
		ct := r.Header().Get("Content-Type")
		if ct == "" {
			// Note: should use first 512 bytes, but first write is fine for our purposes.
			ct = http.DetectContentType(data)
		}
		r.ct = ct
	}
	if !strings.HasPrefix(r.ct, "text/html") {
		return r.ResponseWriter.Write(data)
	}
	r.buf = append(r.buf, data...)
	return len(data), nil
}

func (r *linkRewriter) Flush() {
	var repl []string
	if !r.tour {
		repl = []string{
			`href="/`, `href="/` + r.host + `/`,
			`src="/`, `src="/` + r.host + `/`,
		}
	}
	for host := range validHosts {
		repl = append(repl, `href="https://`+host, `href="/`+host)
		repl = append(repl, `src="https://`+host, `src="/`+host)
	}
	strings.NewReplacer(repl...).WriteString(r.ResponseWriter, string(r.buf))
	r.buf = nil
}

func loggingHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s\t%s", r.RemoteAddr, r.URL)
		h.ServeHTTP(w, r)
	})
}

func xHandler(w http.ResponseWriter, r *http.Request) {
	if !strings.HasPrefix(r.URL.Path, "/x/") {
		// Shouldn't happen if handler is registered correctly.
		http.Redirect(w, r, "https://pkg.go.dev/golang.org/x", http.StatusTemporaryRedirect)
		return
	}
	proj, suffix := strings.TrimPrefix(r.URL.Path, "/x/"), ""
	if i := strings.Index(proj, "/"); i != -1 {
		proj, suffix = proj[:i], proj[i:]
	}
	if proj == "" {
		http.Redirect(w, r, "https://pkg.go.dev/golang.org/x", http.StatusTemporaryRedirect)
		return
	}
	repo, ok := repos.ByGerritProject[proj]
	if !ok || !strings.HasPrefix(repo.ImportPath, "golang.org/x/") {
		http.NotFound(w, r)
		return
	}
	if suffix == "/info/refs" && strings.HasPrefix(r.URL.Query().Get("service"), "git-") && repo.GoGerritProject != "" {
		// Someone is running 'git clone https://golang.org/x/repo'.
		// We want the eventual git checkout to have the right origin (go.googlesource.com)
		// and not just keep hitting golang.org all the time.
		// A redirect would work for this git command but not record the result.
		// Instead, print a useful error for the user.
		http.Error(w, fmt.Sprintf("Use 'git clone https://go.googlesource.com/%s' instead.", repo.GoGerritProject), http.StatusNotFound)
		return
	}
	data := struct {
		Proj   string // Gerrit project ("net", "sys", etc)
		Suffix string // optional "/path" for requests like /x/PROJ/path
	}{proj, suffix}
	if err := xTemplate.Execute(w, data); err != nil {
		log.Println("xHandler:", err)
	}
}

var xTemplate = template.Must(template.New("x").Parse(`<!DOCTYPE html>
<html lang="en">
<title>The Go Programming Language</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="golang.org/x/{{.Proj}} git https://go.googlesource.com/{{.Proj}}">
<meta http-equiv="refresh" content="0; url=https://pkg.go.dev/golang.org/x/{{.Proj}}{{.Suffix}}">
</head>
<body>
<a href="https://pkg.go.dev/golang.org/x/{{.Proj}}{{.Suffix}}">Redirecting to documentation...</a>
</body>
</html>
`))

func toolchainHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/toolchain" {
		// Shouldn't happen if handler is registered correctly.
		http.NotFound(w, r)
		return
	}
	w.Write(toolchainPage)
}

var toolchainPage = []byte(`<!DOCTYPE html>
<html lang="en">
<head>
<title>The Go Programming Language</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="golang.org/toolchain mod https://go.dev/dl/mod">
<meta http-equiv="refresh" content="0; url=https://go.dev/dl/">
</head>
<body>
golang.org/toolchain is the module form of the Go toolchain releases.
<a href="https://go.dev/dl/">Redirecting to Go toolchain download page...</a>
</body>
</html>
`)

var _ fs.ReadDirFS = unionFS{}

// A unionFS is an FS presenting the union of the file systems in the slice.
// If multiple file systems provide a particular file, Open uses the FS listed earlier in the slice.
// If multiple file systems provide a particular directory, ReadDir presents the
// concatenation of all the directories listed in the slice (with duplicates removed).
type unionFS []fs.FS

func (fsys unionFS) Open(name string) (fs.File, error) {
	var errOut error
	for _, sub := range fsys {
		f, err := sub.Open(name)
		if err == nil {
			// Note: Should technically check for directory
			// and return a synthetic directory that merges
			// reads from all the matching directories,
			// but all the directory reads in internal/godoc
			// come from fsys.ReadDir, which does that for us.
			// So we can ignore direct f.ReadDir calls.
			return f, nil
		}
		if errOut == nil {
			errOut = err
		}
	}
	return nil, errOut
}

func (fsys unionFS) ReadDir(name string) ([]fs.DirEntry, error) {
	var all []fs.DirEntry
	var seen map[string]bool // seen[name] is true if name is listed in all; lazily initialized
	var errOut error
	for _, sub := range fsys {
		list, err := fs.ReadDir(sub, name)
		if err != nil {
			errOut = err
		}
		if len(all) == 0 {
			all = append(all, list...)
		} else {
			if seen == nil {
				// Initialize seen only after we get two different directory listings.
				seen = make(map[string]bool)
				for _, d := range all {
					seen[d.Name()] = true
				}
			}
			for _, d := range list {
				name := d.Name()
				if !seen[name] {
					seen[name] = true
					all = append(all, d)
				}
			}
		}
	}
	if len(all) > 0 {
		return all, nil
	}
	return nil, errOut
}

// A fixSpecsFS is an FS mapping /ref/mem.html and /ref/spec.html to
// /doc/go_mem.html and /doc/go_spec.html.
var _ fs.FS = &fixSpecsFS{}

type fixSpecsFS struct {
	fs fs.FS
}

func (fsys fixSpecsFS) Open(name string) (fs.File, error) {
	switch name {
	case "ref/mem.html", "ref/spec.html":
		if f, err := fsys.fs.Open(name); err == nil {
			// Let Go distribution win if they move.
			return f, nil
		}
		// Otherwise fall back to doc/go_*.html
		name = "doc/go_" + strings.TrimPrefix(name, "ref/")
		return fsys.fs.Open(name)

	case "doc/go_mem.html", "doc/go_spec.html":
		data := []byte("<!--{\n\t\"Redirect\": \"/ref/" + strings.TrimPrefix(strings.TrimSuffix(name, ".html"), "doc/go_") + "\"\n}-->\n")
		return &memFile{path.Base(name), bytes.NewReader(data)}, nil
	}

	return fsys.fs.Open(name)
}

// A hideRootMDFS is an FS that hides *.md files in the root directory.
// We use this to hide the Go repository's CONTRIBUTING.md,
// README.md, and SECURITY.md. The last is particularly problematic
// when running locally on a Mac, because it can be opened as
// security.md, which takes priority over _content/security.html.
// Same for wiki.
type hideRootMDFS struct {
	fs fs.FS
}

func (fsys hideRootMDFS) Open(name string) (fs.File, error) {
	if !strings.Contains(name, "/") && strings.HasSuffix(name, ".md") {
		return nil, errors.New(".md file not available")
	}
	switch name {
	case "wiki/README.md", "wiki/CONTRIBUTING.md", "wiki/LICENSE", "wiki/PATENTS", "wiki/codereview.cfg":
		return nil, errors.New("wiki meta file not available")
	}
	return fsys.fs.Open(name)
}

// A seekableFS is an FS wrapper that makes every file seekable
// by reading it entirely into memory when it is opened and then
// serving read operations (including seek) from the memory copy.
type seekableFS struct {
	fs fs.FS
}

func (s *seekableFS) Open(name string) (fs.File, error) {
	f, err := s.fs.Open(name)
	if err != nil {
		return nil, err
	}
	info, err := f.Stat()
	if err != nil {
		f.Close()
		return nil, err
	}
	if info.IsDir() {
		return f, nil
	}
	data, err := ioutil.ReadAll(f)
	if err != nil {
		f.Close()
		return nil, err
	}
	var sf seekableFile
	sf.File = f
	sf.Reset(data)
	return &sf, nil
}

// A seekableFile is a fs.File augmented by an in-memory copy of the file data to allow use of Seek.
type seekableFile struct {
	bytes.Reader
	fs.File
}

// Read calls f.Reader.Read.
// Both f.Reader and f.File have Read methods - a conflict - so f inherits neither.
// This method calls the one we want.
func (f *seekableFile) Read(b []byte) (int, error) {
	return f.Reader.Read(b)
}

// A memFile is an fs.File implementation backed by in-memory data.
type memFile struct {
	name string
	*bytes.Reader
}

func (f *memFile) Stat() (fs.FileInfo, error) { return f, nil }
func (f *memFile) Name() string               { return f.name }
func (*memFile) Mode() fs.FileMode            { return 0444 }
func (*memFile) ModTime() time.Time           { return time.Time{} }
func (*memFile) IsDir() bool                  { return false }
func (*memFile) Sys() interface{}             { return nil }
func (*memFile) Close() error                 { return nil }

// An atomicFS is an fs.FS value safe for reading from multiple goroutines
// as well as updating (assigning a different fs.FS to use in future read requests).
type atomicFS struct {
	v atomic.Value
}

// Set sets the file system used by future calls to Open.
func (a *atomicFS) Set(fsys fs.FS) {
	a.v.Store(&fsys)
}

// A mountFS is a root FS with a second FS mounted at a specific location.
type mountFS struct {
	old fs.FS  // root file system
	dir string // mount point
	new fs.FS  // fs mounted on dir
}

func (m *mountFS) Open(name string) (fs.File, error) {
	if name == m.dir {
		return m.new.Open(".")
	}
	if strings.HasPrefix(name, m.dir) && len(name) > len(m.dir) && name[len(m.dir)] == '/' {
		return m.new.Open(name[len(m.dir)+1:])
	}
	return m.old.Open(name)
}

var errNoFileSystem = errors.New("no file system")

// Open returns fsys.Open(name) where fsys is the file system passed to the most recent call to Set.
// If there has been no call to Set, Open returns errNoFileSystem, an error with text “no file system”.
func (a *atomicFS) Open(name string) (fs.File, error) {
	fsys, _ := a.v.Load().(*fs.FS)
	if fsys == nil {
		return nil, &fs.PathError{Path: name, Op: "open", Err: errNoFileSystem}
	}
	return (*fsys).Open(name)
}

func redirectPrefix(prefix string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		url := strings.TrimSuffix(prefix, "/") + "/" + strings.TrimPrefix(r.URL.Path, "/")
		if r.URL.RawQuery != "" {
			url += "?" + r.URL.RawQuery
		}
		http.Redirect(w, r, url, http.StatusMovedPermanently)
	})
}

type CachedURL struct {
	url     string
	timeout time.Duration

	mu      sync.Mutex
	data    []byte
	err     error
	etag    string
	updated time.Time
}

func NewCachedURL(url string, timeout time.Duration) *CachedURL {
	return &CachedURL{url: url, timeout: timeout}
}

func (c *CachedURL) Get() (data []byte, err error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	if time.Since(c.updated) < c.timeout {
		return c.data, c.err
	}
	defer func() {
		c.updated = time.Now()
		c.data, c.err = data, err
	}()

	cli := &http.Client{Timeout: 60 * time.Second}
	req, err := http.NewRequest("GET", c.url, nil)
	if err != nil {
		return nil, err
	}
	if c.etag != "" {
		req.Header.Set("If-None-Match", c.etag)
	}
	resp, err := cli.Do(req)
	if err != nil {
		return nil, fmt.Errorf("loading rebuild report JSON: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode == http.StatusNotModified {
		// Unmodified.
		log.Printf("checked %s - unmodified", c.url)
		return c.data, c.err
	}
	log.Printf("reloading %s", c.url)
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("loading rebuild report JSON: %v", resp.Status)
	}
	c.etag = resp.Header.Get("Etag")
	data, err = io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("loading rebuild report JSON: %v", err)
	}
	return data, nil
}

func jsonUnmarshal(data []byte) (any, error) {
	var x any
	err := json.Unmarshal(data, &x)
	return x, err
}
