/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
 * -*- coding: utf-8 -*-
 *
 * Copyright (C) 2023 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: sundagao <sundagao@kylinos.cn>
 */
#include "input-wayland-device.h"
#include "input-gsettings.h"
#include "input-device-function.h"
#include <QDBusConnection>

extern "C" {
#include "clib-syslog.h"
}
//外部全局变量，在input-device-funtion.cpp 定义
extern const DeviceFunctionMap deviceFuncMap;

InputWaylandDevice::InputWaylandDevice(QVariant deviceId, DeviceType type, QString deviceName, QObject *parent)
    : InputDevice(deviceId, type, deviceName, parent)
{
    m_interface = new QDBusInterface(QStringLiteral(KDE_KWIN_SERVICE),
                                     QStringLiteral(KDE_KWIN_OBJECT_PATH) + m_deviceId.toString(),
                                     QStringLiteral(KDE_KWIN_INTERFACE),
                                     QDBusConnection::sessionBus(), this);
    if (!m_interface->isValid()) {
        m_interface = new QDBusInterface(QStringLiteral(UKUI_KWIN_SERVICE),
                                         QStringLiteral(UKUI_KWIN_OBJECT_PATH) + m_deviceId.toString(),
                                         QStringLiteral(UKUI_KWIN_INTERFACE),
                                         QDBusConnection::sessionBus(), this);
    }

    initDeviceProperty();
}

void InputWaylandDevice::disable()
{
    setProperty("enabled", false);
}

void InputWaylandDevice::enable()
{
    setProperty("enabled", true);
}

void InputWaylandDevice::setEnable(QVariant value)
{
    setProperty("enabled", value);
}

void InputWaylandDevice::setLeftMode(QVariant value)
{
    setProperty("leftHanded", value);
}

void InputWaylandDevice::setNaturalScroll(QVariant value)
{
    setProperty("naturalScroll", value);
}

void InputWaylandDevice::setTapclick(QVariant value)
{
    setProperty("tapToClick", value);
}

void InputWaylandDevice::setTapDrag(QVariant value)
{
    setProperty("tapAndDrag", value);
}

void InputWaylandDevice::setDisableTyping(QVariant value)
{
    setProperty("disableWhileTyping", value);
}

void InputWaylandDevice::setAccelSpeed(QVariant value)
{
    setProperty("pointerAccelerationProfileAdaptive", value);
    setProperty("pointerAccelerationProfileFlat", !value.toBool());
}

void InputWaylandDevice::setAcceleration(QVariant value)
{
    double acceleration = value.toDouble();
    if (acceleration <= 1.0) {
        acceleration = 1.0;
    } else if (acceleration >= 8.0) {
        acceleration = 8.0;
    }
    acceleration = (acceleration - 1.0) * 2.0 / 7.0 - 1;
    setProperty("pointerAcceleration", acceleration);
}

void InputWaylandDevice::setMiddleButtonEmulation(QVariant value)
{
    setProperty("middleButtonEmulation", value);

}

void InputWaylandDevice::setScrolling(QVariant value)
{
    Q_UNUSED(value)
    bool edgeScroll = getGsettingsValue(KEY_VERT_EDGE_SCROLL).toBool();
    bool twoFingerScroll = getGsettingsValue(KEY_VERT_TWO_FINGER_SCROLL).toBool();
    USD_LOG(LOG_DEBUG,"setScrolling edgeScroll: %d twoFingerScroll: %d",edgeScroll, twoFingerScroll );
    setProperty("scrollEdge", edgeScroll);
    setProperty("scrollTwoFinger", twoFingerScroll);
}

void InputWaylandDevice::setDisableTpMoPresent(QVariant mousePresent)
{
    QVariant value = getGsettingsValue(KEY_TOUCHPAD_DISBLE_O_E_MOUSE);
    if (value.toBool() && mousePresent.toBool()) {
        setEnable(false);
    } else {
        setEnable(true);
    }
}

void InputWaylandDevice::setWheelSpeed(QVariant value)
{
    if (isMouse()) {
        setProperty("scrollFactor", value);
    }
}

QVariant InputWaylandDevice::getProductId()
{
    return getProperty("product");
}

void InputWaylandDevice::setProperty(const char *prop, QVariant value)
{
    if (m_interface->isValid()) {
        USD_LOG(LOG_DEBUG,"set prop %s",prop);
        m_interface->setProperty(prop, value);
    } else {
        USD_LOG(LOG_WARNING,"wayland device interface is not valid .");
    }
}

QVariant InputWaylandDevice::getProperty(const char *prop)
{
    return m_interface->property(prop);
}

void InputWaylandDevice::initDeviceProperty()
{
    //新增设备时初始化属性列表，根据gsetings 配置设置属性。
    QList<QString> keys = InputGsettings::instance()->getGsettingsKeys(m_type);
    if (keys.isEmpty()) {
        USD_LOG(LOG_DEBUG,"get gsettings keys is empty .");
        return;
    }
    for (const QString& key : keys) {
        QVariant value = getGsettingsValue(key);
        if (key == QStringLiteral(KEY_MOUSE_LOCATE_POINTER)) {
            InputDeviceFunction::setLocatePointer(value);
        } else {
            auto func = deviceFuncMap.value(key);
            if (func) {
                func(value,this);
            }
        }
    }
}
