// Package transport includes the implementation for different transport
// protocols.
//
// `Client` can be used to fetch and send packfiles to a git server.
// The `client` package provides higher level functions to instantiate the
// appropriate `Client` based on the repository URL.
//
// go-git supports HTTP and SSH (see `Protocols`), but you can also install
// your own protocols (see the `client` package).
//
// Each protocol has its own implementation of `Client`, but you should
// generally not use them directly, use `client.NewClient` instead.
package transport

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"net/url"
	"strconv"
	"strings"

	giturl "gopkg.in/src-d/go-git.v4/internal/url"
	"gopkg.in/src-d/go-git.v4/plumbing"
	"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
	"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
)

var (
	ErrRepositoryNotFound     = errors.New("repository not found")
	ErrEmptyRemoteRepository  = errors.New("remote repository is empty")
	ErrAuthenticationRequired = errors.New("authentication required")
	ErrAuthorizationFailed    = errors.New("authorization failed")
	ErrEmptyUploadPackRequest = errors.New("empty git-upload-pack given")
	ErrInvalidAuthMethod      = errors.New("invalid auth method")
	ErrAlreadyConnected       = errors.New("session already established")
)

const (
	UploadPackServiceName  = "git-upload-pack"
	ReceivePackServiceName = "git-receive-pack"
)

// Transport can initiate git-upload-pack and git-receive-pack processes.
// It is implemented both by the client and the server, making this a RPC.
type Transport interface {
	// NewUploadPackSession starts a git-upload-pack session for an endpoint.
	NewUploadPackSession(*Endpoint, AuthMethod) (UploadPackSession, error)
	// NewReceivePackSession starts a git-receive-pack session for an endpoint.
	NewReceivePackSession(*Endpoint, AuthMethod) (ReceivePackSession, error)
}

type Session interface {
	// AdvertisedReferences retrieves the advertised references for a
	// repository.
	// If the repository does not exist, returns ErrRepositoryNotFound.
	// If the repository exists, but is empty, returns ErrEmptyRemoteRepository.
	AdvertisedReferences() (*packp.AdvRefs, error)
	io.Closer
}

type AuthMethod interface {
	fmt.Stringer
	Name() string
}

// UploadPackSession represents a git-upload-pack session.
// A git-upload-pack session has two steps: reference discovery
// (AdvertisedReferences) and uploading pack (UploadPack).
type UploadPackSession interface {
	Session
	// UploadPack takes a git-upload-pack request and returns a response,
	// including a packfile. Don't be confused by terminology, the client
	// side of a git-upload-pack is called git-fetch-pack, although here
	// the same interface is used to make it RPC-like.
	UploadPack(context.Context, *packp.UploadPackRequest) (*packp.UploadPackResponse, error)
}

// ReceivePackSession represents a git-receive-pack session.
// A git-receive-pack session has two steps: reference discovery
// (AdvertisedReferences) and receiving pack (ReceivePack).
// In that order.
type ReceivePackSession interface {
	Session
	// ReceivePack sends an update references request and a packfile
	// reader and returns a ReportStatus and error. Don't be confused by
	// terminology, the client side of a git-receive-pack is called
	// git-send-pack, although here the same interface is used to make it
	// RPC-like.
	ReceivePack(context.Context, *packp.ReferenceUpdateRequest) (*packp.ReportStatus, error)
}

// Endpoint represents a Git URL in any supported protocol.
type Endpoint struct {
	// Protocol is the protocol of the endpoint (e.g. git, https, file).
	Protocol string
	// User is the user.
	User string
	// Password is the password.
	Password string
	// Host is the host.
	Host string
	// Port is the port to connect, if 0 the default port for the given protocol
	// wil be used.
	Port int
	// Path is the repository path.
	Path string
}

var defaultPorts = map[string]int{
	"http":  80,
	"https": 443,
	"git":   9418,
	"ssh":   22,
}

// String returns a string representation of the Git URL.
func (u *Endpoint) String() string {
	var buf bytes.Buffer
	if u.Protocol != "" {
		buf.WriteString(u.Protocol)
		buf.WriteByte(':')
	}

	if u.Protocol != "" || u.Host != "" || u.User != "" || u.Password != "" {
		buf.WriteString("//")

		if u.User != "" || u.Password != "" {
			buf.WriteString(url.PathEscape(u.User))
			if u.Password != "" {
				buf.WriteByte(':')
				buf.WriteString(url.PathEscape(u.Password))
			}

			buf.WriteByte('@')
		}

		if u.Host != "" {
			buf.WriteString(u.Host)

			if u.Port != 0 {
				port, ok := defaultPorts[strings.ToLower(u.Protocol)]
				if !ok || ok && port != u.Port {
					fmt.Fprintf(&buf, ":%d", u.Port)
				}
			}
		}
	}

	if u.Path != "" && u.Path[0] != '/' && u.Host != "" {
		buf.WriteByte('/')
	}

	buf.WriteString(u.Path)
	return buf.String()
}

func NewEndpoint(endpoint string) (*Endpoint, error) {
	if e, ok := parseSCPLike(endpoint); ok {
		return e, nil
	}

	if e, ok := parseFile(endpoint); ok {
		return e, nil
	}

	return parseURL(endpoint)
}

func parseURL(endpoint string) (*Endpoint, error) {
	u, err := url.Parse(endpoint)
	if err != nil {
		return nil, err
	}

	if !u.IsAbs() {
		return nil, plumbing.NewPermanentError(fmt.Errorf(
			"invalid endpoint: %s", endpoint,
		))
	}

	var user, pass string
	if u.User != nil {
		user = u.User.Username()
		pass, _ = u.User.Password()
	}

	return &Endpoint{
		Protocol: u.Scheme,
		User:     user,
		Password: pass,
		Host:     u.Hostname(),
		Port:     getPort(u),
		Path:     getPath(u),
	}, nil
}

func getPort(u *url.URL) int {
	p := u.Port()
	if p == "" {
		return 0
	}

	i, err := strconv.Atoi(p)
	if err != nil {
		return 0
	}

	return i
}

func getPath(u *url.URL) string {
	var res string = u.Path
	if u.RawQuery != "" {
		res += "?" + u.RawQuery
	}

	if u.Fragment != "" {
		res += "#" + u.Fragment
	}

	return res
}

func parseSCPLike(endpoint string) (*Endpoint, bool) {
	if giturl.MatchesScheme(endpoint) || !giturl.MatchesScpLike(endpoint) {
		return nil, false
	}

	user, host, portStr, path := giturl.FindScpLikeComponents(endpoint)
	port, err := strconv.Atoi(portStr)
	if err != nil {
		port = 22
	}

	return &Endpoint{
		Protocol: "ssh",
		User:     user,
		Host:     host,
		Port:     port,
		Path:     path,
	}, true
}

func parseFile(endpoint string) (*Endpoint, bool) {
	if giturl.MatchesScheme(endpoint) {
		return nil, false
	}

	path := endpoint
	return &Endpoint{
		Protocol: "file",
		Path:     path,
	}, true
}

// UnsupportedCapabilities are the capabilities not supported by any client
// implementation
var UnsupportedCapabilities = []capability.Capability{
	capability.MultiACK,
	capability.MultiACKDetailed,
	capability.ThinPack,
}

// FilterUnsupportedCapabilities it filter out all the UnsupportedCapabilities
// from a capability.List, the intended usage is on the client implementation
// to filter the capabilities from an AdvRefs message.
func FilterUnsupportedCapabilities(list *capability.List) {
	for _, c := range UnsupportedCapabilities {
		list.Delete(c)
	}
}
