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

import (
	"bytes"
	"fmt"
	"html"
	"html/template"
	"log"
	"net/http"
	"sort"
	"strings"

	"golang.org/x/tools/godoc"
	"golang.org/x/tools/godoc/vfs"
	"golang.org/x/website/internal/history"
)

// releaseHandler serves the Release History page.
type releaseHandler struct {
	ReleaseHistory []Major // Pre-computed release history to display.
}

func (h releaseHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	const relPath = "doc/devel/release.html"

	src, err := vfs.ReadFile(fs, "/doc/devel/release.html")
	if err != nil {
		log.Printf("reading template %s: %v", relPath, err)
		pres.ServeError(w, req, relPath, err)
		return
	}

	meta, src, err := extractMetadata(src)
	if err != nil {
		log.Printf("decoding metadata %s: %v", relPath, err)
		pres.ServeError(w, req, relPath, err)
		return
	}
	if !meta.Template {
		err := fmt.Errorf("got non-template, want template")
		log.Printf("unexpected metadata %s: %v", relPath, err)
		pres.ServeError(w, req, relPath, err)
		return
	}

	page := godoc.Page{
		Title:    meta.Title,
		Subtitle: meta.Subtitle,
		GoogleCN: googleCN(req),
	}
	data := releaseTemplateData{
		Major: h.ReleaseHistory,
	}

	// Evaluate as HTML template.
	tmpl, err := template.New("").Parse(string(src))
	if err != nil {
		log.Printf("parsing template %s: %v", relPath, err)
		pres.ServeError(w, req, relPath, err)
		return
	}
	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, data); err != nil {
		log.Printf("executing template %s: %v", relPath, err)
		pres.ServeError(w, req, relPath, err)
		return
	}
	src = buf.Bytes()

	page.Body = src
	pres.ServePage(w, page)
}

// sortReleases returns a sorted list of Go releases, suitable to be
// displayed on the Release History page. Releases are arranged into
// major releases, each with minor revisions.
func sortReleases(rs map[history.GoVer]history.Release) []Major {
	var major []Major
	byMajorVersion := make(map[history.GoVer]Major)
	for v, r := range rs {
		switch {
		case v.IsMajor():
			m := byMajorVersion[v]
			m.Release = Release{ver: v, rel: r}
			byMajorVersion[v] = m
		case v.IsMinor():
			m := byMajorVersion[majorOf(v)]
			m.Minor = append(m.Minor, Release{ver: v, rel: r})
			byMajorVersion[majorOf(v)] = m
		}
	}
	for _, m := range byMajorVersion {
		sort.Slice(m.Minor, func(i, j int) bool { return m.Minor[i].ver.Z < m.Minor[j].ver.Z })
		major = append(major, m)
	}
	sort.Slice(major, func(i, j int) bool {
		if major[i].ver.X != major[j].ver.X {
			return major[i].ver.X > major[j].ver.X
		}
		return major[i].ver.Y > major[j].ver.Y
	})
	return major
}

// majorOf takes a Go version like 1.5, 1.5.1, 1.5.2, etc.,
// and returns the corresponding major version like 1.5.
func majorOf(v history.GoVer) history.GoVer {
	return history.GoVer{X: v.X, Y: v.Y, Z: 0}
}

type releaseTemplateData struct {
	Major []Major
}

// Major represents a major Go release and its minor revisions
// as displayed on the release history page.
type Major struct {
	Release
	Minor []Release
}

// Release represents a Go release entry as displayed on the release history page.
type Release struct {
	ver history.GoVer
	rel history.Release
}

// V returns the Go release version string, like "1.14", "1.14.1", "1.14.2", etc.
func (r Release) V() string {
	return r.ver.String()
}

// Date returns the date of the release, formatted for display on the release history page.
func (r Release) Date() string {
	d := r.rel.Date
	return fmt.Sprintf("%04d/%02d/%02d", d.Year, d.Month, d.Day)
}

// Released reports whether release r has been released.
func (r Release) Released() bool {
	return !r.rel.Future
}

func (r Release) Summary() (template.HTML, error) {
	var buf bytes.Buffer
	err := releaseSummaryHTML.Execute(&buf, releaseSummaryTemplateData{
		V:                     r.V(),
		Security:              r.rel.Security,
		Released:              r.Released(),
		Quantifier:            r.rel.Quantifier,
		ComponentsAndPackages: joinComponentsAndPackages(r.rel),
		More:                  r.rel.More,
		CustomSummary:         r.rel.CustomSummary,
	})
	return template.HTML(buf.String()), err
}

type releaseSummaryTemplateData struct {
	V                     string        // Go release version string, like "1.14", "1.14.1", "1.14.2", etc.
	Security              bool          // Security release.
	Released              bool          // Whether release has been released.
	Quantifier            string        // Optional quantifier. Empty string for unspecified amount of fixes (typical), "a" for a single fix, "two", "three" for multiple fixes, etc.
	ComponentsAndPackages template.HTML // Components and packages involved.
	More                  template.HTML // Additional release content.
	CustomSummary         template.HTML // CustomSummary, if non-empty, replaces the entire release content summary with custom HTML.
}

var releaseSummaryHTML = template.Must(template.New("").Parse(`
{{if not .CustomSummary}}
	{{if .Released}}includes{{else}}will include{{end}}
	{{.Quantifier}}
	{{if .Security}}security{{end}}
	{{if eq .Quantifier "a"}}fix{{else}}fixes{{end -}}
	{{with .ComponentsAndPackages}} to {{.}}{{end}}.
	{{.More}}

	See the
	<a href="https://github.com/golang/go/issues?q=milestone%3AGo{{.V}}+label%3ACherryPickApproved">Go
	{{.V}} milestone</a> on our issue tracker for details.
{{else}}
	{{.CustomSummary}}
{{end}}
`))

// joinComponentsAndPackages joins components and packages involved
// in a Go release for the purposes of being displayed on the
// release history page, keeping English grammar rules in mind.
//
// The different special cases are:
//
// 	c1
// 	c1 and c2
// 	c1, c2, and c3
//
// 	the p1 package
// 	the p1 and p2 packages
// 	the p1, p2, and p3 packages
//
// 	c1 and [1 package]
// 	c1, and [2 or more packages]
// 	c1, c2, and [1 or more packages]
//
func joinComponentsAndPackages(r history.Release) template.HTML {
	var buf strings.Builder

	// List components, if any.
	for i, comp := range r.Components {
		if len(r.Packages) == 0 {
			// No packages, so components are joined with more rules.
			switch {
			case i != 0 && len(r.Components) == 2:
				buf.WriteString(" and ")
			case i != 0 && len(r.Components) >= 3 && i != len(r.Components)-1:
				buf.WriteString(", ")
			case i != 0 && len(r.Components) >= 3 && i == len(r.Components)-1:
				buf.WriteString(", and ")
			}
		} else {
			// When there are packages, all components are comma-separated.
			if i != 0 {
				buf.WriteString(", ")
			}
		}
		buf.WriteString(string(comp))
	}

	// Join components and packages using a comma and/or "and" as needed.
	if len(r.Components) > 0 && len(r.Packages) > 0 {
		if len(r.Components)+len(r.Packages) >= 3 {
			buf.WriteString(",")
		}
		buf.WriteString(" and ")
	}

	// List packages, if any.
	if len(r.Packages) > 0 {
		buf.WriteString("the ")
	}
	for i, pkg := range r.Packages {
		switch {
		case i != 0 && len(r.Packages) == 2:
			buf.WriteString(" and ")
		case i != 0 && len(r.Packages) >= 3 && i != len(r.Packages)-1:
			buf.WriteString(", ")
		case i != 0 && len(r.Packages) >= 3 && i == len(r.Packages)-1:
			buf.WriteString(", and ")
		}
		buf.WriteString("<code>" + html.EscapeString(pkg) + "</code>")
	}
	switch {
	case len(r.Packages) == 1:
		buf.WriteString(" package")
	case len(r.Packages) >= 2:
		buf.WriteString(" packages")
	}

	return template.HTML(buf.String())
}
