package sftp

import (
	"errors"
	"net/url"
	"strings"
)

// Config collects all information required to connect to an sftp server.
type Config struct {
	User, Host, Dir string
}

// ParseConfig extracts all information for the sftp connection from the string s.
func ParseConfig(s string) (interface{}, error) {
	if strings.HasPrefix(s, "sftp://") {
		return parseFormat1(s)
	}

	// otherwise parse in the sftp:user@host:path format, which means we'll get
	// "user@host:path" in s
	return parseFormat2(s)
}

// parseFormat1 parses the first format, starting with a slash, so the user
// either specified "sftp://host/path", so we'll get everything after the first
// colon character
func parseFormat1(s string) (Config, error) {
	url, err := url.Parse(s)
	if err != nil {
		return Config{}, err
	}

	cfg := Config{
		Host: url.Host,
		Dir:  url.Path[1:],
	}
	if url.User != nil {
		cfg.User = url.User.Username()
	}
	return cfg, nil
}

// parseFormat2 parses the second format, sftp:user@host:path
func parseFormat2(s string) (cfg Config, err error) {
	// split user/host and path at the second colon
	data := strings.SplitN(s, ":", 3)
	if len(data) < 3 {
		return Config{}, errors.New("sftp: invalid format, hostname or path not found")
	}

	if data[0] != "sftp" {
		return Config{}, errors.New(`invalid format, does not start with "sftp:"`)
	}

	userhost := data[1]
	cfg.Dir = data[2]

	data = strings.SplitN(userhost, "@", 2)
	if len(data) == 2 {
		cfg.User = data[0]
		cfg.Host = data[1]
	} else {
		cfg.Host = userhost
	}

	return cfg, nil
}