package evdev

import (
	"fmt"
	"syscall"
	"unsafe"
)

// EvType is EV_KEY, EV_SW, EV_LED, EV_SND, ...
type EvType uint16

// EvCode describes codes within a type (eg. KEY_A, KEY_B, ...)
type EvCode uint16

// EvProp describes device properties (eg. INPUT_PROP_ACCELEROMETER, INPUT_PROP_BUTTONPAD, ...)
type EvProp uint16

// StateMap describes the current state of codes within a type, as booleans.
type StateMap map[EvCode]bool

// InputEvent describes an event that is generated by an InputDevice
type InputEvent struct {
	Time  syscall.Timeval // time in seconds since epoch at which event occurred
	Type  EvType          // event type - one of ecodes.EV_*
	Code  EvCode          // event code related to the event type
	Value int32           // event value related to the event type
}

func (e *InputEvent) TypeName() string {
	return TypeName(e.Type)
}

func (e *InputEvent) CodeName() string {
	return CodeName(e.Type, e.Code)
}

func (e *InputEvent) String() string {
	return fmt.Sprintf(
		"type: 0x%02x [%s], code: 0x%02x [%s], value: %d",
		e.Type, e.TypeName(), e.Code, e.CodeName(), e.Value,
	)
}

var eventsize = int(unsafe.Sizeof(InputEvent{}))

// InputID ...
type InputID struct {
	BusType uint16
	Vendor  uint16
	Product uint16
	Version uint16
}

// AbsInfo describes details on ABS input types
type AbsInfo struct {
	Value      int32
	Minimum    int32
	Maximum    int32
	Fuzz       int32
	Flat       int32
	Resolution int32
}

// InputKeymapEntry is used to retrieve and modify keymap data
type InputKeymapEntry struct {
	Flags    uint8
	Len      uint8
	Index    uint16
	KeyCode  uint32
	ScanCode [32]uint8
}

// InputMask ...
type InputMask struct {
	Type      uint32
	CodesSize uint32
	CodesPtr  uint64
}

// UinputUserDevice is used when creating or cloning a device
type UinputUserDevice struct {
	Name       [uinputMaxNameSize]byte
	ID         InputID
	EffectsMax uint32
	Absmax     [absSize]int32
	Absmin     [absSize]int32
	Absfuzz    [absSize]int32
	Absflat    [absSize]int32
}
