// Copyright 2019 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 sumdb implements the HTTP protocols for serving or accessing a module checksum database.
package sumdb

import (
	"context"
	"net/http"
	"os"
	"strings"

	"golang.org/x/mod/internal/lazyregexp"
	"golang.org/x/mod/module"
	"golang.org/x/mod/sumdb/tlog"
)

// A ServerOps provides the external operations
// (underlying database access and so on) needed by the Server.
type ServerOps interface {
	// Signed returns the signed hash of the latest tree.
	Signed(ctx context.Context) ([]byte, error)

	// ReadRecords returns the content for the n records id through id+n-1.
	ReadRecords(ctx context.Context, id, n int64) ([][]byte, error)

	// Lookup looks up a record for the given module,
	// returning the record ID.
	Lookup(ctx context.Context, m module.Version) (int64, error)

	// ReadTileData reads the content of tile t.
	// It is only invoked for hash tiles (t.L ≥ 0).
	ReadTileData(ctx context.Context, t tlog.Tile) ([]byte, error)
}

// A Server is the checksum database HTTP server,
// which implements http.Handler and should be invoked
// to serve the paths listed in ServerPaths.
type Server struct {
	ops ServerOps
}

// NewServer returns a new Server using the given operations.
func NewServer(ops ServerOps) *Server {
	return &Server{ops: ops}
}

// ServerPaths are the URL paths the Server can (and should) serve.
//
// Typically a server will do:
//
//	srv := sumdb.NewServer(ops)
//	for _, path := range sumdb.ServerPaths {
//		http.Handle(path, srv)
//	}
//
var ServerPaths = []string{
	"/lookup/",
	"/latest",
	"/tile/",
}

var modVerRE = lazyregexp.New(`^[^@]+@v[0-9]+\.[0-9]+\.[0-9]+(-[^@]*)?(\+incompatible)?$`)

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	switch {
	default:
		http.NotFound(w, r)

	case strings.HasPrefix(r.URL.Path, "/lookup/"):
		mod := strings.TrimPrefix(r.URL.Path, "/lookup/")
		if !modVerRE.MatchString(mod) {
			http.Error(w, "invalid module@version syntax", http.StatusBadRequest)
			return
		}
		i := strings.Index(mod, "@")
		escPath, escVers := mod[:i], mod[i+1:]
		path, err := module.UnescapePath(escPath)
		if err != nil {
			reportError(w, err)
			return
		}
		vers, err := module.UnescapeVersion(escVers)
		if err != nil {
			reportError(w, err)
			return
		}
		id, err := s.ops.Lookup(ctx, module.Version{Path: path, Version: vers})
		if err != nil {
			reportError(w, err)
			return
		}
		records, err := s.ops.ReadRecords(ctx, id, 1)
		if err != nil {
			// This should never happen - the lookup says the record exists.
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if len(records) != 1 {
			http.Error(w, "invalid record count returned by ReadRecords", http.StatusInternalServerError)
			return
		}
		msg, err := tlog.FormatRecord(id, records[0])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		signed, err := s.ops.Signed(ctx)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
		w.Write(msg)
		w.Write(signed)

	case r.URL.Path == "/latest":
		data, err := s.ops.Signed(ctx)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
		w.Write(data)

	case strings.HasPrefix(r.URL.Path, "/tile/"):
		t, err := tlog.ParseTilePath(r.URL.Path[1:])
		if err != nil {
			http.Error(w, "invalid tile syntax", http.StatusBadRequest)
			return
		}
		if t.L == -1 {
			// Record data.
			start := t.N << uint(t.H)
			records, err := s.ops.ReadRecords(ctx, start, int64(t.W))
			if err != nil {
				reportError(w, err)
				return
			}
			if len(records) != t.W {
				http.Error(w, "invalid record count returned by ReadRecords", http.StatusInternalServerError)
				return
			}
			var data []byte
			for i, text := range records {
				msg, err := tlog.FormatRecord(start+int64(i), text)
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
				}
				data = append(data, msg...)
			}
			w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
			w.Write(data)
			return
		}

		data, err := s.ops.ReadTileData(ctx, t)
		if err != nil {
			reportError(w, err)
			return
		}
		w.Header().Set("Content-Type", "application/octet-stream")
		w.Write(data)
	}
}

// reportError reports err to w.
// If it's a not-found, the reported error is 404.
// Otherwise it is an internal server error.
// The caller must only call reportError in contexts where
// a not-found err should be reported as 404.
func reportError(w http.ResponseWriter, err error) {
	if os.IsNotExist(err) {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	http.Error(w, err.Error(), http.StatusInternalServerError)
}
