// Copyright 2017 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 (
	"context"
	"fmt"
	"html/template"
	"log"
	"math/rand"
	"net/http"
	"path"
	"strconv"
	"strings"
	"sync"
	"time"

	"golang.org/x/build/devapp/owners"
	"golang.org/x/build/maintner"
	"golang.org/x/build/maintner/godata"
)

// A server is an http.Handler that serves content within staticDir at root and
// the dynamically-generated dashboards at their respective endpoints.
type server struct {
	mux         *http.ServeMux
	staticDir   string
	templateDir string

	cMu              sync.RWMutex // Used to protect the fields below.
	corpus           *maintner.Corpus
	repo             *maintner.GitHubRepo
	helpWantedIssues []issueData
	data             pageData

	// GopherCon-specific fields. Must still hold cMu when reading/writing these.
	userMapping map[int]*maintner.GitHubUser // Gerrit Owner ID => GitHub user
	activities  []activity                   // All contribution activities
	totalPoints int
}

type issueData struct {
	id          int32
	titlePrefix string
}

type pageData struct {
	release releaseData
	reviews reviewsData
}

func newServer(mux *http.ServeMux, staticDir, templateDir string) *server {
	s := &server{
		mux:         mux,
		staticDir:   staticDir,
		templateDir: templateDir,
		userMapping: map[int]*maintner.GitHubUser{},
	}
	s.mux.Handle("/", http.FileServer(http.Dir(s.staticDir)))
	s.mux.HandleFunc("/favicon.ico", s.handleFavicon)
	s.mux.HandleFunc("/release", s.withTemplate("/release.tmpl", s.handleRelease))
	s.mux.HandleFunc("/reviews", s.withTemplate("/reviews.tmpl", s.handleReviews))
	s.mux.HandleFunc("/dir/", handleDirRedirect)
	s.mux.HandleFunc(owners.URLPathPrefix, owners.Handler)
	for _, p := range []string{"/imfeelinghelpful", "/imfeelinglucky"} {
		s.mux.HandleFunc(p, s.handleRandomHelpWantedIssue)
	}
	s.mux.HandleFunc("/_/activities", s.handleActivities)
	return s
}

func (s *server) withTemplate(tmpl string, fn func(*template.Template, http.ResponseWriter, *http.Request)) http.HandlerFunc {
	t := template.Must(template.ParseFiles(path.Join(s.templateDir, tmpl)))
	return func(w http.ResponseWriter, r *http.Request) { fn(t, w, r) }
}

// initCorpus fetches a full maintner corpus, overwriting any existing data.
func (s *server) initCorpus(ctx context.Context) error {
	s.cMu.Lock()
	defer s.cMu.Unlock()
	corpus, err := godata.Get(ctx)
	if err != nil {
		return fmt.Errorf("godata.Get: %v", err)
	}
	s.corpus = corpus
	s.repo = s.corpus.GitHub().Repo("golang", "go") // The golang/go repo.
	if s.repo == nil {
		return fmt.Errorf(`s.corpus.GitHub().Repo("golang", "go") = nil`)
	}
	return nil
}

// corpusUpdateLoop continuously updates the server’s corpus until ctx’s Done
// channel is closed.
func (s *server) corpusUpdateLoop(ctx context.Context) {
	log.Println("Starting corpus update loop ...")
	for {
		log.Println("Updating help wanted issues ...")
		s.updateHelpWantedIssues()
		log.Println("Updating activities ...")
		s.updateActivities()
		s.cMu.Lock()
		s.data.release.dirty = true
		s.data.reviews.dirty = true
		s.cMu.Unlock()
		err := s.corpus.UpdateWithLocker(ctx, &s.cMu)
		if err != nil {
			if err == maintner.ErrSplit {
				log.Println("Corpus out of sync. Re-fetching corpus.")
				s.initCorpus(ctx)
			} else {
				log.Printf("corpus.Update: %v; sleeping 15s", err)
				time.Sleep(15 * time.Second)
				continue
			}
		}

		select {
		case <-ctx.Done():
			return
		default:
			continue
		}
	}
}

const (
	issuesURLBase = "https://golang.org/issue/"

	labelHelpWantedID = 150880243
)

func (s *server) updateHelpWantedIssues() {
	s.cMu.Lock()
	defer s.cMu.Unlock()

	var issues []issueData
	s.repo.ForeachIssue(func(i *maintner.GitHubIssue) error {
		if i.Closed {
			return nil
		}
		if i.HasLabelID(labelHelpWantedID) {
			prefix := strings.SplitN(i.Title, ":", 2)[0]
			issues = append(issues, issueData{id: i.Number, titlePrefix: prefix})
		}
		return nil
	})
	s.helpWantedIssues = issues
}

func (s *server) handleRandomHelpWantedIssue(w http.ResponseWriter, r *http.Request) {
	s.cMu.RLock()
	defer s.cMu.RUnlock()
	if len(s.helpWantedIssues) == 0 {
		http.Redirect(w, r, issuesURLBase, http.StatusSeeOther)
		return
	}
	pkgs := r.URL.Query().Get("pkg")
	var rid int32
	if pkgs == "" {
		rid = s.helpWantedIssues[rand.Intn(len(s.helpWantedIssues))].id
	} else {
		filtered := s.filteredHelpWantedIssues(strings.Split(pkgs, ",")...)
		if len(filtered) == 0 {
			http.Redirect(w, r, issuesURLBase, http.StatusSeeOther)
			return
		}
		rid = filtered[rand.Intn(len(filtered))].id
	}
	http.Redirect(w, r, issuesURLBase+strconv.Itoa(int(rid)), http.StatusSeeOther)
}

func (s *server) filteredHelpWantedIssues(pkgs ...string) []issueData {
	var issues []issueData
	for _, i := range s.helpWantedIssues {
		for _, p := range pkgs {
			if strings.HasPrefix(i.titlePrefix, p) {
				issues = append(issues, i)
				break
			}
		}
	}
	return issues
}

func (s *server) handleFavicon(w http.ResponseWriter, r *http.Request) {
	// Need to specify content type for consistent tests, without this it's
	// determined from mime.types on the box the test is running on
	w.Header().Set("Content-Type", "image/x-icon")
	http.ServeFile(w, r, path.Join(s.staticDir, "/favicon.ico"))
}

// ServeHTTP satisfies the http.Handler interface.
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.TLS != nil {
		w.Header().Set("Strict-Transport-Security", "max-age=31536000; preload")
	}
	s.mux.ServeHTTP(w, r)
}

// handleDirRedirect accepts requests of the form:
//     /dir/REPO/some/dir/
// And redirects them to either:
//     https://github.com/golang/REPO/tree/master/some/dir/
// or:
//     https://go.googlesource.com/REPO/+/master/some/dir/
// ... depending on the Referer. This is so we can make links
// in Markdown docs that are clickable on both GitHub and
// in the go.googlesource.com viewer. If detection fails, we
// default to GitHub.
func handleDirRedirect(w http.ResponseWriter, r *http.Request) {
	useGoog := strings.Contains(r.Referer(), "googlesource.com")
	path := r.URL.Path
	if !strings.HasPrefix(path, "/dir/") {
		http.Error(w, "bad mux", http.StatusInternalServerError)
		return
	}
	path = strings.TrimPrefix(path, "/dir/")
	// path is now "REPO/some/dir/"
	var repo string
	slash := strings.IndexByte(path, '/')
	if slash == -1 {
		repo, path = path, ""
	} else {
		repo, path = path[:slash], path[slash+1:]
	}
	path = strings.TrimSuffix(path, "/")
	var target string
	if useGoog {
		target = fmt.Sprintf("https://go.googlesource.com/%s/+/master/%s", repo, path)
	} else {
		target = fmt.Sprintf("https://github.com/golang/%s/tree/master/%s", repo, path)
	}
	http.Redirect(w, r, target, http.StatusFound)
}
