// Copyright (C) 2023  Shanhu Tech Inc.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License
// for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

package gometa

import (
	"fmt"
	"net/http"
	"path"
	"sort"

	"shanhu.io/g/aries"
)

// IsGoGetRequest checks if an incoming request is generated by "go get"
func IsGoGetRequest(req *http.Request) bool {
	query := req.URL.Query()
	_, ok := query["go-get"]
	return ok
}

// NewGitMux creates an HTTP mux which handles go get requests
// for repos under a particular domain.
func NewGitMux(domain string, repos map[string]string) *aries.Mux {
	m := aries.NewMux()

	var names []string
	for repo := range repos {
		names = append(names, repo)
	}
	sort.Strings(names)

	for _, repo := range names {
		vcsRoot := repos[repo]
		r := NewGitRepo(path.Join(domain, repo), vcsRoot)
		m.Dir(path.Join("/", repo), r.Serve)
	}

	return m
}

// NewGitHubMux creates an HTTP mux which handles go get requests
// for repos under a particular domain that maps to a particular
// GitHub user or organization account.
func NewGitHubMux(
	domain, user string, pubRepos, privRepos []string,
) *aries.Mux {
	m := make(map[string]string)
	for _, repo := range pubRepos {
		m[repo] = fmt.Sprintf("https://github.com/%s/%s.git", user, repo)
	}
	for _, repo := range privRepos {
		m[repo] = fmt.Sprintf("ssh://git@github.com/%s/%s.git", user, repo)
	}
	return NewGitMux(domain, m)
}

// ServeGoGet will serve the request if it contains "go-get" in the query.
// It returns true when it is served, and false if it is not.
func ServeGoGet(mux *aries.Mux, c *aries.C) error {
	query := c.Req.URL.Query()
	if _, ok := query["go-get"]; !ok {
		return aries.Miss
	}

	if err := mux.Serve(c); err != aries.Miss {
		return err
	}
	return aries.NotFound
}
