package sftp

import (
	"net/url"
	"path"
	"strings"

	"github.com/restic/restic/internal/errors"
	"github.com/restic/restic/internal/options"
)

// Config collects all information required to connect to an sftp server.
type Config struct {
	User, Host, Path string
	Layout           string `option:"layout" help:"use this backend directory layout (default: auto-detect)"`
	Command          string `option:"command" help:"specify command to create sftp connection"`
}

func init() {
	options.Register("sftp", Config{})
}

// ParseConfig parses the string s and extracts the sftp config. The
// supported configuration formats are sftp://user@host/directory
//  and sftp:user@host:directory.  The directory will be path Cleaned and can
//  be an absolute path if it starts with a '/' (e.g.
//  sftp://user@host//absolute and sftp:user@host:/absolute).
func ParseConfig(s string) (interface{}, error) {
	var user, host, dir string
	switch {
	case strings.HasPrefix(s, "sftp://"):
		// parse the "sftp://user@host/path" url format
		url, err := url.Parse(s)
		if err != nil {
			return nil, errors.Wrap(err, "url.Parse")
		}
		if url.User != nil {
			user = url.User.Username()
		}
		host = url.Host
		dir = url.Path
		if dir == "" {
			return nil, errors.Errorf("invalid backend %q, no directory specified", s)
		}

		dir = dir[1:]
	case strings.HasPrefix(s, "sftp:"):
		// parse the sftp:user@host:path format, which means we'll get
		// "user@host:path" in s
		s = s[5:]
		// split user@host and path at the colon
		data := strings.SplitN(s, ":", 2)
		if len(data) < 2 {
			return nil, errors.New("sftp: invalid format, hostname or path not found")
		}
		host = data[0]
		dir = data[1]
		// split user and host at the "@"
		data = strings.SplitN(host, "@", 2)
		if len(data) == 2 {
			user = data[0]
			host = data[1]
		}
	default:
		return nil, errors.New(`invalid format, does not start with "sftp:"`)
	}
	return Config{
		User: user,
		Host: host,
		Path: path.Clean(dir),
	}, nil
}
