#include "trayicon.h"
#include <QDBusInterface>
#include <QDBusReply>
#include <QProcess>

TrayIcon::TrayIcon(QQuickPaintedItem *parent)
    : QQuickPaintedItem(parent)
    , m_type(0)
{
    //sound
    if (QGSettings::isSchemaInstalled("org.ukui.quick-operation.panel")) {
        sound = new QGSettings("org.ukui.quick-operation.panel");
        connect(sound, &QGSettings::changed, this, &TrayIcon::getSoundValue);
    }
    //wifi
    getWifiValue();
    QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"),
                                         QString("/org/freedesktop/NetworkManager"),
                                         QString("org.freedesktop.NetworkManager"),
                                         QString("PropertiesChanged"), this, SLOT(getWifiValue()));

    //message
    QDBusConnection::sessionBus().connect(QString("org.ukui.Sidebar"),
                                          QString("/org/ukui/Sidebar/notification"),
                                          QString("org.ukui.Sidebar.notification"),
                                          QString("Sig_NotificationNumChange"), this, SLOT(getMessageValue()));

    //power
    initPowerDbusaddrest();
    initPowerValue();
    QDBusConnection::systemBus().connect(QString("org.freedesktop.UPower"), powerpath,
        "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(initPowerValue()));

    //bluetooth
    if (QGSettings::isSchemaInstalled("org.ukui.bluetooth")) {
        bluetoothSetting = new QGSettings("org.ukui.bluetooth");
        connect(bluetoothSetting, &QGSettings::changed, this, &TrayIcon::getBluetoothSwitch);
    }
    //time
    if (QGSettings::isSchemaInstalled("org.ukui.control-center.panel.plugins")) {
        timeSetting = new QGSettings("org.ukui.control-center.panel.plugins");
        connect(timeSetting, &QGSettings::changed, this, &TrayIcon::getTimeDateState);
    }
    getTimeDateState();
}

QIcon TrayIcon::icon()
{
    return m_icon;
}

QString TrayIcon::source()
{
    return m_source;
}

void TrayIcon::setSource(const QString &source)
{
    m_icon = QIcon::fromTheme(source, QIcon(source));
    m_source = source;
    emit sourceChanged();
    update();
}

int TrayIcon::type()
{
    return m_type;
}

void TrayIcon::setType(const int &type)
{
    m_type = type;
    switch (m_type) {
    case Sound:
        getSoundValue();
        break;
    case Power: {
        initPowerValue();
        break;
    }
    case Message: {
        getMessageValue();
        break;
    }
    case Wifi: {
        getWifiValue();
        break;
    }
    case Bluetooth: {
        getBluetoothSwitch();
        break;
    }
    default:
        break;
    }
    update();
    emit typeChanged();
}

void TrayIcon::paint(QPainter *painter)
{
    m_icon.paint(painter, boundingRect().toRect());
}

QString TrayIcon::timeformat()
{
    return m_timeformat;
}

void TrayIcon::settimeformat(const QString &timeformat)
{
    if (m_timeformat != timeformat) {
        m_timeformat = timeformat;
        emit timeformatChanged();
    }
}

QString TrayIcon::dateformat()
{
    return m_dateformat;
}

void TrayIcon::setdateformat(const QString &dateformat)
{
    if (m_dateformat != dateformat) {
        m_dateformat = dateformat;
        emit dateformatChanged();
    }
}

void TrayIcon::getSoundValue()
{
    if (QGSettings::isSchemaInstalled("org.ukui.quick-operation.panel")) {
        int soundValue = 0;
        if (sound->keys().contains("soundstate")) {
            bool soundState = sound->get("soundstate").toBool();
            if (soundState) {
                soundValue = 0;
            } else {
                soundValue = sound->get("volumesize").toInt();
            }
            setVolumeIcon(soundValue);
        } else {
            if (sound->keys().contains("volumesize")) {
                soundValue = sound->get("volumesize").toInt();
                setVolumeIcon(soundValue);
            }
        }
    }
}

void TrayIcon::initPowerDbusaddrest()
{
    QStringList users;
    QDBusInterface m_interface1("org.freedesktop.UPower",
                                "/org/freedesktop/UPower",
                                "org.freedesktop.UPower",
                                QDBusConnection::systemBus() );
    if (!m_interface1.isValid()) {
        qDebug() << "dbus接口初始化失败";
        return;
    }
    QDBusReply<QList<QDBusObjectPath>> obj_reply = m_interface1.call("EnumerateDevices");
    if (obj_reply.isValid()) {
        for (QDBusObjectPath op : obj_reply.value()) {
             users << op.path();
        }
        if (users.size() == 1 || users.size() == 0) {
            return;
        }
        powerpath = users.at(1);
     }
}

void TrayIcon::getMessageValue()
{
    QDBusInterface interfaceMess("org.ukui.Sidebar",
                                 "/org/ukui/Sidebar/notification",
                                 "org.ukui.Sidebar.notification",
                                 QDBusConnection::sessionBus());
    QDBusReply<int> result = interfaceMess.call("getNotificationNum");
    if (result == 0) {
        setMessageIcon(false);
    } else {
        setMessageIcon(true);
    }
}

void TrayIcon::initPowerValue()
{
    QDBusInterface m_interface( "org.freedesktop.UPower",
                                powerpath,
                                "org.freedesktop.DBus.Properties",
                                QDBusConnection::systemBus() );
    if (!m_interface.isValid()) {
        qDebug() << "dbus接口初始化失败";
    }
    QDBusReply<QVariant> obj_reply = m_interface.call("Get","org.freedesktop.UPower.Device","Percentage");

    QDBusReply<QVariant> obj_state = m_interface.call("Get","org.freedesktop.UPower.Device","State");

    if (obj_reply.isValid() && obj_state.isValid()) {
        if (obj_state.value().toUInt() == 2 || obj_state.value().toUInt() == 3) {
            setPowerIcon(obj_reply.value().toInt());
        } else {
            setPowerChargeIcon(obj_reply.value().toInt());
        }
    }
    emit powerValueChanged();
}

void TrayIcon::getBluetoothSwitch()
{
    QProcess p1;
    p1.start("rfkill list");
    p1.waitForFinished(3000);
    QString bluetoothState = p1.readAll();
    if (bluetoothState.contains("Bluetooth")) {
        QProcess p;
        p.start("hciconfig");
        p.waitForFinished(3000);
        QString bluetoothInfo = p.readAll();
        if (bluetoothInfo.contains("DOWN")) {
            setBluetoothIcon(false);
        }
        if (bluetoothInfo.contains("UP")) {
            setBluetoothIcon(true);
        }
    } else {
        setBluetoothIcon(false);
    }
}

void TrayIcon::getTimeDateState()
{
    if (QGSettings::isSchemaInstalled("org.ukui.control-center.panel.plugins")) {
        if (timeSetting->keys().contains("hoursystem")) {
            QString timeState = timeSetting->get("hoursystem").toString();
            settimeformat(timeState);
        }
        if (timeSetting->keys().contains("hoursystem")) {
            QString dateState = timeSetting->get("date").toString();
            setdateformat(dateState);
        }
    }
}


void TrayIcon::getWifiValue()
{
    netconnectType = 0;

    QDBusInterface interface( "org.freedesktop.NetworkManager",
                              "/org/freedesktop/NetworkManager",
                              "org.freedesktop.DBus.Properties",
                              QDBusConnection::systemBus());

    //获取已经连接了那些网络，及这些网络对应的网络类型(ethernet or wifi)
    QDBusMessage result = interface.call("Get", "org.freedesktop.NetworkManager", "ActiveConnections");
    QList<QVariant> outArgs = result.arguments();
    QVariant first = outArgs.at(0);
    QDBusVariant dbvFirst = first.value<QDBusVariant>();
    QVariant vFirst = dbvFirst.variant();
    QDBusArgument dbusArgs = vFirst.value<QDBusArgument>();
    QDBusArgument dbusArgshelp = vFirst.value<QDBusArgument>();

    QDBusObjectPath objPath;
    dbusArgs.beginArray();

    while (!dbusArgs.atEnd()) {
        dbusArgs >> objPath;

        QDBusInterface interfacePath( "org.freedesktop.NetworkManager",
                                  objPath.path(),
                                  "org.freedesktop.DBus.Properties",
                                  QDBusConnection::systemBus() );

        QDBusReply<QVariant> replyConnectType = interfacePath.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Type");
        QDBusReply<QVariant> replyConnectivity = interface.call("Get", "org.freedesktop.NetworkManager", "Connectivity");
        int connectivityState = replyConnectivity.value().toInt();
//        qDebug() << "connect type" <<replyConnectType.value().toString();

        if (replyConnectType.value().toString() == "802-3-ethernet") {
            netconnectType = 1;
            if (connectivityState == 4) {
                setNetIcon(-1, true); //有网
                return;
            } else {
                setNetIcon(-2, true); //无网
            }
        }

        if (replyConnectType.value().toString() == "802-11-wireless") {
            netconnectType = 2;
            QDBusReply<QVariant> replyConnectivity = interface.call("Get", "org.freedesktop.NetworkManager", "Connectivity");
            if (connectivityState == 4) {
                QDBusMessage resultSpecificObject = interfacePath.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "SpecificObject");
                QList<QVariant> outArgsSpecificObject = resultSpecificObject.arguments();
                QVariant firstSpecificObject = outArgsSpecificObject.at(0);
                QDBusVariant dbvFirstSpecificObject = firstSpecificObject.value<QDBusVariant>();
                QVariant vFirstSpecificObject = dbvFirstSpecificObject.variant();
                QDBusObjectPath objPathSpecificObject = vFirstSpecificObject.value<QDBusObjectPath>();

                QDBusInterface interfaceAP( "org.freedesktop.NetworkManager",
                                          objPathSpecificObject.path(),
                                          "org.freedesktop.DBus.Properties",
                                          QDBusConnection::systemBus() );

                QDBusReply<QVariant> replyStrength = interfaceAP.call("Get", "org.freedesktop.NetworkManager.AccessPoint", "Strength"); //signal

                QByteArray sesultStrength = replyStrength.value().toByteArray();
                int wifiSignal = sesultStrength[0] & 0x000000FF;
                wifiSignal |= ((sesultStrength[1] << 8) & 0x0000FF00);
                wifiSignal |= ((sesultStrength[2] << 16) & 0x00FF0000);
                wifiSignal |= ((sesultStrength[3] << 24) & 0xFF000000);
                setNetIcon(wifiSignal, true);
            } else {
                setNetIcon(-2, true);
            }
        }
    }
    if (netconnectType == 0) {
        setNetIcon(-1, false);
    }
    emit wifiStateChanged();
}

void TrayIcon::setVolumeIcon(int value)
{
    if (type() == 0) {
        if (value <= 0) {
            setSource("audio-volume-muted-symbolic");
        } else if (value > 0 && value <= 33) {
            setSource("audio-volume-low-symbolic");
        } else if (value > 33 && value <= 66) {
            setSource("audio-volume-medium-symbolic");
        } else {
            setSource("audio-volume-high-symbolic");
        }
    }
}
void TrayIcon::setPowerIcon(int value)
{
    if (type() == 1) {
        if (value == 100) {
            setSource("battery-full-symbolic");
        } else {
            int val;
            setSource("battery-level-50-symbolic");
            for(int i = 0; i <= 100; i += 10) {
                if (value <= i) {
                    val = i;
                    break;
                }
            }
            QString valueString = QString("battery-level-%1-symbolic").arg(val);
            setSource(valueString);
        }
    }
}
void TrayIcon::setPowerChargeIcon(int value)
{
    if (type() == 1) {
        if (value == 0) {
            setSource("battery-empty-charging-symbolic");
        } else if (value == 100) {
            setSource("battery-level-100-charging-symbolic");
        } else {
            int val;
            for(int i = 10; i <= 100; i += 10) {
                if (value <= i) {
                    val = i;
                    break;
                }
            }
            QString valueString = QString("battery-level-%1-charging-symbolic").arg(val);
            setSource(valueString);
        }
    }
}

void TrayIcon::setMessageIcon(bool value)
{
    if(type() == 2) {
        if (value) {
            setSource("kylin-tool-box-null");
        } else {
            setSource("kylin-tool-box");
        }
    }
}

void TrayIcon::setNetIcon(int value, bool state)
{
    if (type() == 3) {
        if (state) {
            if (netconnectType == 1) {
//                qDebug() << "wire" <<"value:" <<value<<"state:" <<state;
                if (value == -1) {
                    setSource("network-wired-symbolic");
                } else {
                    setSource("network-error-symbolic");
                }
            }
            if (netconnectType == 2) {
                if (value < 0) {
//                    qDebug() << "wifi no net" <<"value:" <<value<<"state:" <<state;
                    setSource("network-wired-symbolic");
                } else {
                    //无线网络状态改变
//                    qDebug() << "wifi" <<"value:" <<value<<"state:" <<state;
                    if (value >= 75) {
                        setSource("network-wireless-signal-excellent-symbolic");
                    } else if (value >= 55 && value < 75) {
                        setSource("network-wireless-signal-good-symbolic");
                    } else if (value >= 35 && value < 55) {
                        setSource("network-wireless-signal-ok-symbolic");
                    } else if(value >= 15 && value < 35) {
                        setSource("network-wireless-signal-weak-symbolic");
                    } else {
                        setSource("network-wired-disconnected-symbolic");//network-cellular-signal-none-symbolic
                    }
                }
            }
        } else {
//            qDebug() << "no net" <<"value:" <<value<<"state:";
            setSource("network-wired-disconnected-symbolic");
        }
    }
}

void TrayIcon::setBluetoothIcon(bool state)
{
    if (type() == 4) {
        if (state) {
            setSource("ukui-bluetooth-on-symbolic");
        } else {
            setSource("ukui-bluetooth-off-symbolic");
        }
    }
}
