package endpoints

import (
	
	
	
	

	
)

// DefaultKey is a compound map key of a variant and other values.
type DefaultKey struct {
	Variant        EndpointVariant
	ServiceVariant ServiceVariant
}

// EndpointKey is a compound map key of a region and associated variant value.
type EndpointKey struct {
	Region         string
	Variant        EndpointVariant
	ServiceVariant ServiceVariant
}

// EndpointVariant is a bit field to describe the endpoints attributes.
type EndpointVariant uint64

const (
	// FIPSVariant indicates that the endpoint is FIPS capable.
	FIPSVariant EndpointVariant = 1 << (64 - 1 - iota)

	// DualStackVariant indicates that the endpoint is DualStack capable.
	DualStackVariant
)

// ServiceVariant is a bit field to describe the service endpoint attributes.
type ServiceVariant uint64

const (
	defaultProtocol = "https"
	defaultSigner   = "v4"
)

var (
	protocolPriority = []string{"https", "http"}
	signerPriority   = []string{"v4", "s3v4"}
)

// Options provide configuration needed to direct how endpoints are resolved.
type Options struct {
	// Logger is a logging implementation that log events should be sent to.
	Logger logging.Logger

	// LogDeprecated indicates that deprecated endpoints should be logged to the provided logger.
	LogDeprecated bool

	// ResolvedRegion is the resolved region string. If provided (non-zero length) it takes priority
	// over the region name passed to the ResolveEndpoint call.
	ResolvedRegion string

	// Disable usage of HTTPS (TLS / SSL)
	DisableHTTPS bool

	// Instruct the resolver to use a service endpoint that supports dual-stack.
	// If a service does not have a dual-stack endpoint an error will be returned by the resolver.
	UseDualStackEndpoint aws.DualStackEndpointState

	// Instruct the resolver to use a service endpoint that supports FIPS.
	// If a service does not have a FIPS endpoint an error will be returned by the resolver.
	UseFIPSEndpoint aws.FIPSEndpointState

	// ServiceVariant is a bitfield of service specified endpoint variant data.
	ServiceVariant ServiceVariant
}

// GetEndpointVariant returns the EndpointVariant for the variant associated options.
func ( Options) () ( EndpointVariant) {
	if .UseDualStackEndpoint == aws.DualStackEndpointStateEnabled {
		 |= DualStackVariant
	}
	if .UseFIPSEndpoint == aws.FIPSEndpointStateEnabled {
		 |= FIPSVariant
	}
	return 
}

// Partitions is a slice of partition
type Partitions []Partition

// ResolveEndpoint resolves a service endpoint for the given region and options.
func ( Partitions) ( string,  Options) (aws.Endpoint, error) {
	if len() == 0 {
		return aws.Endpoint{}, fmt.Errorf("no partitions found")
	}

	if .Logger == nil {
		.Logger = logging.Nop{}
	}

	if len(.ResolvedRegion) > 0 {
		 = .ResolvedRegion
	}

	for  := 0;  < len(); ++ {
		if ![].canResolveEndpoint(, ) {
			continue
		}

		return [].ResolveEndpoint(, )
	}

	// fallback to first partition format to use when resolving the endpoint.
	return [0].ResolveEndpoint(, )
}

// Partition is an AWS partition description for a service and its' region endpoints.
type Partition struct {
	ID                string
	RegionRegex       *regexp.Regexp
	PartitionEndpoint string
	IsRegionalized    bool
	Defaults          map[DefaultKey]Endpoint
	Endpoints         Endpoints
}

func ( Partition) ( string,  Options) bool {
	,  := .Endpoints[EndpointKey{
		Region:  ,
		Variant: .GetEndpointVariant(),
	}]
	return  || .RegionRegex.MatchString()
}

// ResolveEndpoint resolves and service endpoint for the given region and options.
func ( Partition) ( string,  Options) ( aws.Endpoint,  error) {
	if len() == 0 && len(.PartitionEndpoint) != 0 {
		 = .PartitionEndpoint
	}

	 := .Endpoints

	 := .GetEndpointVariant()
	 := .ServiceVariant

	 := .Defaults[DefaultKey{
		Variant:        ,
		ServiceVariant: ,
	}]

	return .endpointForRegion(, , , ).resolve(.ID, , , )
}

func ( Partition) ( string,  EndpointVariant,  ServiceVariant,  Endpoints) Endpoint {
	 := EndpointKey{
		Region:  ,
		Variant: ,
	}

	if ,  := [];  {
		return 
	}

	if !.IsRegionalized {
		return [EndpointKey{
			Region:         .PartitionEndpoint,
			Variant:        ,
			ServiceVariant: ,
		}]
	}

	// Unable to find any matching endpoint, return
	// blank that will be used for generic endpoint creation.
	return Endpoint{}
}

// Endpoints is a map of service config regions to endpoints
type Endpoints map[EndpointKey]Endpoint

// CredentialScope is the credential scope of a region and service
type CredentialScope struct {
	Region  string
	Service string
}

// Endpoint is a service endpoint description
type Endpoint struct {
	// True if the endpoint cannot be resolved for this partition/region/service
	Unresolveable aws.Ternary

	Hostname  string
	Protocols []string

	CredentialScope CredentialScope

	SignatureVersions []string

	// Indicates that this endpoint is deprecated.
	Deprecated aws.Ternary
}

// IsZero returns whether the endpoint structure is an empty (zero) value.
func ( Endpoint) () bool {
	switch {
	case .Unresolveable != aws.UnknownTernary:
		return false
	case len(.Hostname) != 0:
		return false
	case len(.Protocols) != 0:
		return false
	case .CredentialScope != (CredentialScope{}):
		return false
	case len(.SignatureVersions) != 0:
		return false
	}
	return true
}

func ( Endpoint) (,  string,  Endpoint,  Options) (aws.Endpoint, error) {
	var  Endpoint
	.mergeIn()
	.mergeIn()
	 = 

	if .IsZero() {
		return aws.Endpoint{}, fmt.Errorf("unable to resolve endpoint for region: %v", )
	}

	var  string
	if .Unresolveable != aws.TrueTernary {
		// Only attempt to resolve the endpoint if it can be resolved.
		 := strings.Replace(.Hostname, "{region}", , 1)

		 := getEndpointScheme(.Protocols, .DisableHTTPS)
		 =  + "://" + 
	}

	 := .CredentialScope.Region
	if len() == 0 {
		 = 
	}
	 := .CredentialScope.Service

	if .Deprecated == aws.TrueTernary && .LogDeprecated {
		.Logger.Logf(logging.Warn, "endpoint identifier %q, url %q marked as deprecated", , )
	}

	return aws.Endpoint{
		URL:           ,
		PartitionID:   ,
		SigningRegion: ,
		SigningName:   ,
		SigningMethod: getByPriority(.SignatureVersions, signerPriority, defaultSigner),
	}, nil
}

func ( *Endpoint) ( Endpoint) {
	if .Unresolveable != aws.UnknownTernary {
		.Unresolveable = .Unresolveable
	}
	if len(.Hostname) > 0 {
		.Hostname = .Hostname
	}
	if len(.Protocols) > 0 {
		.Protocols = .Protocols
	}
	if len(.CredentialScope.Region) > 0 {
		.CredentialScope.Region = .CredentialScope.Region
	}
	if len(.CredentialScope.Service) > 0 {
		.CredentialScope.Service = .CredentialScope.Service
	}
	if len(.SignatureVersions) > 0 {
		.SignatureVersions = .SignatureVersions
	}
	if .Deprecated != aws.UnknownTernary {
		.Deprecated = .Deprecated
	}
}

func ( []string,  bool) string {
	if  {
		return "http"
	}

	return getByPriority(, protocolPriority, defaultProtocol)
}

func ( []string,  []string,  string) string {
	if len() == 0 {
		return 
	}

	for  := 0;  < len(); ++ {
		for  := 0;  < len(); ++ {
			if [] == [] {
				return []
			}
		}
	}

	return [0]
}