// Copyright 2020 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 web

import (
	"bytes"
	"fmt"
	"io/fs"
	"net/http"
	"net/url"
	"path"
	"regexp"
	"strings"
	"unicode/utf8"

	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/ast"
	"github.com/yuin/goldmark/extension"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/renderer/html"
	"github.com/yuin/goldmark/text"
	"github.com/yuin/goldmark/util"
	"golang.org/x/website/internal/backport/html/template"
	"golang.org/x/website/internal/tmplfunc"
)

// RenderContent returns the HTML rendering for the page using the named base template
// (the standard base template is "site.tmpl").
func (site *Site) RenderContent(p Page, tmpl string) (template.HTML, error) {
	html, err := site.renderHTML(p, tmpl, &http.Request{URL: &url.URL{Path: "/missingurl"}})
	if err != nil {
		return "", err
	}
	return template.HTML(html), nil
}

// renderHTML renders and returns the Content and framed HTML for the page.
func (site *Site) renderHTML(p Page, tmpl string, r *http.Request) ([]byte, error) {
	// Clone p, because we are going to set its Content key-value pair.
	p2 := make(Page)
	for k, v := range p {
		p2[k] = v
	}
	p = p2

	url, ok := p["URL"].(string)
	if !ok {
		// Set URL - caller did not.
		p["URL"] = r.URL.Path
	}
	file, _ := p["File"].(string)
	data, _ := p["FileData"].(string)

	// Load base template.
	base, err := site.readFile(".", tmpl)
	if err != nil {
		return nil, err
	}

	dir := strings.Trim(path.Dir(url), "/")
	if dir == "" {
		dir = "."
	}
	sd := &siteDir{site, dir}

	t := template.New("site.tmpl").Funcs(template.FuncMap{
		"add":          func(a, b int) int { return a + b },
		"sub":          func(a, b int) int { return a - b },
		"mul":          func(a, b int) int { return a * b },
		"div":          func(a, b int) int { return a / b },
		"code":         sd.code,
		"data":         sd.data,
		"page":         sd.page,
		"pages":        sd.pages,
		"play":         sd.play,
		"request":      func() *http.Request { return r },
		"path":         func() pkgPath { return pkgPath{} },
		"strings":      func() pkgStrings { return pkgStrings{} },
		"file":         sd.file,
		"first":        first,
		"markdown":     markdown,
		"raw":          raw,
		"yaml":         yamlFn,
		"presentStyle": presentStyle,
	})
	t.Funcs(site.funcs)

	if err := tmplfunc.Parse(t, string(base)); err != nil {
		return nil, err
	}

	// Load page-specific layout template.
	layout, _ := p["layout"].(string)
	if layout == "" {
		l, ok := site.findLayout(dir, "default")
		if ok {
			layout = l
		} else {
			layout = "none"
		}
	} else if path.IsAbs(layout) {
		layout = strings.TrimLeft(path.Clean(layout+".tmpl"), "/")
	} else if strings.Contains(layout, "/") {
		layout = path.Join(dir, layout+".tmpl")
	} else if layout != "none" {
		l, ok := site.findLayout(dir, layout)
		if !ok {
			return nil, fmt.Errorf("cannot find layout %q", layout)
		}
		layout = l
	}

	if layout != "none" {
		ldata, err := site.readFile(".", layout)
		if err != nil {
			return nil, err
		}
		if err := tmplfunc.Parse(t.New(layout), string(ldata)); err != nil {
			return nil, err
		}
	}

	var buf bytes.Buffer
	if _, ok := p["Content"]; !ok && data != "" {
		// Load actual Markdown content (also a template).
		tf := t.New(file)
		if err := tmplfunc.Parse(tf, data); err != nil {
			return nil, err
		}
		if err := tf.Execute(&buf, p); err != nil {
			return nil, err
		}
		if strings.HasSuffix(file, ".md") {
			html, err := markdownToHTML(buf.String())
			if err != nil {
				return nil, err
			}
			p["Content"] = html
		} else {
			p["Content"] = template.HTML(buf.String())
		}
		buf.Reset()
	}

	if err := t.Execute(&buf, p); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// findLayout searches the start directory and parent directories for a template with the given base name.
func (site *Site) findLayout(dir, name string) (string, bool) {
	name += ".tmpl"
	for {
		abs := path.Join(dir, name)
		if _, err := fs.Stat(site.fs, abs); err == nil {
			return abs, true
		}
		if dir == "." {
			return "", false
		}
		dir = path.Dir(dir)
	}
}

// markdownToHTML converts Markdown to HTML.
// The Markdown source may contain raw HTML,
// but Go templates have already been processed.
func markdownToHTML(markdown string) (template.HTML, error) {
	// parser.WithHeadingAttribute allows custom ids on headings.
	// html.WithUnsafe allows use of raw HTML, which we need for tables.
	md := goldmark.New(
		goldmark.WithParserOptions(
			parser.WithHeadingAttribute(),
			parser.WithAutoHeadingID(),
			parser.WithASTTransformers(util.Prioritized(mdTransformFunc(mdLink), 1)),
		),
		goldmark.WithRendererOptions(html.WithUnsafe()),
		goldmark.WithExtensions(
			extension.NewTypographer(),
			extension.NewLinkify(
				extension.WithLinkifyAllowedProtocols([][]byte{[]byte("http"), []byte("https")}),
				extension.WithLinkifyEmailRegexp(regexp.MustCompile(`[^\x00-\x{10FFFF}]`)), // impossible
			),
			extension.DefinitionList,
		),
	)
	var buf bytes.Buffer
	if err := md.Convert(replaceTabs([]byte(markdown)), &buf); err != nil {
		return "", err
	}
	return template.HTML(buf.Bytes()), nil
}

// mdTransformFunc is a func implementing parser.ASTTransformer.
type mdTransformFunc func(*ast.Document, text.Reader, parser.Context)

func (f mdTransformFunc) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
	f(node, reader, pc)
}

// mdLink walks doc, adding rel=noreferrer target=_blank to non-relative links.
func mdLink(doc *ast.Document, _ text.Reader, _ parser.Context) {
	mdLinkWalk(doc)
}

func mdLinkWalk(n ast.Node) {
	switch n := n.(type) {
	case *ast.Link:
		dest := string(n.Destination)
		if strings.HasPrefix(dest, "https://") || strings.HasPrefix(dest, "http://") {
			n.SetAttributeString("rel", []byte("noreferrer"))
			n.SetAttributeString("target", []byte("_blank"))
		}
		return
	case *ast.AutoLink:
		// All autolinks are non-relative.
		n.SetAttributeString("rel", []byte("noreferrer"))
		n.SetAttributeString("target", []byte("_blank"))
		return
	}

	for child := n.FirstChild(); child != nil; child = child.NextSibling() {
		mdLinkWalk(child)
	}
}

// replaceTabs replaces all tabs in text with spaces up to a 4-space tab stop.
//
// In Markdown, tabs used for indentation are required to be interpreted as
// 4-space tab stops. See https://spec.commonmark.org/0.30/#tabs.
// Go also renders nicely and more compactly on the screen with 4-space
// tab stops, while browsers often use 8-space.
// And Goldmark crashes in some inputs that mix spaces and tabs.
// Fix the crashes and make the Go code consistently compact across browsers,
// all while staying Markdown-compatible, by expanding to 4-space tab stops.
//
// This function does not handle multi-codepoint Unicode sequences correctly.
func replaceTabs(text []byte) []byte {
	var buf bytes.Buffer
	col := 0
	for len(text) > 0 {
		r, size := utf8.DecodeRune(text)
		text = text[size:]

		switch r {
		case '\n':
			buf.WriteByte('\n')
			col = 0

		case '\t':
			buf.WriteByte(' ')
			col++
			for col%4 != 0 {
				buf.WriteByte(' ')
				col++
			}

		default:
			buf.WriteRune(r)
			col++
		}
	}
	return buf.Bytes()
}
