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

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

package web

import (
	"bytes"
	"encoding/json"
	"io/fs"
	"log"
	"path"
	"strings"
)

type file struct {
	// Copied from document metadata directives
	Title    string
	Subtitle string
	Template bool

	Path     string // URL path
	FilePath string // filesystem path relative to goroot
	Body     []byte // content after metadata
}

type fileJSON struct {
	Title    string
	Subtitle string
	Template bool
	Redirect string // if set, redirect to other URL
}

// open returns the *file for a given relative path or nil if none exists.
func open(fsys fs.FS, relpath string) *file {
	// Strip trailing .html or .md or /; it all names the same page.
	if strings.HasSuffix(relpath, ".html") {
		relpath = strings.TrimSuffix(relpath, ".html")
	} else if strings.HasSuffix(relpath, ".md") {
		relpath = strings.TrimSuffix(relpath, ".md")
	} else if strings.HasSuffix(relpath, "/") {
		relpath = strings.TrimSuffix(relpath, "/")
	}

	files := []string{relpath + ".html", relpath + ".md", path.Join(relpath, "index.html"), path.Join(relpath, "index.md")}
	var filePath string
	var b []byte
	var err error
	for _, filePath = range files {
		b, err = fs.ReadFile(fsys, filePath)
		if err == nil {
			break
		}
	}

	// Special case for memory model and spec, which live
	// in the main Go repo's doc directory and therefore have not
	// been renamed to their serving relpaths.
	// We wait until the ReadFiles above have failed so that the
	// code works if these are ever moved to /ref/spec and /ref/mem.
	if err != nil && relpath == "ref/spec" {
		return open(fsys, "doc/go_spec")
	}
	if err != nil && relpath == "ref/mem" {
		return open(fsys, "doc/go_mem")
	}

	if err != nil {
		return nil
	}

	// Special case for memory model and spec, continued.
	switch relpath {
	case "doc/go_spec":
		relpath = "ref/spec"
	case "doc/go_mem":
		relpath = "ref/mem"
	}

	// If we read an index.md or index.html, the canonical relpath is without the index.md/index.html suffix.
	if name := path.Base(filePath); name == "index.html" || name == "index.md" {
		relpath, _ = path.Split(filePath)
	}

	js, body, err := parseFile(b)
	if err != nil {
		log.Printf("extractMetadata %s: %v", relpath, err)
		return nil
	}

	f := &file{
		Title:    js.Title,
		Subtitle: js.Subtitle,
		Template: js.Template,
		Path:     "/" + relpath,
		FilePath: filePath,
		Body:     body,
	}
	if js.Redirect != "" {
		// Allow (placeholder) documents to declare a redirect.
		f.Path = js.Redirect
	}

	return f
}

var (
	jsonStart = []byte("<!--{")
	jsonEnd   = []byte("}-->")
)

// parseFile extracts the metaJSON from a byte slice.
// It returns the metadata and the remaining text.
// If no metadata is present, it returns an empty metaJSON and the original text.
func parseFile(b []byte) (meta fileJSON, tail []byte, err error) {
	tail = b
	if !bytes.HasPrefix(b, jsonStart) {
		return
	}
	end := bytes.Index(b, jsonEnd)
	if end < 0 {
		return
	}
	b = b[len(jsonStart)-1 : end+1] // drop leading <!-- and include trailing }
	if err = json.Unmarshal(b, &meta); err != nil {
		return
	}
	tail = tail[end+len(jsonEnd):]
	return
}
