// Copyright 2016 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tcpinfo

import (
	
	

	
)

var (
	_ json.Marshaler = &Info{}
	_ tcpopt.Option  = &Info{}
)

// An Info represents connection information.
//
// Only supported on Darwin, FreeBSD, Linux and NetBSD.
type Info struct {
	State             State              `json:"state"`               // connection state
	Options           []Option           `json:"opts,omitempty"`      // requesting options
	PeerOptions       []Option           `json:"peer_opts,omitempty"` // options requested from peer
	SenderMSS         MaxSegSize         `json:"snd_mss"`             // maximum segment size for sender in bytes
	ReceiverMSS       MaxSegSize         `json:"rcv_mss"`             // maximum segment size for receiver in bytes
	RTT               time.Duration      `json:"rtt"`                 // round-trip time
	RTTVar            time.Duration      `json:"rttvar"`              // round-trip time variation
	RTO               time.Duration      `json:"rto"`                 // retransmission timeout
	ATO               time.Duration      `json:"ato"`                 // delayed acknowledgement timeout [Linux only]
	LastDataSent      time.Duration      `json:"last_data_sent"`      // since last data sent [Linux only]
	LastDataReceived  time.Duration      `json:"last_data_rcvd"`      // since last data received [FreeBSD and Linux]
	LastAckReceived   time.Duration      `json:"last_ack_rcvd"`       // since last ack received [Linux only]
	FlowControl       *FlowControl       `json:"flow_ctl,omitempty"`  // flow control information
	CongestionControl *CongestionControl `json:"cong_ctl,omitempty"`  // congestion control information
	Sys               *SysInfo           `json:"sys,omitempty"`       // platform-specific information
}

// A FlowControl represents flow control information.
type FlowControl struct {
	ReceiverWindow uint `json:"rcv_wnd"` // advertised receiver window in bytes
}

// A CongestionControl represents congestion control information.
type CongestionControl struct {
	SenderSSThreshold   uint `json:"snd_ssthresh"`   // slow start threshold for sender in bytes or # of segments
	ReceiverSSThreshold uint `json:"rcv_ssthresh"`   // slow start threshold for receiver in bytes [Linux only]
	SenderWindowBytes   uint `json:"snd_cwnd_bytes"` // congestion window for sender in bytes [Darwin and FreeBSD]
	SenderWindowSegs    uint `json:"snd_cwnd_segs"`  // congestion window for sender in # of segments [Linux and NetBSD]
}

// Level implements the Level method of tcpopt.Option interface.
func ( *Info) () int { return options[soInfo].level }

// Name implements the Name method of tcpopt.Option interface.
func ( *Info) () int { return options[soInfo].name }

// MarshalJSON implements the MarshalJSON method of json.Marshaler
// interface.
func ( *Info) () ([]byte, error) {
	 := make(map[string]interface{})
	["state"] = .State.String()
	if len(.Options) > 0 {
		 := make(map[string]interface{})
		for ,  := range .Options {
			[.Kind().String()] = 
		}
		["opts"] = 
	}
	if len(.PeerOptions) > 0 {
		 := make(map[string]interface{})
		for ,  := range .PeerOptions {
			[.Kind().String()] = 
		}
		["peer_opts"] = 
	}
	["snd_mss"] = .SenderMSS
	["rcv_mss"] = .ReceiverMSS
	["rtt"] = .RTT
	["rttvar"] = .RTTVar
	["rto"] = .RTO
	["ato"] = .ATO
	["last_data_sent"] = .LastDataSent
	["last_data_rcvd"] = .LastDataReceived
	["last_ack_rcvd"] = .LastAckReceived
	if .FlowControl != nil {
		["flow_ctl"] = .FlowControl
	}
	if .CongestionControl != nil {
		["cong_ctl"] = .CongestionControl
	}
	if .Sys != nil {
		["sys"] = .Sys
	}
	return json.Marshal(&)
}

// A CCInfo represents raw information of congestion control
// algorithm.
//
// Only supported on Linux.
type CCInfo struct {
	Raw []byte `json:"raw,omitempty"`
}

// Level implements the Level method of tcpopt.Option interface.
func ( *CCInfo) () int { return options[soCCInfo].level }

// Name implements the Name method of tcpopt.Option interface.
func ( *CCInfo) () int { return options[soCCInfo].name }

// Marshal implements the Marshal method of tcpopt.Option interface.
func ( *CCInfo) () ([]byte, error) { return .Raw, nil }

func parseCCInfo( []byte) (tcpopt.Option, error) { return &CCInfo{Raw: }, nil }

// A CCAlgorithm represents a name of congestion control algorithm.
//
// Only supported on Linux.
type CCAlgorithm string

// Level implements the Level method of tcpopt.Option interface.
func ( CCAlgorithm) () int { return options[soCCAlgo].level }

// Name implements the Name method of tcpopt.Option interface.
func ( CCAlgorithm) () int { return options[soCCAlgo].name }

// Marshal implements the Marshal method of tcpopt.Option interface.
func ( CCAlgorithm) () ([]byte, error) {
	if  == "" {
		return nil, nil
	}
	return []byte(), nil
}

func parseCCAlgorithm( []byte) (tcpopt.Option, error) { return CCAlgorithm(), nil }

// A CCAlgorithmInfo represents congestion control algorithm
// information.
//
// Only supported on Linux.
type CCAlgorithmInfo interface {
	Algorithm() string
}

// ParseCCAlgorithmInfo parses congestion control algorithm
// information.
//
// Only supported on Linux.
func ( string,  []byte) (CCAlgorithmInfo, error) {
	,  := parseCCAlgorithmInfo(, )
	if  != nil {
		return nil, 
	}
	return , nil
}