package main

import (
	"bytes"
	"html/template"
	"net/url"
	"strings"

	"code.hackerspace.pl/hscloud/devtools/hackdoc/config"

	"github.com/gabriel-vasile/mimetype"
	"github.com/golang/glog"
	"gopkg.in/russross/blackfriday.v2"
)

// renderMarkdown renders markdown to HTML, replacing all relative (intra-hackdoc) links with version that have ref set.
func renderMarkdown(input []byte, ref string) []byte {
	r := blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{
		Flags: blackfriday.CommonHTMLFlags | blackfriday.TOC,
	})

	// master is the default branch - do not make special links for that, as
	// that makes them kinda ugly.
	if ref == flagGitwebDefaultBranch {
		ref = ""
	}

	parser := blackfriday.New(blackfriday.WithRenderer(r), blackfriday.WithExtensions(blackfriday.CommonExtensions))
	ast := parser.Parse(input)

	// Render table of contents (raw HTML) into bytes.
	var tocB bytes.Buffer
	tocB.Write([]byte(`<div class="toc">`))
	r.RenderHeader(&tocB, ast)
	tocB.Write([]byte(`</div>`))
	toc := tocB.Bytes()

	var buf bytes.Buffer
	buf.Write([]byte(`<div class="content">`))
	// Render Markdown with some custom behaviour.
	ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
		// Fix intra-hackdoc links to contain ?ref=
		if ref != "" && entering && node.Type == blackfriday.Link || node.Type == blackfriday.Image {
			dest := string(node.Destination)
			u, err := url.Parse(dest)
			if err == nil && !u.IsAbs() {
				q := u.Query()
				q["ref"] = []string{ref}
				u.RawQuery = q.Encode()
				node.Destination = []byte(u.String())
				glog.V(10).Infof("link fix %q -> %q", dest, u.String())
			}
		}
		// Replace [TOC] anchor with a rendered TOC.
		if entering && node.Type == blackfriday.Text && string(node.Literal) == "[TOC]" {
			buf.Write(toc)
			return blackfriday.GoToNext
		}
		return r.RenderNode(&buf, node, entering)
	})
	buf.Write([]byte(`</div>`))
	r.RenderFooter(&buf, ast)
	return buf.Bytes()
}

type pathPart struct {
	Label string
	Path  string
}

func (r *request) renderable(dirpath string) bool {
	cfg, err := config.ForPath(r.ctx, r.source, dirpath)
	if err != nil {
		glog.Errorf("could not get config for path %q: %v", dirpath, err)
		return false
	}

	for _, f := range cfg.DefaultIndex {
		fpath := dirpath + "/" + f
		file, err := r.source.IsFile(r.ctx, fpath)
		if err != nil {
			glog.Errorf("IsFile(%q): %v", fpath, err)
			return false
		}

		if file {
			return true
		}
	}

	return false
}

func (r *request) handleFile(path string, cfg *config.Config) {
	data, err := r.source.ReadFile(r.ctx, path)
	if err != nil {
		glog.Errorf("ReadFile(%q): %w", err)
		r.handle500()
		return
	}

	// TODO(q3k): do MIME detection instead.
	if strings.HasSuffix(path, ".md") {
		rendered := renderMarkdown([]byte(data), r.ref)

		r.logRequest("serving markdown at %s, cfg %+v", path, cfg)

		// TODO(q3k): allow markdown files to override which template to load
		tmpl, ok := cfg.Templates["default"]
		if !ok {
			glog.Errorf("No default template found for %s", path)
			// TODO(q3k): implement fallback template
			r.w.Write(rendered)
			return
		}

		pathInDepot := strings.TrimPrefix(path, "//")
		pathParts := []pathPart{
			{Label: "//", Path: "/"},
		}
		parts := strings.Split(pathInDepot, "/")
		fullPath := ""
		for i, p := range parts {
			label := p
			if i != len(parts)-1 {
				label = label + "/"
			}
			fullPath += "/" + p
			target := fullPath
			if i != len(parts)-1 && !r.renderable("/"+fullPath) {
				target = ""
			}
			pathParts = append(pathParts, pathPart{Label: label, Path: target})
		}

		vars := map[string]interface{}{
			"Rendered":    template.HTML(rendered),
			"Title":       path,
			"Path":        path,
			"PathInDepot": pathInDepot,
			"PathParts":   pathParts,
			"HackdocURL":  flagHackdocURL,
			"WebLinks":    r.source.WebLinks(pathInDepot),
		}
		err = tmpl.Execute(r.w, vars)
		if err != nil {
			glog.Errorf("Could not execute template for %s: %v", err)
		}

		return
	}

	// Just serve the file.
	var mime string
	if strings.HasSuffix(path, ".js") {
		// Force .js to always be the correct MIME type.
		mime = "text/javascript"
	} else {
		// Otherwise, use magic to detect type.
		mime = mimetype.Detect(data).String()
	}
	r.w.Header().Set("Content-Type", mime)
	r.w.Write(data)
}
