package flowcontrol

import (
	
	

	
	
	
	
)

type connectionFlowController struct {
	baseFlowController
}

var _ ConnectionFlowController = &connectionFlowController{}

// NewConnectionFlowController gets a new flow controller for the connection
// It is created before we receive the peer's transport parameters, thus it starts with a sendWindow of 0.
func (
	 protocol.ByteCount,
	 protocol.ByteCount,
	 func( protocol.ByteCount) bool,
	 *utils.RTTStats,
	 utils.Logger,
) *connectionFlowController {
	return &connectionFlowController{
		baseFlowController: baseFlowController{
			rttStats:             ,
			receiveWindow:        ,
			receiveWindowSize:    ,
			maxReceiveWindowSize: ,
			allowWindowIncrease:  ,
			logger:               ,
		},
	}
}

// IncrementHighestReceived adds an increment to the highestReceived value
func ( *connectionFlowController) ( protocol.ByteCount,  monotime.Time) error {
	.mutex.Lock()
	defer .mutex.Unlock()

	// If this is the first frame received on this connection, start flow-control auto-tuning.
	if .highestReceived == 0 {
		.startNewAutoTuningEpoch()
	}
	.highestReceived += 

	if .checkFlowControlViolation() {
		return &qerr.TransportError{
			ErrorCode:    qerr.FlowControlError,
			ErrorMessage: fmt.Sprintf("received %d bytes for the connection, allowed %d bytes", .highestReceived, .receiveWindow),
		}
	}
	return nil
}

func ( *connectionFlowController) ( protocol.ByteCount) ( bool) {
	.mutex.Lock()
	defer .mutex.Unlock()

	.addBytesRead()
	return .hasWindowUpdate()
}

func ( *connectionFlowController) ( monotime.Time) protocol.ByteCount {
	.mutex.Lock()
	defer .mutex.Unlock()

	 := .receiveWindowSize
	 := .getWindowUpdate()
	if .logger.Debug() &&  < .receiveWindowSize {
		.logger.Debugf("Increasing receive flow control window for the connection to %d kB", .receiveWindowSize/(1<<10))
	}
	return 
}

// EnsureMinimumWindowSize sets a minimum window size
// it should make sure that the connection-level window is increased when a stream-level window grows
func ( *connectionFlowController) ( protocol.ByteCount,  monotime.Time) {
	.mutex.Lock()
	defer .mutex.Unlock()

	if  <= .receiveWindowSize {
		return
	}
	 := min(, .maxReceiveWindowSize)
	if  :=  - .receiveWindowSize;  > 0 && .allowWindowIncrease() {
		.receiveWindowSize = 
		if .logger.Debug() {
			.logger.Debugf("Increasing receive flow control window for the connection to %d, in response to stream flow control window increase", )
		}
	}
	.startNewAutoTuningEpoch()
}

// Reset rests the flow controller. This happens when 0-RTT is rejected.
// All stream data is invalidated, it's as if we had never opened a stream and never sent any data.
// At that point, we only have sent stream data, but we didn't have the keys to open 1-RTT keys yet.
func ( *connectionFlowController) () error {
	.mutex.Lock()
	defer .mutex.Unlock()

	if .bytesRead > 0 || .highestReceived > 0 || !.epochStartTime.IsZero() {
		return errors.New("flow controller reset after reading data")
	}
	.bytesSent = 0
	.lastBlockedAt = 0
	.sendWindow = 0
	return nil
}