package rcmgr

import (
	
	
	

	
	
	
)

// ResourceScopeLimiter is a trait interface that allows you to access scope limits.
type ResourceScopeLimiter interface {
	Limit() Limit
	SetLimit(Limit)
}

var _ ResourceScopeLimiter = (*resourceScope)(nil)

// ResourceManagerStat is a trait that allows you to access resource manager state.
type ResourceManagerState interface {
	ListServices() []string
	ListProtocols() []protocol.ID
	ListPeers() []peer.ID

	Stat() ResourceManagerStat
}

type ResourceManagerStat struct {
	System    network.ScopeStat
	Transient network.ScopeStat
	Services  map[string]network.ScopeStat
	Protocols map[protocol.ID]network.ScopeStat
	Peers     map[peer.ID]network.ScopeStat
}

var _ ResourceManagerState = (*resourceManager)(nil)

func ( *resourceScope) () Limit {
	.Lock()
	defer .Unlock()

	return .rc.limit
}

func ( *resourceScope) ( Limit) {
	.Lock()
	defer .Unlock()

	.rc.limit = 
}

func ( *protocolScope) ( Limit) {
	.rcmgr.setStickyProtocol(.proto)
	.resourceScope.SetLimit()
}

func ( *peerScope) ( Limit) {
	.rcmgr.setStickyPeer(.peer)
	.resourceScope.SetLimit()
}

func ( *resourceManager) () []string {
	.mx.Lock()
	defer .mx.Unlock()

	 := make([]string, 0, len(.svc))
	for  := range .svc {
		 = append(, )
	}

	sort.Slice(, func(,  int) bool {
		return strings.Compare([], []) < 0
	})

	return 
}

func ( *resourceManager) () []protocol.ID {
	.mx.Lock()
	defer .mx.Unlock()

	 := make([]protocol.ID, 0, len(.proto))
	for  := range .proto {
		 = append(, )
	}

	sort.Slice(, func(,  int) bool {
		return [] < []
	})

	return 
}

func ( *resourceManager) () []peer.ID {
	.mx.Lock()
	defer .mx.Unlock()

	 := make([]peer.ID, 0, len(.peer))
	for  := range .peer {
		 = append(, )
	}

	sort.Slice(, func(,  int) bool {
		return bytes.Compare([]byte([]), []byte([])) < 0
	})

	return 
}

func ( *resourceManager) () ( ResourceManagerStat) {
	.mx.Lock()
	 := make([]*serviceScope, 0, len(.svc))
	for ,  := range .svc {
		 = append(, )
	}
	 := make([]*protocolScope, 0, len(.proto))
	for ,  := range .proto {
		 = append(, )
	}
	 := make([]*peerScope, 0, len(.peer))
	for ,  := range .peer {
		 = append(, )
	}
	.mx.Unlock()

	// Note: there is no global lock, so the system is updating while we are dumping its state...
	//       as such stats might not exactly add up to the system level; we take the system stat
	//       last nonetheless so that this is the most up-to-date snapshot
	.Peers = make(map[peer.ID]network.ScopeStat, len())
	for ,  := range  {
		.Peers[.peer] = .Stat()
	}
	.Protocols = make(map[protocol.ID]network.ScopeStat, len())
	for ,  := range  {
		.Protocols[.proto] = .Stat()
	}
	.Services = make(map[string]network.ScopeStat, len())
	for ,  := range  {
		.Services[.service] = .Stat()
	}
	.Transient = .transient.Stat()
	.System = .system.Stat()

	return 
}

func ( *resourceManager) () int {
	return .limits.GetSystemLimits().GetConnTotalLimit()
}