// 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 Request struct {
	Payload struct {
		Paths []string `json:"paths"`
	} `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
		}

		var resp Response
		resp.Payload.Entries = make(map[string]*Entry)
		for _, p := range req.Payload.Paths {
			resp.Payload.Entries[p] = match(p)
		}
		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())
}

// translatePath 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 translatePath(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
}

// translateOwnersPaths returns a copy of entries with all its keys
// adjusted for better readability on https://dev.golang.org/owners.
func translateOwnersPaths() (map[string]*Entry, error) {
	tm := make(map[string]*Entry)
	for path, entry := range entries {
		tPath := translatePath(path)
		if _, ok := tm[tPath]; ok {
			return nil, fmt.Errorf("path translation of %q creates a duplicate entry %q", path, tPath)
		}
		tm[tPath] = entry
	}
	return tm, nil
}

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

	indexCache.once.Do(func() {
		displayEntries, err := translateOwnersPaths()
		if err != nil {
			indexCache.err = err
			return
		}
		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">
	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>
</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 := .}}
	<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>
`))
