package net

import (
	
	
	

	
)

var invoke common.Invoker = common.Invoke{}

type IOCountersStat struct {
	Name        string `json:"name"`        // interface name
	BytesSent   uint64 `json:"bytesSent"`   // number of bytes sent
	BytesRecv   uint64 `json:"bytesRecv"`   // number of bytes received
	PacketsSent uint64 `json:"packetsSent"` // number of packets sent
	PacketsRecv uint64 `json:"packetsRecv"` // number of packets received
	Errin       uint64 `json:"errin"`       // total number of errors while receiving
	Errout      uint64 `json:"errout"`      // total number of errors while sending
	Dropin      uint64 `json:"dropin"`      // total number of incoming packets which were dropped
	Dropout     uint64 `json:"dropout"`     // total number of outgoing packets which were dropped (always 0 on OSX and BSD)
	Fifoin      uint64 `json:"fifoin"`      // total number of FIFO buffers errors while receiving
	Fifoout     uint64 `json:"fifoout"`     // total number of FIFO buffers errors while sending
}

// Addr is implemented compatibility to psutil
type Addr struct {
	IP   string `json:"ip"`
	Port uint32 `json:"port"`
}

type ConnectionStat struct {
	Fd     uint32  `json:"fd"`
	Family uint32  `json:"family"`
	Type   uint32  `json:"type"`
	Laddr  Addr    `json:"localaddr"`
	Raddr  Addr    `json:"remoteaddr"`
	Status string  `json:"status"`
	Uids   []int32 `json:"uids"`
	Pid    int32   `json:"pid"`
}

// System wide stats about different network protocols
type ProtoCountersStat struct {
	Protocol string           `json:"protocol"`
	Stats    map[string]int64 `json:"stats"`
}

// NetInterfaceAddr is designed for represent interface addresses
type InterfaceAddr struct {
	Addr string `json:"addr"`
}

type InterfaceStat struct {
	Index        int             `json:"index"`
	MTU          int             `json:"mtu"`          // maximum transmission unit
	Name         string          `json:"name"`         // e.g., "en0", "lo0", "eth0.100"
	HardwareAddr string          `json:"hardwareaddr"` // IEEE MAC-48, EUI-48 and EUI-64 form
	Flags        []string        `json:"flags"`        // e.g., FlagUp, FlagLoopback, FlagMulticast
	Addrs        []InterfaceAddr `json:"addrs"`
}

type FilterStat struct {
	ConnTrackCount int64 `json:"conntrackCount"`
	ConnTrackMax   int64 `json:"conntrackMax"`
}

// ConntrackStat has conntrack summary info
type ConntrackStat struct {
	Entries       uint32 `json:"entries"`        // Number of entries in the conntrack table
	Searched      uint32 `json:"searched"`       // Number of conntrack table lookups performed
	Found         uint32 `json:"found"`          // Number of searched entries which were successful
	New           uint32 `json:"new"`            // Number of entries added which were not expected before
	Invalid       uint32 `json:"invalid"`        // Number of packets seen which can not be tracked
	Ignore        uint32 `json:"ignore"`         // Packets seen which are already connected to an entry
	Delete        uint32 `json:"delete"`         // Number of entries which were removed
	DeleteList    uint32 `json:"delete_list"`    // Number of entries which were put to dying list
	Insert        uint32 `json:"insert"`         // Number of entries inserted into the list
	InsertFailed  uint32 `json:"insert_failed"`  // # insertion attempted but failed (same entry exists)
	Drop          uint32 `json:"drop"`           // Number of packets dropped due to conntrack failure.
	EarlyDrop     uint32 `json:"early_drop"`     // Dropped entries to make room for new ones, if maxsize reached
	IcmpError     uint32 `json:"icmp_error"`     // Subset of invalid. Packets that can't be tracked d/t error
	ExpectNew     uint32 `json:"expect_new"`     // Entries added after an expectation was already present
	ExpectCreate  uint32 `json:"expect_create"`  // Expectations added
	ExpectDelete  uint32 `json:"expect_delete"`  // Expectations deleted
	SearchRestart uint32 `json:"search_restart"` // Conntrack table lookups restarted due to hashtable resizes
}

func (, , , , , , , , , , , , , , , ,  uint32) *ConntrackStat {
	return &ConntrackStat{
		Entries:       ,
		Searched:      ,
		Found:         ,
		New:           ,
		Invalid:       ,
		Ignore:        ,
		Delete:        ,
		DeleteList:    ,
		Insert:        ,
		InsertFailed:  ,
		Drop:          ,
		EarlyDrop:     ,
		IcmpError:     ,
		ExpectNew:     ,
		ExpectCreate:  ,
		ExpectDelete:  ,
		SearchRestart: ,
	}
}

type ConntrackStatList struct {
	items []*ConntrackStat
}

func () *ConntrackStatList {
	return &ConntrackStatList{
		items: []*ConntrackStat{},
	}
}

func ( *ConntrackStatList) ( *ConntrackStat) {
	.items = append(.items, )
}

func ( *ConntrackStatList) () []ConntrackStat {
	 := make([]ConntrackStat, len(.items))
	for ,  := range .items {
		[] = *
	}
	return 
}

// Summary returns a single-element list with totals from all list items.
func ( *ConntrackStatList) () []ConntrackStat {
	 := NewConntrackStat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
	for ,  := range .items {
		.Entries += .Entries
		.Searched += .Searched
		.Found += .Found
		.New += .New
		.Invalid += .Invalid
		.Ignore += .Ignore
		.Delete += .Delete
		.DeleteList += .DeleteList
		.Insert += .Insert
		.InsertFailed += .InsertFailed
		.Drop += .Drop
		.EarlyDrop += .EarlyDrop
		.IcmpError += .IcmpError
		.ExpectNew += .ExpectNew
		.ExpectCreate += .ExpectCreate
		.ExpectDelete += .ExpectDelete
		.SearchRestart += .SearchRestart
	}
	return []ConntrackStat{*}
}

func ( IOCountersStat) () string {
	,  := json.Marshal()
	return string()
}

func ( ConnectionStat) () string {
	,  := json.Marshal()
	return string()
}

func ( ProtoCountersStat) () string {
	,  := json.Marshal()
	return string()
}

func ( Addr) () string {
	,  := json.Marshal()
	return string()
}

func ( InterfaceStat) () string {
	,  := json.Marshal()
	return string()
}

func ( InterfaceAddr) () string {
	,  := json.Marshal()
	return string()
}

func ( ConntrackStat) () string {
	,  := json.Marshal()
	return string()
}

func () ([]InterfaceStat, error) {
	return InterfacesWithContext(context.Background())
}

func ( context.Context) ([]InterfaceStat, error) {
	,  := net.Interfaces()
	if  != nil {
		return nil, 
	}
	 := make([]InterfaceStat, 0, len())
	for ,  := range  {

		var  []string
		if .Flags&net.FlagUp != 0 {
			 = append(, "up")
		}
		if .Flags&net.FlagBroadcast != 0 {
			 = append(, "broadcast")
		}
		if .Flags&net.FlagLoopback != 0 {
			 = append(, "loopback")
		}
		if .Flags&net.FlagPointToPoint != 0 {
			 = append(, "pointtopoint")
		}
		if .Flags&net.FlagMulticast != 0 {
			 = append(, "multicast")
		}

		 := InterfaceStat{
			Index:        .Index,
			Name:         .Name,
			MTU:          .MTU,
			HardwareAddr: .HardwareAddr.String(),
			Flags:        ,
		}
		,  := .Addrs()
		if  == nil {
			.Addrs = make([]InterfaceAddr, 0, len())
			for ,  := range  {
				.Addrs = append(.Addrs, InterfaceAddr{
					Addr: .String(),
				})
			}

		}
		 = append(, )
	}

	return , nil
}

func getIOCountersAll( []IOCountersStat) ([]IOCountersStat, error) {
	 := IOCountersStat{
		Name: "all",
	}
	for ,  := range  {
		.BytesRecv += .BytesRecv
		.PacketsRecv += .PacketsRecv
		.Errin += .Errin
		.Dropin += .Dropin
		.BytesSent += .BytesSent
		.PacketsSent += .PacketsSent
		.Errout += .Errout
		.Dropout += .Dropout
	}

	return []IOCountersStat{}, nil
}