/*
* Copyright (C) 2024, 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
* (at your option) 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 <https://www.gnu.org/licenses/>.
*
* Authors: zhouyong <zhouyong01@kylinos.cn>
*
*/
#ifndef UKUIAUDIOSINKMODEL_H
#define UKUIAUDIOSINKMODEL_H

#include <QAbstractListModel>
#include <QList>
#include <QString>
#include "../extra/DBusClient.h"

class UKUIAudioSinkModel : public QAbstractListModel
{
    Q_OBJECT

public:
    // 定义角色（暴露给 QML 的属性）
    enum SinkInfoRoles {
        ItemTypeRole = Qt::UserRole + 1,
        TitleRole,      // 标题内容（仅 Header 使用）
        CardNameRole,
        CardDescRole,
        PortNameRole,
        PortLabelRole,
        PriorityRole,
        DirectionRole,
        AvailableRole,
        PortEnabledRole,
        PortTypeRole,
        PortIconRole,
        IsActivePortRole,

        StreamNameRole,
        StreamIndexRole,
        StreamVolumeRole,
        StreamRole,
        StreamIconNameRole
    };
    Q_ENUM(SinkInfoRoles)

    // 定义数据项类型
    enum ItemType {
        Invaild = -1,
        HeaderOutput,    // 输出设备标题
        HeaderAppVolume, // 应用音量标题
        DeviceItem,      // 设备项
        StreamItem,      // 应用音量项
        EmptyDeviceItem, // 空设备项
        EmptyStreamItem  // 空应用音量项
    };
    Q_ENUM(ItemType)

    // 内部数据结构
    struct SinkInfo
    {
        ItemType itemType = Invaild; //列表item类型 ItemType
        QString title = ""; // 标题文案
        QString cardName;  // 声卡名称
        QString cardDesc;  // 声卡描述
        QString portName;  // 设备端口名称
        QString portLabel; // 设备端口描述
        uint32_t priority; // 端口优先级
        quint32 direction; // 端口方向 input or output
        quint32 available; // 端口可用状态
        bool enabled = true;  // 端口是否启用
        int32_t type;  // 端口的类型
        QString portIcon = ""; //  设备图标
        bool isActivePort = false;
        friend const ClientDeviceInfo& operator>>(const ClientDeviceInfo& argument, SinkInfo& info) {
            info.itemType = DeviceItem;
            info.cardName = argument.cardName;
            info.cardDesc = argument.cardDesc;
            info.portName = argument.portName;
            info.portLabel = argument.portLabel;
            info.priority = argument.priority;
            info.direction = argument.direction;
            info.available = argument.available;
            info.enabled = argument.enabled;
            info.type = argument.type;
            return argument;
        }

        friend const ClientDefaultDeviceInfo& operator>>(const ClientDefaultDeviceInfo& argument, SinkInfo& info) {
            info.itemType = DeviceItem;
            info.cardName = argument.cardName;
            info.cardDesc = argument.activePortDesc;
            info.portName = argument.activePortName;
            info.portLabel = tr("Multi Bluetooth Output");
            info.priority = -1;
            info.direction = 0;
            info.available = 0;
            info.enabled = 1;
            info.type = 0;
            return argument;
        }

        QString streamName;     // 流媒体名称
        quint32 streamIndex;    // 流媒体索引
        uint32_t streamVolume;  // 流媒体音量
        QString streamRole;     // 流媒体角色
        QString streamIconName; // 流媒体图标名称
        friend const StreamInfo& operator>>(const StreamInfo& argument, SinkInfo& info) {
            info.itemType = StreamItem;
            info.streamName = argument.name;
            info.streamIndex = argument.index;
            info.streamVolume = argument.volume;
            info.streamRole = argument.role;
            info.streamIconName = argument.iconName;
            return argument;
        }
    };

    static UKUIAudioSinkModel& getInstance();

    void initData();
    void initSlots();

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int,QByteArray> roleNames() const override;

    void addDeviceHeader();
    void addEmptyDevice();
    void addDevice(ClientDeviceInfo deviceInfo);
    void addDevice(ClientDefaultDeviceInfo deviceInfo);
    bool setDeviceActivePort(QString portName, QString cardName);
    void removeDevice(int index);
    void clearDevice();
    int getDeviceCount();
    int getEnabledDeviceCount();
    int getInsertDeviceIndex();

    void addStreamHeader();
    void addEmptyStream();
    void addStream(StreamInfo streamInfo);
    void removeStream(int index);
    void clearStream();
    int getStreamCount();
    int getStreamIndexByStreamIconName(QString iconName);

    void releaseModel();

signals:

private Q_SLOTS:

private:
    UKUIAudioSinkModel() = default;
    UKUIAudioSinkModel(const UKUIAudioSinkModel&) = delete;
    UKUIAudioSinkModel(UKUIAudioSinkModel&&) = delete;
    ~UKUIAudioSinkModel();

public:

private:
    QList<SinkInfo> m_sinkInfos;

};

#endif // UKUIAUDIOSINKMODEL_H
