package adau1761

import (
	"netease_control_center/globals"
	"netease_control_center/interfaces/log"
	"netease_control_center/nembd/base"
	"os"
	"sync"
	"syscall"
	"unsafe"
)

const (
	MAGIC_NUM      = 'A'
	CMD_SET_VOLUME = 0
	CMD_GET_VOLUME = 1
	CMD_MUTE       = 2
	CMD_SET_EQ     = 7
	devpath        = "/dev/adau1761"
	MAX_VOLUME     = globals.MaxVolume
)

var (
	cur_Vol     int = -1
	setVolLock  sync.Mutex
	VolChangeCb func(vol int)
)

func init() {
	globals.Seteq = setEq
}

func Mute(isMute bool) error {
	fd, err := os.Open(devpath)
	if err != nil {
		return err
	}
	defer fd.Close()

	var muteval int
	if isMute {
		muteval = 1
	} else {
		muteval = 0
	}

	cmd := base.IOW(MAGIC_NUM, CMD_MUTE, 4)

	_, _, err2 := syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), uintptr(cmd), uintptr(muteval))

	if err2 != 0 {
		return syscall.Errno(err2)
	}

	return nil
}

func MustGetVol() int {
	vol, _ := GetVol()
	return vol
}

func GetVol() (int, error) {
	if cur_Vol >= 0 {
		return cur_Vol, nil
	}
	fd, err := os.Open(devpath)
	if err != nil {
		return 0, err
	}
	defer fd.Close()
	cmd := base.IOR(MAGIC_NUM, CMD_GET_VOLUME, 4)
	var vol int
	_, _, err2 := syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), uintptr(cmd), uintptr(unsafe.Pointer(&vol)))

	if err2 != 0 {
		return 0, syscall.Errno(err2)
	}

	return int(vol), nil
}

func SetVol(vol int) (int, error) {
	defer func() {
		globals.CurVboxVolSt.VolumePer = uint8(globals.GetPerByVol(vol))
		if VolChangeCb != nil {
			VolChangeCb(vol)
		}
		setVolLock.Unlock()
	}()

	setVolLock.Lock()

	fd, err := os.Open(devpath)
	if err != nil {
		return 0, err
	}
	defer fd.Close()
	switch {
	case vol > MAX_VOLUME:
		vol = MAX_VOLUME
	case vol < 0:
		vol = 0
	}

	cmd := base.IOW(MAGIC_NUM, CMD_SET_VOLUME, 4)
	_, _, err2 := syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), uintptr(cmd), uintptr(vol))

	if err2 != 0 {
		return 0, syscall.Errno(err2)
	} else {
		cur_Vol = vol
		return vol, nil
	}
}

func IncVol(step int) (int, error) {
	cur, err := GetVol()
	if err != nil {
		return 0, err
	}

	return SetVol(step + cur)
}

func DecVol(step int) (int, error) {
	cur, err := GetVol()
	if err != nil {
		return 0, err
	}

	return SetVol(cur - step)
}

func setEq(eq int) (err error) {
	return
	fd, err := os.Open(devpath)
	if err != nil {
		return err
	}
	defer fd.Close()
	cmd := base.IOW(MAGIC_NUM, CMD_SET_EQ, 4)
	_, _, err = syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), uintptr(cmd), uintptr(eq))
	log.Println(log.DebugLog, "Set eq:", eq)
	return
}
