/*
    SPDX-FileCopyrightText: 2021-2026 Devin Lin <devin@kde.org>

    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/

#pragma once

#include "plasmanm_cellular_export.h"

#include <QList>
#include <QObject>
#include <QString>
#include <QtQmlIntegration>

#include <NetworkManagerQt/ModemDevice>

#include <ModemManagerQt/GenericTypes>
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>

class CellularModem;

class PLASMANM_CELLULAR_EXPORT CellularAvailableNetwork : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(bool isCurrentlyUsed READ isCurrentlyUsed NOTIFY isCurrentlyUsedChanged)
    Q_PROPERTY(QString operatorLong READ operatorLong NOTIFY operatorLongChanged)
    Q_PROPERTY(QString operatorShort READ operatorShort NOTIFY operatorShortChanged)
    Q_PROPERTY(QString operatorCode READ operatorCode NOTIFY operatorCodeChanged)
    Q_PROPERTY(QString accessTechnology READ accessTechnology NOTIFY accessTechnologyChanged)

public:
    CellularAvailableNetwork(QObject *parent = nullptr,
                             ModemManager::Modem3gpp::Ptr mm3gppDevice = nullptr,
                             bool isCurrentlyUsed = false,
                             QString operatorLong = QString(),
                             QString operatorShort = QString(),
                             QString operatorCode = QString(),
                             MMModemAccessTechnology accessTechnology = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);

    bool isCurrentlyUsed();
    QString operatorLong();
    QString operatorShort();
    QString operatorCode();
    QString accessTechnology();

    Q_INVOKABLE void registerToNetwork();

Q_SIGNALS:
    void isCurrentlyUsedChanged();
    void operatorLongChanged();
    void operatorShortChanged();
    void operatorCodeChanged();
    void accessTechnologyChanged();

private:
    bool m_isCurrentlyUsed;
    QString m_operatorLong;
    QString m_operatorShort;
    QString m_operatorCode;
    QString m_accessTechnology;
    ModemManager::Modem3gpp::Ptr m_mm3gppDevice;
};

class PLASMANM_CELLULAR_EXPORT CellularModemDetails : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    // modemmanager device
    Q_PROPERTY(QStringList accessTechnologies READ accessTechnologies NOTIFY accessTechnologiesChanged) // currently used tech
    Q_PROPERTY(QString device READ device NOTIFY deviceChanged)
    Q_PROPERTY(QString deviceIdentifier READ deviceIdentifier NOTIFY deviceIdentifierChanged)
    Q_PROPERTY(QStringList drivers READ drivers NOTIFY driversChanged)
    Q_PROPERTY(QString equipmentIdentifier READ equipmentIdentifier NOTIFY equipmentIdentifierChanged)
    // TODO add bands
    Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY isEnabledChanged)
    Q_PROPERTY(QString manufacturer READ manufacturer NOTIFY manufacturerChanged)
    Q_PROPERTY(QString model READ model NOTIFY modelChanged)
    Q_PROPERTY(QStringList ownNumbers READ ownNumbers NOTIFY ownNumbersChanged)
    Q_PROPERTY(QString plugin READ plugin NOTIFY pluginChanged)
    Q_PROPERTY(QString powerState READ powerState NOTIFY powerStateChanged)
    Q_PROPERTY(QString revision READ revision NOTIFY revisionChanged)
    Q_PROPERTY(uint signalQuality READ signalQuality NOTIFY signalQualityChanged)
    Q_PROPERTY(QString simPath READ simPath NOTIFY simPathChanged)
    Q_PROPERTY(QString state READ state NOTIFY stateChanged)
    Q_PROPERTY(QString stateFailedReason READ stateFailedReason NOTIFY stateFailedReasonChanged)
    // modemmanager 3gpp device
    Q_PROPERTY(QString operatorCode READ operatorCode NOTIFY operatorCodeChanged)
    Q_PROPERTY(QString operatorName READ operatorName NOTIFY operatorNameChanged)
    Q_PROPERTY(QString registrationState READ registrationState NOTIFY registrationStateChanged)
    Q_PROPERTY(QList<CellularAvailableNetwork *> networks READ networks NOTIFY networksChanged)
    Q_PROPERTY(bool isScanningNetworks READ isScanningNetworks NOTIFY isScanningNetworksChanged)
    // networkmanager device
    Q_PROPERTY(QString firmwareVersion READ firmwareVersion NOTIFY firmwareVersionChanged)
    Q_PROPERTY(QString interfaceName READ interfaceName NOTIFY interfaceNameChanged)
    Q_PROPERTY(QString metered READ metered NOTIFY meteredChanged)

public:
    CellularModemDetails(QObject *parent = nullptr, CellularModem *modem = nullptr);

    QStringList accessTechnologies();
    QString device();
    QString deviceIdentifier();
    QStringList drivers();
    QString equipmentIdentifier();
    bool isEnabled();
    QString manufacturer();
    QString model();
    QStringList ownNumbers();
    QString plugin();
    QString powerState();
    QString revision();
    uint signalQuality();
    QString simPath();
    QString state();
    QString stateFailedReason();

    QString operatorCode();
    QString operatorName();
    QString registrationState();

    Q_INVOKABLE void scanNetworks();
    QList<CellularAvailableNetwork *> networks();
    bool isScanningNetworks();

    QString firmwareVersion();
    QString interfaceName();
    QString metered();

Q_SIGNALS:
    void accessTechnologiesChanged();
    void deviceChanged();
    void deviceIdentifierChanged();
    void driversChanged();
    void equipmentIdentifierChanged();
    void isEnabledChanged();
    void manufacturerChanged();
    void modelChanged();
    void ownNumbersChanged();
    void pluginChanged();
    void powerStateChanged();
    void revisionChanged();
    void signalQualityChanged();
    void simPathChanged();
    void stateChanged();
    void stateFailedReasonChanged();
    void operatorCodeChanged();
    void operatorNameChanged();
    void registrationStateChanged();
    void networksChanged();
    void isScanningNetworksChanged();
    void firmwareVersionChanged();
    void interfaceNameChanged();
    void meteredChanged();
    void errorOccurred(const QString &message);

private:
    void updateNMSignals();
    void scanNetworksFinished(QDBusPendingCallWatcher *call);

    CellularModem *m_modem;
    QDBusPendingCallWatcher *m_scanNetworkWatcher;
    bool m_isScanningNetworks;
    QList<CellularAvailableNetwork *> m_cachedScannedNetworks;
};
