// 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 frontend

import (
	"bytes"
	"context"
	"html"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/google/safehtml"
	"github.com/google/safehtml/uncheckedconversions"
	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/ast"
	"github.com/yuin/goldmark/extension"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/renderer"
	ghtml "github.com/yuin/goldmark/renderer/html"
	"github.com/yuin/goldmark/util"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/experiment"
)

// serveStyleGuide serves the styleguide page, the content of which is
// generated from the markdown files in content/static.
func (s *Server) serveStyleGuide(w http.ResponseWriter, r *http.Request, ds internal.DataSource) error {
	ctx := r.Context()
	if !experiment.IsActive(ctx, internal.ExperimentStyleGuide) {
		return &serverError{status: http.StatusNotFound}
	}
	page, err := styleGuide(ctx, s.staticPath.String())
	page.basePage = s.newBasePage(r, "")
	page.AllowWideContent = true
	page.UseResponsiveLayout = true
	if err != nil {
		return err
	}
	s.servePage(ctx, w, "styleguide", page)
	return nil
}

type styleGuidePage struct {
	basePage
	Sections []*StyleSection
	Outline  []*Heading
}

// styleGuide collects the paths to the markdown files in content/static,
// renders them into sections for the styleguide, and merges the document
// outlines into a single page outline.
func styleGuide(ctx context.Context, staticPath string) (_ *styleGuidePage, err error) {
	defer derrors.WrapStack(&err, "styleGuide(%q)", staticPath)
	files, err := markdownFiles(staticPath)
	if err != nil {
		return nil, err
	}
	var sections []*StyleSection
	for _, f := range files {
		doc, err := styleSection(ctx, f)
		if err != nil {
			return nil, err
		}
		sections = append(sections, doc)
	}
	var outline []*Heading
	for _, s := range sections {
		outline = append(outline, s.Outline...)
	}
	return &styleGuidePage{
		Sections: sections,
		Outline:  outline,
	}, nil
}

// StyleSection represents a section on the styleguide page.
type StyleSection struct {
	// ID is the ID for the header element of the section.
	ID string

	// Title is the title of the section, taken from the name
	// of the markdown file.
	Title string

	// Content is the HTML rendered from the parsed markdown file.
	Content safehtml.HTML

	// Outline is a collection of headings used in the navigation.
	Outline []*Heading
}

// styleSection uses goldmark to parse a markdown file and render
// a section of the styleguide.
func styleSection(ctx context.Context, filename string) (_ *StyleSection, err error) {
	defer derrors.WrapStack(&err, "styleSection(%q)", filename)
	var buf bytes.Buffer
	source, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	// We set priority values so that we always use our custom transformer
	// instead of the default ones. The default values are in:
	// https://github.com/yuin/goldmark/blob/7b90f04af43131db79ec320be0bd4744079b346f/parser/parser.go#L567
	const (
		astTransformerPriority = 10000
		nodeRenderersPriority  = 100
	)
	et := &extractTOC{ctx: ctx}
	md := goldmark.New(
		goldmark.WithExtensions(extension.GFM),
		goldmark.WithParserOptions(
			parser.WithAutoHeadingID(),
			parser.WithAttribute(),
			parser.WithASTTransformers(
				util.Prioritized(et, astTransformerPriority),
			),
		),
		goldmark.WithRendererOptions(
			renderer.WithNodeRenderers(
				util.Prioritized(&guideRenderer{}, nodeRenderersPriority),
			),
			ghtml.WithUnsafe(),
			ghtml.WithXHTML(),
		),
	)

	if err := md.Convert(source, &buf); err != nil {
		return nil, err
	}

	id := strings.TrimSuffix(filepath.Base(filename), ".md")
	return &StyleSection{
		ID:      id,
		Title:   camelCase(id),
		Content: uncheckedconversions.HTMLFromStringKnownToSatisfyTypeContract(buf.String()),
		Outline: et.Headings,
	}, nil
}

// guideRenderer is a renderer.NodeRenderer implementation that renders
// styleguide sections.
type guideRenderer struct {
	ghtml.Config
}

func (r *guideRenderer) writeLines(w util.BufWriter, source []byte, n ast.Node) {
	l := n.Lines().Len()
	for i := 0; i < l; i++ {
		line := n.Lines().At(i)
		w.Write(line.Value(source))
	}
}

func (r *guideRenderer) writeEscapedLines(w util.BufWriter, source []byte, n ast.Node) {
	l := n.Lines().Len()
	for i := 0; i < l; i++ {
		line := n.Lines().At(i)
		w.Write([]byte(html.EscapeString(string(line.Value(source)))))
	}
}

// renderFencedCodeBlock writes html code snippets twice, once as actual
// html for the page and again as a code snippet.
func (r *guideRenderer) renderFencedCodeBlock(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
	if !entering {
		return ast.WalkContinue, nil
	}
	n := node.(*ast.FencedCodeBlock)
	w.WriteString("<span>\n")
	r.writeLines(w, source, n)
	w.WriteString("</span>\n")
	w.WriteString("<pre class=\"StringifyElement-markup js-clipboard\">\n")
	r.writeEscapedLines(w, source, n)
	w.WriteString("</pre>\n")
	return ast.WalkContinue, nil
}

// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
func (r *guideRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
	reg.Register(ast.KindFencedCodeBlock, r.renderFencedCodeBlock)
}

// markdownFiles walks the content/static directory and collects
// the paths to markdown files.
func markdownFiles(dir string) ([]string, error) {
	var matches []string
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		if matched, err := filepath.Match("*.md", filepath.Base(path)); err != nil {
			return err
		} else if matched {
			matches = append(matches, path)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return matches, nil
}

// camelCase turns a snake cased strink into a camel case string.
// For example, hello-world becomes HelloWorld. This function is
// used to ensure proper casing in the classnames of the style
// sections.
func camelCase(s string) string {
	p := strings.Split(s, "-")
	var o []string
	for _, v := range p {
		o = append(o, strings.Title(v))
	}
	return strings.Join(o, "")
}
