package netaddr

import (
	
	
	
	
)

// RelayURL is a URL identifying a relay server.
//
// It wraps a parsed URL and is cheap to copy. It is encouraged to use a
// fully-qualified DNS domain name (one ending in a ".", e.g. "relay.example.com.")
// so that local DNS search domains do not interfere with resolution.
//
// The zero value is not usable; construct a RelayURL with [ParseRelayURL] or
// [RelayURLFromURL].
type RelayURL struct {
	url *url.URL
}

// ParseRelayURL parses s into a RelayURL. It returns an error wrapping
// [ErrParseRelayURL] if s is not a valid URL.
func ( string) (RelayURL, error) {
	,  := url.Parse()
	if  != nil {
		return RelayURL{}, fmt.Errorf("%w: %v", ErrParseRelayURL, )
	}
	return RelayURLFromURL(), nil
}

// RelayURLFromURL wraps an already-parsed URL as a RelayURL, normalizing it so
// that equivalent URLs compare equal (see [RelayURL.String]).
func ( *url.URL) RelayURL {
	 := *
	return RelayURL{url: normalizeURL(&)}
}

// ErrParseRelayURL is returned (wrapped) when a relay URL cannot be parsed.
var ErrParseRelayURL = errors.New("failed to parse relay URL")

// URL returns a copy of the underlying parsed URL.
func ( RelayURL) () *url.URL {
	if .url == nil {
		return nil
	}
	 := *.url
	return &
}

// String returns the normalized string form of the URL. An empty path is
// rendered as "/", matching the WHATWG URL serialization used by the Rust
// reference implementation (e.g. "https://example.com" -> "https://example.com/").
func ( RelayURL) () string {
	if .url == nil {
		return ""
	}
	return .url.String()
}

// Host returns the host (without port) of the relay URL.
func ( RelayURL) () string {
	if .url == nil {
		return ""
	}
	return .url.Hostname()
}

// IsZero reports whether r is the unusable zero value.
func ( RelayURL) () bool { return .url == nil }

// Equal reports whether r and other are the same relay URL.
func ( RelayURL) ( RelayURL) bool { return .String() == .String() }

// Compare returns -1, 0, or +1 comparing r and other by their normalized
// string form, giving RelayURL a total order.
func ( RelayURL) ( RelayURL) int {
	return strings.Compare(.String(), .String())
}

// MarshalText implements encoding.TextMarshaler.
func ( RelayURL) () ([]byte, error) { return []byte(.String()), nil }

// UnmarshalText implements encoding.TextUnmarshaler.
func ( *RelayURL) ( []byte) error {
	,  := ParseRelayURL(string())
	if  != nil {
		return 
	}
	* = 
	return nil
}

// normalizeURL applies the small subset of WHATWG URL normalization that the
// reference implementation relies on: a special scheme (http/https/ws/wss) with
// an empty path serializes with a "/" path, and the host is lower-cased.
func normalizeURL( *url.URL) *url.URL {
	.Host = strings.ToLower(.Host)
	if .Path == "" && isSpecialScheme(.Scheme) {
		.Path = "/"
	}
	return 
}

func isSpecialScheme( string) bool {
	switch strings.ToLower() {
	case "http", "https", "ws", "wss", "ftp", "file":
		return true
	}
	return false
}