// Copyright 2018 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 owners

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strings"
	"sync"

	"golang.org/x/build/repos"
)

type Owner struct {
	// GitHubUsername is a GitHub user name or team name.
	GitHubUsername string `json:"githubUsername"`
	GerritEmail    string `json:"gerritEmail"`
}

type Entry struct {
	Primary   []Owner `json:"primary"`
	Secondary []Owner `json:"secondary,omitempty"`
}

type displayEntry struct {
	Primary   []Owner
	Secondary []Owner
	GerritURL string
}

type Request struct {
	Payload struct {
		// Paths is a set of relative paths rooted at go.googlesource.com,
		// where the first path component refers to the repository name,
		// while the rest refers to a path within that repository.
		//
		// For instance, a path like go/src/runtime/trace/trace.go refers
		// to the repository at go.googlesource.com/go, and the path
		// src/runtime/trace/trace.go within that repository.
		//
		// A request with Paths set will return the owner entry
		// for the deepest part of each path that it has information
		// on.
		//
		// For example, the path go/src/runtime/trace/trace.go will
		// match go/src/runtime/trace if there exist entries for both
		// go/src/runtime and go/src/runtime/trace.
		//
		// Must be empty if All is true.
		Paths []string `json:"paths"`

		// All indicates that the response must contain every available
		// entry about code owners.
		//
		// If All is true, Paths must be empty.
		All bool `json:"all"`
	} `json:"payload"`
	Version int `json:"v"` // API version
}

type Response struct {
	Payload struct {
		Entries map[string]*Entry `json:"entries"` // paths in request -> Entry
	} `json:"payload"`
	Error string `json:"error,omitempty"`
}

// match takes a path consisting of the repo name and full path of a file or
// directory within that repo and returns the deepest Entry match in the file
// hierarchy for the given resource.
func match(path string) *Entry {
	var deepestPath string
	for p := range entries {
		if hasPathPrefix(path, p) && len(p) > len(deepestPath) {
			deepestPath = p
		}
	}
	return entries[deepestPath]
}

// hasPathPrefix reports whether the slash-separated path s
// begins with the elements in prefix.
//
// Copied from go/src/cmd/go/internal/str.HasPathPrefix.
func hasPathPrefix(s, prefix string) bool {
	if len(s) == len(prefix) {
		return s == prefix
	}
	if prefix == "" {
		return true
	}
	if len(s) > len(prefix) {
		if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' {
			return s[:len(prefix)] == prefix
		}
	}
	return false
}

// Handler takes one or more paths and returns a map of each to a matching
// Entry struct. If no Entry is matched for the path, the value for the key
// is nil.
func Handler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "GET":
		serveIndex(w, r)
		return
	case "POST":
		var req Request
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			jsonError(w, "unable to decode request", http.StatusBadRequest)
			// TODO: increment expvar for monitoring.
			log.Printf("unable to decode owners request: %v", err)
			return
		}

		if len(req.Payload.Paths) > 0 && req.Payload.All {
			jsonError(w, "paths must be empty when all is true", http.StatusBadRequest)
			// TODO: increment expvar for monitoring.
			log.Printf("invalid request: paths is non-empty but all is true")
			return
		}

		var resp Response
		if req.Payload.All {
			resp.Payload.Entries = entries
		} else {
			resp.Payload.Entries = make(map[string]*Entry)
			for _, p := range req.Payload.Paths {
				resp.Payload.Entries[p] = match(p)
			}
		}
		// resp.Payload.Entries must not be mutated because it contains
		// references to the global "entries" value.

		var buf bytes.Buffer
		if err := json.NewEncoder(&buf).Encode(resp); err != nil {
			jsonError(w, "unable to encode response", http.StatusInternalServerError)
			// TODO: increment expvar for monitoring.
			log.Printf("unable to encode owners response: %v", err)
			return
		}
		w.Write(buf.Bytes())
	case "OPTIONS":
		// Likely a CORS preflight request; leave resp.Payload empty.
	default:
		jsonError(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}
}

func jsonError(w http.ResponseWriter, text string, code int) {
	w.WriteHeader(code)
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(Response{Error: text}); err != nil {
		// TODO: increment expvar for monitoring.
		log.Printf("unable to encode error response: %v", err)
		return
	}
	w.Write(buf.Bytes())
}

// TranslatePathForIssues takes a path for a package based on go.googlesource.com
// and translates it into a form that aligns more closely with the issue
// tracker.
//
// Specifically, Go standard library packages lose the go/src prefix,
// repositories with a golang.org/x/ import path get the x/ prefix,
// and all other paths are left as-is (this includes e.g. domains).
func TranslatePathForIssues(path string) string {
	// Check if it's in the standard library, in which case,
	// drop the prefix.
	if strings.HasPrefix(path, "go/src/") {
		return path[len("go/src/"):]
	}

	// Check if it's some other path in the main repo, in which case,
	// drop the go/ prefix.
	if strings.HasPrefix(path, "go/") {
		return path[len("go/"):]
	}

	// Check if it's a golang.org/x/ repository, and if so add an x/ prefix.
	firstComponent := path
	i := strings.IndexRune(path, '/')
	if i > 0 {
		firstComponent = path[:i]
	}
	if _, ok := repos.ByImportPath["golang.org/x/"+firstComponent]; ok {
		return "x/" + path
	}

	// None of the above was true, so just leave it untouched.
	return path
}

// formatEntries returns an entries map adjusted for better readability on
// https://dev.golang.org/owners.
func formatEntries(entries map[string]*Entry) (map[string]*displayEntry, error) {
	tm := make(map[string]*displayEntry)
	for path, entry := range entries {
		tPath := TranslatePathForIssues(path)
		if _, ok := tm[tPath]; ok {
			return nil, fmt.Errorf("path translation of %q creates a duplicate entry %q", path, tPath)
		}
		tm[tPath] = &displayEntry{
			Primary:   entry.Primary,
			Secondary: entry.Secondary,
			GerritURL: gerritURL(path, tPath),
		}
	}
	return tm, nil
}

func gerritURL(path, tPath string) string {
	var project string
	var dir string
	if strings.HasPrefix(path, "go/") {
		project = "go"
		dir = tPath
	} else if strings.HasPrefix(tPath, "x/") {
		parts := strings.SplitN(tPath, "/", 3)
		project = parts[1]
		if len(parts) == 3 {
			dir = parts[2]
		}
	} else {
		return ""
	}
	url := "https://go-review.googlesource.com/q/project:" + project
	if dir != "" {
		url += "+dir:" + dir
	}
	return url
}

// ownerData is passed to the Template, which produces two tables.
type ownerData struct {
	Paths    map[string]*displayEntry
	ArchOSes map[string]*displayEntry
}

func serveIndex(w http.ResponseWriter, _ *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")

	indexCache.once.Do(func() {
		paths, err := formatEntries(entries)
		if err != nil {
			indexCache.err = err
			return
		}

		archOses, err := formatEntries(archOses)
		if err != nil {
			indexCache.err = err
			return
		}

		displayEntries := ownerData{paths, archOses}

		var buf bytes.Buffer
		indexCache.err = indexTmpl.Execute(&buf, displayEntries)
		indexCache.html = buf.Bytes()
	})
	if indexCache.err != nil {
		log.Printf("unable to serve index page HTML: %v", indexCache.err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	w.Write(indexCache.html)
}

// indexCache is a cache of the owners index page HTML.
//
// As long as the owners are defined at package initialization time
// and not modified at runtime, the HTML doesn't change per request.
var indexCache struct {
	once sync.Once
	html []byte // Page HTML rendered by indexTmpl.
	err  error
}

var indexTmpl = template.Must(template.New("index").Funcs(template.FuncMap{
	"githubURL": func(githubUsername string) string {
		if i := strings.Index(githubUsername, "/"); i != -1 {
			// A GitHub team like "{org}/{team}".
			org, team := githubUsername[:i], githubUsername[i+len("/"):]
			return "https://github.com/orgs/" + org + "/teams/" + team
		}
		return "https://github.com/" + githubUsername
	},
}).Parse(`<!DOCTYPE html>
<html lang="en">
<title>Go Code Owners</title>
<meta name=viewport content="width=device-width, initial-scale=1">
<style>
* {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}
body {
	font-family: sans-serif;
	margin: 1rem 1.5rem;
}
.header {
	color: #666;
	font-size: 90%;
	margin-bottom: 1rem;
}
.table-header {
	font-weight: bold;
	position: sticky;
	top: 0;
}
.table-header,
.entry {
	background-color: #fff;
	border-bottom: 1px solid #ddd;
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	margin: .15rem 0;
	padding: .15rem 0;
}
.path,
.primary,
.secondary {
	flex-basis: 33.3%;
}
</style>
<header class="header">
	<p>Reviews are automatically assigned to primary owners.</p>
	<p>Alter these entries at
	<a href="https://go.googlesource.com/build/+/master/devapp/owners"
		target="_blank" rel="noopener">golang.org/x/build/devapp/owners</a></p>
</header>
<main>
<div class="table-header">
	<span class="path">Path</span>
	<span class="primary">Primaries</span>
	<span class="secondary">Secondaries</span>
</div>
{{range $path, $entry := .Paths}}
	<div class="entry">
		<span class="path">
			{{if $entry.GerritURL}}<a href="{{$entry.GerritURL}}" target="_blank" rel="noopener">{{end}}
			{{$path}}
			{{if $entry.GerritURL}}</a>{{end}}
		</span>
		<span class="primary">
			{{range .Primary}}
				<a href="{{githubURL .GitHubUsername}}" target="_blank" rel="noopener">@{{.GitHubUsername}}</a>
			{{end}}
		</span>
		<span class="secondary">
			{{range .Secondary}}
				<a href="{{githubURL .GitHubUsername}}" target="_blank" rel="noopener">@{{.GitHubUsername}}</a>
			{{end}}
		</span>
	</div>
{{end}}
<div class="table-header">
	<span class="path">Arch/OS</span>
	<span class="primary">Primaries</span>
	<span class="secondary">Secondaries</span>
</div>
{{range $path, $entry := .ArchOSes}}
	<div class="entry">
		<span class="path">{{$path}}</span>
		<span class="primary">
			{{range .Primary}}
				<a href="{{githubURL .GitHubUsername}}" target="_blank" rel="noopener">@{{.GitHubUsername}}</a>
			{{end}}
		</span>
		<span class="secondary">
			{{range .Secondary}}
				<a href="{{githubURL .GitHubUsername}}" target="_blank" rel="noopener">@{{.GitHubUsername}}</a>
			{{end}}
		</span>
	</div>
{{end}}
</main>
`))
