// +build linux
// Input device event monitor.
package main

import (
	"errors"
	"fmt"
	"netease_control_center/interfaces/log"
	"netease_control_center/nembd/evdev"
	"os"
	"strings"
)

const (
	usage       = "usage: evtest <device> [<type> <value>]"
	device_glob = "/dev/input/event*"
)

// Select a device from a list of accessible input devices.
func select_device() (*evdev.InputDevice, error) {
	devices, _ := evdev.ListInputDevices(device_glob)

	lines := make([]string, 0)
	max := 0
	if len(devices) > 0 {
		for i := range devices {
			dev := devices[i]
			str := fmt.Sprintf("%-3d %-20s %-35s %s", i, dev.Fn, dev.Name, dev.Phys)
			if len(str) > max {
				max = len(str)
			}
			lines = append(lines, str)
		}
		log.Printf(log.DebugLog, "%-3s %-20s %-35s %s\n", "ID", "Device", "Name", "Phys")
		log.Printf(log.DebugLog, strings.Repeat("-", max)+"\n")
		log.Printf(log.DebugLog, strings.Join(lines, "\n")+"\n")

		var choice int
		choice_max := len(lines) - 1

	ReadChoice:
		log.Printf(log.DebugLog, "Select device [0-%d]: ", choice_max)
		_, err := fmt.Scan(&choice)
		if err != nil || choice > choice_max || choice < 0 {
			goto ReadChoice
		}

		return devices[choice], nil
	}

	errmsg := fmt.Sprintf("no accessible input devices found by %s", device_glob)
	return nil, errors.New(errmsg)
}

func format_event(ev *evdev.InputEvent) string {
	var res, f, code_name string

	code := int(ev.Code)
	etype := int(ev.Type)

	switch ev.Type {
	case evdev.EV_SYN:
		if ev.Code == evdev.SYN_MT_REPORT {
			f = "time %d.%-8d +++++++++ %s ++++++++"
		} else {
			f = "time %d.%-8d --------- %s --------"
		}
		return fmt.Sprintf(f, ev.Time.Sec, ev.Time.Usec, evdev.SYN[code])
	case evdev.EV_KEY:
		val, haskey := evdev.KEY[code]
		if haskey {
			code_name = val
		} else {
			val, haskey := evdev.BTN[code]
			if haskey {
				code_name = val
			} else {
				code_name = "?"
			}
		}
	default:
		m, haskey := evdev.ByEventType[etype]
		if haskey {
			code_name = m[code]
		} else {
			code_name = "?"
		}
	}

	evfmt := "time %d.%-8d type %d (%s), code %-3d (%s), value %d"
	res = fmt.Sprintf(evfmt, ev.Time.Sec, ev.Time.Usec, etype,
		evdev.EV[int(ev.Type)], ev.Code, code_name, ev.Value)

	return res
}

func main() {
	var dev *evdev.InputDevice
	var events []evdev.InputEvent
	var err error

	log.Printf(log.DebugLog, "Key Inputevent test app by wangzijiao\n\n")

	switch len(os.Args) {
	case 1:
		dev, err = select_device()
		if err != nil {
			log.Println(log.ErrorLog, err.Error())
			os.Exit(1)
		}
	case 2:
		dev, err = evdev.Open(os.Args[1])
		if err != nil {
			log.Printf(log.DebugLog, "unable to open input device: %s\n", os.Args[1])
			os.Exit(1)
		}
	default:
		log.Printf(log.DebugLog, usage+"\n")
		os.Exit(1)
	}

	info := fmt.Sprintf("bus 0x%04x, vendor 0x%04x, product 0x%04x, version 0x%04x",
		dev.Bustype, dev.Vendor, dev.Product, dev.Version)

	repeat_info := dev.GetRepeatRate()

	log.Printf(log.DebugLog, "Evdev protocol version: %d\n", dev.EvdevVersion)
	log.Printf(log.DebugLog, "Device name: %s\n", dev.Name)
	log.Printf(log.DebugLog, "Device info: %s\n", info)
	log.Printf(log.DebugLog, "Repeat settings: repeat %d. delay %d\n", repeat_info[0], repeat_info[1])
	log.Printf(log.DebugLog, "Device capabilities:\n")

	// for ctype, codes := range dev.Capabilities {
	// 	fmt.Printf("  LocalId %s %d\n", ctype.Name, ctype.LocalId)
	// 	for i := range codes {
	// 		fmt.Printf("   Code %d %s\n", codes[i].Code, codes[i].Name)
	// 	}
	// }

	log.Printf(log.DebugLog, "Listening for events ...\n")

	for {
		events, err = dev.Read()
		for i := range events {
			str := format_event(&events[i])
			log.Println(log.ErrorLog, str)
		}
	}
}

// print('Device capabilities:')
// for type, codes in device.capabilities(verbose=True).items():
//     print('  LocalId {} {}:'.format(*type))
//     for i in codes:
//         if isinstance(i[1], AbsInfo):
//             print('    Code {:<4} {}:'.format(*i[0]))
//             print('      {}'.format(i[1]))
//         else:
//             print('    Code {:<4} {}'.format(*i))
//     print('')
//
//
