// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

package inputdevices

import (
	"errors"
	"io/ioutil"
	"os"
	"strings"

	"github.com/godbus/dbus"
	configManager "github.com/linuxdeepin/go-dbus-factory/org.desktopspec.ConfigManager"
	"github.com/linuxdeepin/go-lib/dbusutil"
)

const(
    touchpadSwitchFile = "/proc/uos/touchpad_switch"
    touchpadExpandSwitchFile = "/proc/uos/touchpad_expand_switch"
    touchpadDBusPath = "/com/deepin/system/InputDevices/Touchpad"
    touchpadDBusInterface = "com.deepin.system.InputDevices.Touchpad"
)

type Touchpad struct {
	service       *dbusutil.Service
	Enable        bool
	IsExist       bool
	ExpandIsExist bool
	ExpandEnable  bool
}

func newTouchpad(service *dbusutil.Service) *Touchpad {
	return &Touchpad {
		service: service,
	}
}

func (t *Touchpad) SetTouchpadEnable(enabled bool) *dbus.Error {
	err := t.setTouchpadEnable(enabled)
	if err != nil {
		return dbusutil.ToError(err)
	}
	if err := touchpadExpandExist(touchpadExpandSwitchFile); err == nil {
		v, err := getDsgConf(_dsettingsToupadExpandEnabled)
		if err != nil {
			logger.Warning(err)
		}
		err = t.setTouchpadExpandEnable(enabled && v, false)
		if err != nil {
			logger.Warning(err)
		}
	}
	return dbusutil.ToError(err)
}

func (t *Touchpad) SetTouchpadExpandEnable(enabled bool) *dbus.Error {
	err := t.setTouchpadExpandEnable(enabled, true)
	return dbusutil.ToError(err)
}

func (t *Touchpad) setTouchpadEnable(enabled bool) error {
	logger.Debug("setTouchpadEnable enabled : ", enabled)
	if t.setPropEnable(enabled) {
		err := setDsgConf(_dsettingsTouchpadEnabledKey, enabled)
		if err != nil{
			logger.Warning(err)
			return err
		}
	}
	arg := "enable"
	if !enabled {
		arg = "disable"
	}
	err := ioutil.WriteFile(touchpadSwitchFile, []byte(arg), 0644)
	if err != nil{
		logger.Warning(" ioutil.WriteFile err : ", err)
		return err
	}
	return nil
}

func setDsgConf(dsg string, enable bool) error {
	sysBus, err := dbus.SystemBus()
	if err != nil {
		return err
	}
	ds := configManager.NewConfigManager(sysBus)
	confPath, err := ds.AcquireManager(0, _dsettingsAppID, _dsettingsInputdevicesName, "")
	if err != nil {
		return err
	}
	dsManager, err := configManager.NewManager(sysBus, confPath)
	if err != nil {
		return err
	}
	err = dsManager.SetValue(0, dsg, dbus.MakeVariant(enable))
	if err != nil {
		return err
	}
	return nil
}

func getDsgConf(dsg string) (bool, error) {
	sysBus, err := dbus.SystemBus()
	if err != nil {
		return false, err
	}
	ds := configManager.NewConfigManager(sysBus)
	confPath, err := ds.AcquireManager(0, _dsettingsAppID, _dsettingsInputdevicesName, "")
	if err != nil {
		return false, err
	}
	dsManager, err := configManager.NewManager(sysBus, confPath)
	if err != nil {
		return false, err
	}

	v, err := dsManager.Value(0, dsg)
	if err != nil {
		return false, err
	}
	return v.Value().(bool), nil
}

func touchpadEnable(filePath string) (bool, error) {
	err := touchpadExist(filePath)
	if err != nil {
		return false, err
	}
	content, err := ioutil.ReadFile(touchpadSwitchFile)
	if err != nil {
		return false, err
	}
	return strings.Contains(string(content), "enable"), nil
}

func touchpadExist(filePath string) error {
	if filePath != touchpadSwitchFile {
		return errors.New("filePath is inValid")
	}
	_, err := os.Stat(touchpadSwitchFile)
	if err != nil {
		logger.Warning(err)
		return err
	}
	return nil
}

func (t *Touchpad) setTouchpadExpandEnable(enabled bool, updateDsg bool) error {
	logger.Debug("setTouchpadExpandEnable enabled : ", enabled)
	if t.setPropExpandEnable(enabled) && updateDsg {
		setDsgConf(_dsettingsToupadExpandEnabled, enabled)
	}
	arg := "enable"
	if !enabled {
		arg = "disable"
	}
	err := ioutil.WriteFile(touchpadExpandSwitchFile, []byte(arg), 0644)
	if err != nil{
		logger.Warning(" ioutil.WriteFile err : ", err)
		return err
	}
	return nil
}

func touchpadExpandEnable(filePath string) (bool, error) {
	err := touchpadExpandExist(filePath)
	if err != nil {
		return false, err
	}
	content, err := ioutil.ReadFile(touchpadExpandSwitchFile)
	if err != nil {
		return false, err
	}
	return strings.Contains(string(content), "enable"), nil
}

func touchpadExpandExist(filePath string) error {
	if filePath != touchpadExpandSwitchFile {
		return errors.New("filePath is inValid")
	}
	_, err := os.Stat(touchpadExpandSwitchFile)
	if err != nil {
		logger.Warning(err)
		return err
	}
	return nil
}

func (t *Touchpad) GetInterfaceName() string {
	return touchpadDBusInterface
}

func (t *Touchpad) export(path dbus.ObjectPath) error {
	return t.service.Export(path, t)
}

func (t *Touchpad) stopExport() error {
	return t.service.StopExport(t)
}
