package usb

// Device represents a USB device
type Device struct {
	BusID          string `json:"bus_id"` // e.g. "1-1.4"
	BusNum         uint32 `json:"bus_num"`
	DevNum         uint32 `json:"dev_num"`
	Speed          uint32 `json:"speed"`
	VendorID       uint16 `json:"vendor_id"`
	ProductID      uint16 `json:"product_id"`
	BcdDevice      uint16 `json:"bcd_device"`
	DeviceClass    uint8  `json:"device_class"`
	DeviceSubClass uint8  `json:"device_sub_class"`
	DeviceProtocol uint8  `json:"device_protocol"`
	ConfigValue    uint8  `json:"config_value"`
	NumConfigs     uint8  `json:"num_configs"`
	Manufacturer   string `json:"manufacturer"`
	Product        string `json:"product"`
	Serial         string `json:"serial"`
	SysPath        string `json:"sys_path"` // sysfs path
	DevPath        string `json:"dev_path"` // /dev/bus/usb path

	// Interfaces holds one entry per interface number at alternate setting 0.
	// These are the interfaces that get claimed when sharing the device.
	Interfaces []Interface `json:"interfaces"`

	// Endpoints holds every endpoint of the active configuration across all
	// alternate settings, keyed by full bEndpointAddress (direction bit
	// included). Endpoints that only exist in a non-zero alternate setting
	// are included, so the transfer type stays correct after SET_INTERFACE.
	Endpoints map[uint8]Endpoint `json:"endpoints"`
}

// Interface represents a USB interface at one alternate setting
type Interface struct {
	Number     uint8      `json:"number"`
	AltSetting uint8      `json:"alt_setting"`
	Class      uint8      `json:"class"`
	SubClass   uint8      `json:"sub_class"`
	Protocol   uint8      `json:"protocol"`
	Driver     string     `json:"driver"`
	Endpoints  []Endpoint `json:"endpoints"`
}

// Endpoint represents a USB endpoint
type Endpoint struct {
	Address       uint8  `json:"address"`       // bEndpointAddress (bit 7=direction, bits 3:0=number)
	TransferType  uint8  `json:"transfer_type"` // 0=control, 1=iso, 2=bulk, 3=interrupt
	MaxPacketSize uint16 `json:"max_packet_size"`
	Interval      uint8  `json:"interval"` // bInterval
}

// IsIn reports whether this is an IN (device-to-host) endpoint.
func (e Endpoint) IsIn() bool { return e.Address&0x80 != 0 }

// Number returns the endpoint number without the direction bit.
func (e Endpoint) Number() uint8 { return e.Address & 0x0F }

// USB transfer types (from bmAttributes)
const (
	TransferTypeControl     = 0
	TransferTypeIsochronous = 1
	TransferTypeBulk        = 2
	TransferTypeInterrupt   = 3
)

// DevID returns the USB/IP device ID (busnum << 16 | devnum)
func (d *Device) DevID() uint32 {
	return (d.BusNum << 16) | d.DevNum
}

// IsHub returns true if this is a USB hub
func (d *Device) IsHub() bool {
	return d.DeviceClass == 9
}

// DisplayName returns a human-readable device name
func (d *Device) DisplayName() string {
	if d.Product != "" {
		if d.Manufacturer != "" {
			return d.Manufacturer + " " + d.Product
		}
		return d.Product
	}
	return "Unknown USB Device"
}
