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

//go:build go1.16
// +build go1.16

package web

import (
	"bytes"
	"fmt"
	"html"
	"html/template"
	"io"
	"io/fs"
	"log"
	"net/http"
	"path"
	"regexp"
	"runtime"
	"strconv"
	"strings"

	"golang.org/x/website/internal/api"
	"golang.org/x/website/internal/pkgdoc"
	"golang.org/x/website/internal/spec"
	"golang.org/x/website/internal/texthtml"
)

// Site is a website served from a file system.
type Site struct {
	fs  fs.FS
	api api.DB

	mux        *http.ServeMux
	fileServer http.Handler

	Templates *template.Template

	// GoogleCN reports whether this request should be marked GoogleCN.
	// If the function is nil, no requests are marked GoogleCN.
	GoogleCN func(*http.Request) bool

	// GoogleAnalytics optionally adds Google Analytics via the provided
	// tracking ID to each page.
	GoogleAnalytics string

	docFuncs template.FuncMap
}

// NewSite returns a new Presentation from a file system.
func NewSite(fsys fs.FS) (*Site, error) {
	apiDB, err := api.Load(fsys)
	if err != nil {
		return nil, err
	}
	p := &Site{
		fs:         fsys,
		api:        apiDB,
		mux:        http.NewServeMux(),
		fileServer: http.FileServer(http.FS(fsys)),
	}
	docs := &docServer{
		p: p,
		d: pkgdoc.NewDocs(fsys),
	}
	p.mux.Handle("/cmd/", docs)
	p.mux.Handle("/pkg/", docs)
	p.mux.HandleFunc("/", p.serveFile)
	p.initDocFuncs()

	t, err := template.New("").Funcs(siteFuncs).ParseFS(fsys, "lib/godoc/*.html")
	if err != nil {
		return nil, err
	}
	p.Templates = t

	return p, nil
}

// ServeError responds to the request with the given error.
func (s *Site) ServeError(w http.ResponseWriter, r *http.Request, err error) {
	w.WriteHeader(http.StatusNotFound)
	s.ServePage(w, r, Page{
		Title:    r.URL.Path,
		Template: "error.html",
		Data:     err,
	})
}

// ServeHTTP implements http.Handler, dispatching the request appropriately.
func (s *Site) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	s.mux.ServeHTTP(w, r)
}

// ServePage responds to the request with the content described by page.
func (s *Site) ServePage(w http.ResponseWriter, r *http.Request, page Page) {
	page = s.fullPage(r, page)
	applyTemplateToResponseWriter(w, s.Templates.Lookup("site.html"), &page)
}

// A Page describes the contents of a webpage to be served.
//
// A Page's Methods are for use by the templates rendering the page.
type Page struct {
	Title    string // <h1>
	TabTitle string // prefix in <title>; defaults to Title
	Subtitle string // subtitle (date for spec, memory model)
	SrcPath  string // path to file in /src for text view

	// Template and Data describe the data to be
	// rendered into the overall site frame template.
	// If Template is empty, then Data should be a template.HTML
	// holding raw HTML to render into the site frame.
	// Otherwise, Template should be the name of a template file
	// in _content/lib/godoc (for example, "package.html"),
	// and that template will be executed
	// (with the *Page as its data argument) to produce HTML.
	//
	// The overall site template site.html is also invoked with
	// the *Page as its data argument. It is what arranges to call Template.
	Template string      // template to apply to data (empty string when Data is raw template.HTML)
	Data     interface{} // data to be rendered into page frame

	// Filled in automatically by ServePage
	GoogleCN        bool   // page is being served from golang.google.cn
	GoogleAnalytics string // Google Analytics tag
	Version         string // current Go version

	site *Site
}

// fullPage returns a copy of page with the “automatic” fields filled in.
func (s *Site) fullPage(r *http.Request, page Page) Page {
	if page.TabTitle == "" {
		page.TabTitle = page.Title
	}
	page.Version = runtime.Version()
	page.GoogleCN = s.googleCN(r)
	page.GoogleAnalytics = s.GoogleAnalytics
	page.site = s
	return page
}

// Invoke invokes the template with the given name on
// a copy of p with .Data set to data, returning the resulting HTML.
func (p *Page) Invoke(name string, data interface{}) template.HTML {
	t := p.site.Templates.Lookup(name)
	var buf bytes.Buffer
	p1 := *p
	p1.Data = data
	if err := t.Execute(&buf, &p1); err != nil {
		log.Printf("%s.Execute: %s", t.Name(), err)
	}
	return template.HTML(buf.String())
}

type writeErrorSaver struct {
	w   io.Writer
	err error
}

func (w *writeErrorSaver) Write(p []byte) (int, error) {
	n, err := w.w.Write(p)
	if err != nil {
		w.err = err
	}
	return n, err
}

// applyTemplateToResponseWriter uses an http.ResponseWriter as the io.Writer
// for the call to template.Execute.  It uses an io.Writer wrapper to capture
// errors from the underlying http.ResponseWriter.  Errors are logged only when
// they come from the template processing and not the Writer; this avoid
// polluting log files with error messages due to networking issues, such as
// client disconnects and http HEAD protocol violations.
func applyTemplateToResponseWriter(rw http.ResponseWriter, t *template.Template, data interface{}) {
	w := &writeErrorSaver{w: rw}
	err := t.Execute(w, data)
	// There are some cases where template.Execute does not return an error when
	// rw returns an error, and some where it does.  So check w.err first.
	if w.err == nil && err != nil {
		// Log template errors.
		log.Printf("%s.Execute: %s", t.Name(), err)
	}
}

func (s *Site) serveFile(w http.ResponseWriter, r *http.Request) {
	if strings.HasSuffix(r.URL.Path, "/index.html") {
		// We'll show index.html for the directory.
		// Use the dir/ version as canonical instead of dir/index.html.
		http.Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len("index.html")], http.StatusMovedPermanently)
		return
	}

	// Check to see if we need to redirect or serve another file.
	abspath := r.URL.Path
	relpath := path.Clean(strings.TrimPrefix(abspath, "/"))
	if f := open(s.fs, relpath); f != nil {
		if f.Path != abspath {
			// Redirect to canonical path.
			http.Redirect(w, r, f.Path, http.StatusMovedPermanently)
			return
		}
		// Serve from the actual filesystem path.
		s.serveHTML(w, r, f)
		return
	}

	dir, err := fs.Stat(s.fs, relpath)
	if err != nil {
		// Check for spurious trailing slash.
		if strings.HasSuffix(abspath, "/") {
			trimmed := relpath[:len(relpath)-1]
			if _, err := fs.Stat(s.fs, trimmed); err == nil ||
				open(s.fs, trimmed) != nil {
				http.Redirect(w, r, "/"+trimmed, http.StatusMovedPermanently)
				return
			}
		}
		s.ServeError(w, r, err)
		return
	}

	if dir != nil && dir.IsDir() {
		if maybeRedirect(w, r) {
			return
		}
		s.serveDir(w, r, relpath)
		return
	}

	if isTextFile(s.fs, relpath) {
		if maybeRedirectFile(w, r) {
			return
		}
		s.serveText(w, r, relpath)
		return
	}

	s.fileServer.ServeHTTP(w, r)
}

func maybeRedirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
	canonical := path.Clean(r.URL.Path)
	if !strings.HasSuffix(canonical, "/") {
		canonical += "/"
	}
	if r.URL.Path != canonical {
		url := *r.URL
		url.Path = canonical
		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
		redirected = true
	}
	return
}

func maybeRedirectFile(w http.ResponseWriter, r *http.Request) (redirected bool) {
	c := path.Clean(r.URL.Path)
	c = strings.TrimRight(c, "/")
	if r.URL.Path != c {
		url := *r.URL
		url.Path = c
		http.Redirect(w, r, url.String(), http.StatusMovedPermanently)
		redirected = true
	}
	return
}

var doctype = []byte("<!DOCTYPE ")

func (s *Site) serveHTML(w http.ResponseWriter, r *http.Request, f *file) {
	src := f.Body
	isMarkdown := strings.HasSuffix(f.FilePath, ".md")

	// if it begins with "<!DOCTYPE " assume it is standalone
	// html that doesn't need the template wrapping.
	if bytes.HasPrefix(src, doctype) {
		w.Write(src)
		return
	}

	page := Page{
		Title:    f.Title,
		Subtitle: f.Subtitle,
	}

	// evaluate as template if indicated
	if f.Template {
		page = s.fullPage(r, page)
		tmpl, err := template.New("main").Funcs(s.docFuncs).Parse(string(src))
		if err != nil {
			log.Printf("parsing template %s: %v", f.Path, err)
			s.ServeError(w, r, err)
			return
		}
		var buf bytes.Buffer
		if err := tmpl.Execute(&buf, page); err != nil {
			log.Printf("executing template %s: %v", f.Path, err)
			s.ServeError(w, r, err)
			return
		}
		src = buf.Bytes()
	}

	// Apply markdown as indicated.
	// (Note template applies before Markdown.)
	if isMarkdown {
		html, err := renderMarkdown(src)
		if err != nil {
			log.Printf("executing markdown %s: %v", f.Path, err)
			s.ServeError(w, r, err)
			return
		}
		src = html
	}

	// if it's the language spec, add tags to EBNF productions
	if strings.HasSuffix(f.FilePath, "go_spec.html") {
		var buf bytes.Buffer
		spec.Linkify(&buf, src)
		src = buf.Bytes()
	}

	page.Data = template.HTML(src)
	s.ServePage(w, r, page)
}

func (s *Site) serveDir(w http.ResponseWriter, r *http.Request, relpath string) {
	if maybeRedirect(w, r) {
		return
	}

	list, err := fs.ReadDir(s.fs, relpath)
	if err != nil {
		s.ServeError(w, r, err)
		return
	}

	var info []fs.FileInfo
	for _, d := range list {
		i, err := d.Info()
		if err == nil {
			info = append(info, i)
		}
	}

	s.ServePage(w, r, Page{
		Title:    "Directory",
		SrcPath:  relpath,
		TabTitle: relpath,
		Template: "dirlist.html",
		Data:     info,
	})
}

func (s *Site) serveText(w http.ResponseWriter, r *http.Request, relpath string) {
	src, err := fs.ReadFile(s.fs, relpath)
	if err != nil {
		log.Printf("ReadFile: %s", err)
		s.ServeError(w, r, err)
		return
	}

	if r.FormValue("m") == "text" {
		s.serveRawText(w, src)
		return
	}

	cfg := texthtml.Config{
		GoComments: path.Ext(relpath) == ".go",
		Highlight:  r.FormValue("h"),
		Selection:  rangeSelection(r.FormValue("s")),
		Line:       1,
	}

	var buf bytes.Buffer
	buf.WriteString("<pre>")
	buf.Write(texthtml.Format(src, cfg))
	buf.WriteString("</pre>")

	fmt.Fprintf(&buf, `<p><a href="/%s?m=text">View as plain text</a></p>`, html.EscapeString(relpath))

	title := "Text file"
	if strings.HasSuffix(relpath, ".go") {
		title = "Source file"
	}
	s.ServePage(w, r, Page{
		Title:    title,
		SrcPath:  relpath,
		TabTitle: relpath,
		Data:     template.HTML(buf.String()),
	})
}

var selRx = regexp.MustCompile(`^([0-9]+):([0-9]+)`)

// rangeSelection computes the Selection for a text range described
// by the argument str, of the form Start:End, where Start and End
// are decimal byte offsets.
func rangeSelection(str string) texthtml.Selection {
	m := selRx.FindStringSubmatch(str)
	if len(m) >= 2 {
		from, _ := strconv.Atoi(m[1])
		to, _ := strconv.Atoi(m[2])
		if from < to {
			return texthtml.Spans(texthtml.Span{Start: from, End: to})
		}
	}
	return nil
}

func (s *Site) serveRawText(w http.ResponseWriter, text []byte) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Write(text)
}

func (s *Site) googleCN(r *http.Request) bool {
	return s.GoogleCN != nil && s.GoogleCN(r)
}
