// Copyright 2015 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 gerrit

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	"golang.org/x/oauth2"
)

// Auth is a Gerrit authentication mode.
// The most common ones are NoAuth or BasicAuth.
type Auth interface {
	setAuth(*Client, *http.Request) error
}

// BasicAuth sends a username and password.
func BasicAuth(username, password string) Auth {
	return basicAuth{username, password}
}

type basicAuth struct {
	username, password string
}

func (ba basicAuth) setAuth(c *Client, r *http.Request) error {
	r.SetBasicAuth(ba.username, ba.password)
	return nil
}

// GitCookiesAuth derives the Gerrit authentication token from
// gitcookies based on the URL of the Gerrit request.
// The cookie file used is determined by running "git config
// http.cookiefile" in the current directory.
// To use a specific file, see GitCookieFileAuth.
func GitCookiesAuth() Auth {
	return gitCookiesAuth{}
}

// GitCookieFileAuth derives the Gerrit authentication token from the
// provided gitcookies file. It is equivalent to GitCookiesAuth,
// except that "git config http.cookiefile" is not used to find which
// cookie file to use.
func GitCookieFileAuth(file string) Auth {
	return &gitCookieFileAuth{file: file}
}

func netrcPath() string {
	if runtime.GOOS == "windows" {
		return filepath.Join(os.Getenv("USERPROFILE"), "_netrc")
	}
	return filepath.Join(os.Getenv("HOME"), ".netrc")
}

type gitCookiesAuth struct{}

func (gitCookiesAuth) setAuth(c *Client, r *http.Request) error {
	// First look in Git's http.cookiefile, which is where Gerrit
	// now tells users to store this information.
	git := exec.Command("git", "config", "http.cookiefile")
	git.Stderr = os.Stderr

	// Ignore a failure here, git will exit(1) if no cookies are
	// present and prevent the netrc from being read below.
	gitOut, _ := git.Output()

	cookieFile := strings.TrimSpace(string(gitOut))
	if len(cookieFile) != 0 {
		auth := &gitCookieFileAuth{file: cookieFile}
		if err := auth.setAuth(c, r); err != nil {
			return err
		}
		if len(r.Header["Cookie"]) > 0 {
			return nil
		}
	}

	url, err := url.Parse(c.url)
	if err != nil {
		return err
	}

	// If not there, then look in $HOME/.netrc, which is where Gerrit
	// used to tell users to store the information, until the passwords
	// got so long that old versions of curl couldn't handle them.
	host := url.Host
	netrc := netrcPath()
	data, _ := ioutil.ReadFile(netrc)
	for _, line := range strings.Split(string(data), "\n") {
		if i := strings.Index(line, "#"); i >= 0 {
			line = line[:i]
		}
		f := strings.Fields(line)
		if len(f) >= 6 && f[0] == "machine" && f[1] == host && f[2] == "login" && f[4] == "password" {
			r.SetBasicAuth(f[3], f[5])
			return nil
		}
	}
	return fmt.Errorf("no authentication configured for Gerrit; tried both git config http.cookiefile and %s", netrc)
}

type gitCookieFileAuth struct {
	file string

	once sync.Once
	jar  *cookiejar.Jar
	err  error
}

func (a *gitCookieFileAuth) loadCookieFileOnce() {
	data, err := ioutil.ReadFile(a.file)
	if err != nil {
		a.err = fmt.Errorf("Error loading cookie file: %v", err)
		return
	}
	a.jar = parseGitCookies(string(data))
}

func (a *gitCookieFileAuth) setAuth(c *Client, r *http.Request) error {
	a.once.Do(a.loadCookieFileOnce)
	if a.err != nil {
		return a.err
	}

	url, err := url.Parse(c.url)
	if err != nil {
		return err
	}

	for _, cookie := range a.jar.Cookies(url) {
		r.AddCookie(cookie)
	}
	return nil
}

func parseGitCookies(data string) *cookiejar.Jar {
	jar, _ := cookiejar.New(nil)
	for _, line := range strings.Split(data, "\n") {
		f := strings.Split(line, "\t")
		if len(f) < 7 {
			continue
		}
		expires, err := strconv.ParseInt(f[4], 10, 64)
		if err != nil {
			continue
		}
		c := http.Cookie{
			Domain:  f[0],
			Path:    f[2],
			Secure:  f[3] == "TRUE",
			Expires: time.Unix(expires, 0),
			Name:    f[5],
			Value:   f[6],
		}
		// Construct a fake URL to add c to the jar.
		url := url.URL{
			Scheme: "http",
			Host:   c.Domain,
			Path:   c.Path,
		}
		jar.SetCookies(&url, []*http.Cookie{&c})
	}
	return jar
}

// Scopes to use when creating a TokenSource.
var OAuth2Scopes = []string{
	"https://www.googleapis.com/auth/cloud-platform",
	"https://www.googleapis.com/auth/gerritcodereview",
	"https://www.googleapis.com/auth/source.full_control",
	"https://www.googleapis.com/auth/source.read_write",
	"https://www.googleapis.com/auth/source.read_only",
}

// OAuth2Auth uses the given TokenSource to authenticate requests.
func OAuth2Auth(src oauth2.TokenSource) Auth {
	return oauth2Auth{src}
}

type oauth2Auth struct {
	src oauth2.TokenSource
}

func (a oauth2Auth) setAuth(c *Client, r *http.Request) error {
	token, err := a.src.Token()
	if err != nil {
		return err
	}
	token.SetAuthHeader(r)
	return nil
}

// NoAuth makes requests unauthenticated.
var NoAuth = noAuth{}

type noAuth struct{}

func (noAuth) setAuth(c *Client, r *http.Request) error {
	return nil
}

type digestAuth struct {
	Username, Password, Realm, NONCE, QOP, Opaque, Algorithm string
}

func getDigestAuth(username, password string, resp *http.Response) *digestAuth {
	header := resp.Header.Get("www-authenticate")
	parts := strings.SplitN(header, " ", 2)
	parts = strings.Split(parts[1], ", ")
	opts := make(map[string]string)

	for _, part := range parts {
		vals := strings.SplitN(part, "=", 2)
		key := vals[0]
		val := strings.Trim(vals[1], "\",")
		opts[key] = val
	}

	auth := digestAuth{
		username, password,
		opts["realm"], opts["nonce"], opts["qop"], opts["opaque"], opts["algorithm"],
	}
	return &auth
}

func setDigestAuth(r *http.Request, username, password string, resp *http.Response, nc int) {
	auth := getDigestAuth(username, password, resp)
	authStr := getDigestAuthString(auth, r.URL, r.Method, nc)
	r.Header.Add("Authorization", authStr)
}

func getDigestAuthString(auth *digestAuth, url *url.URL, method string, nc int) string {
	var buf bytes.Buffer
	h := md5.New()
	fmt.Fprintf(&buf, "%s:%s:%s", auth.Username, auth.Realm, auth.Password)
	buf.WriteTo(h)
	ha1 := hex.EncodeToString(h.Sum(nil))

	h = md5.New()
	fmt.Fprintf(&buf, "%s:%s", method, url.Path)
	buf.WriteTo(h)
	ha2 := hex.EncodeToString(h.Sum(nil))

	ncStr := fmt.Sprintf("%08x", nc)
	hnc := "MTM3MDgw"

	h = md5.New()
	fmt.Fprintf(&buf, "%s:%s:%s:%s:%s:%s", ha1, auth.NONCE, ncStr, hnc, auth.QOP, ha2)
	buf.WriteTo(h)
	respdig := hex.EncodeToString(h.Sum(nil))

	buf.Write([]byte("Digest "))
	fmt.Fprintf(&buf,
		`username="%s", realm="%s", nonce="%s", uri="%s", response="%s"`,
		auth.Username, auth.Realm, auth.NONCE, url.Path, respdig,
	)

	if auth.Opaque != "" {
		fmt.Fprintf(&buf, `, opaque="%s"`, auth.Opaque)
	}
	if auth.QOP != "" {
		fmt.Fprintf(&buf, `, qop="%s", nc=%s, cnonce="%s"`, auth.QOP, ncStr, hnc)
	}
	if auth.Algorithm != "" {
		fmt.Fprintf(&buf, `, algorithm="%s"`, auth.Algorithm)
	}

	return buf.String()
}

func (a digestAuth) setAuth(c *Client, r *http.Request) error {
	resp, err := http.Get(r.URL.String())
	if err != nil {
		return err
	}
	setDigestAuth(r, a.Username, a.Password, resp, 1)
	return nil
}

// DigestAuth returns an Auth implementation which sends
// the provided username and password using HTTP Digest Authentication
// (RFC 2617)
func DigestAuth(username, password string) Auth {
	return digestAuth{
		Username: username,
		Password: password,
	}
}
