/*
 * Copyright (C) 2019 Tianjin KYLIN Information Technology 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, 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 <http://www.gnu.org/licenses/&gt;.
 *
 */
#ifndef UKMEDIAMAINWIDGET_H
#define UKMEDIAMAINWIDGET_H

#include <QWidget>
#include <QMainWindow>
#include <QPushButton>
#include "ukmedia_application_volume_widget.h"
#include "ukmedia_osd_display_widget.h"
#include "ukmedia_custom_sound.h"
#include "ukui_media_set_headset_widget.h"
#include "ukmedia_volume_control.h"
#include "ukui_list_widget_item.h"
#include "ukmedia_system_volume_widget.h"
#include "windowmanager/windowmanager.h"
#include "ukuistylehelper/ukuistylehelper.h"

#include <QTabWidget>
#include <QMenu>
#include <QCheckBox>
#include <QWidgetAction>
#include <QMessageBox>
#include <QFrame>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusObjectPath>
#include <QDBusReply>
#include <QSystemTrayIcon>
#include <QProcess>
#include <QGSettings>
#include <QMediaPlayer>
#include <QTimer>
#include <QTime>
#include <QFrame>
#include <QDesktopWidget>
#include <QMap>
#include <QLayout>
#include <QDBusInterface>
#include <QDBusUnixFileDescriptor>

extern "C" {
#include <gio/gio.h>
#include <dconf/dconf.h>
#include <canberra.h>
#include <glib/gmain.h>
}
#include <alsa/asoundlib.h>
#include <set>

#define HAVE_EXT_DEVICE_RESTORE_API PA_CHECK_VERSION(0,99,0)

#define UKUI_THEME_SETTING "org.ukui.style"
#define UKUI_TRANSPARENCY_SETTING "org.ukui.control-center.personalise"
#define UKUI_THEME_NAME "style-name" //主题名称
#define UKUI_THEME_WHITE "ukui-default" //默认主题
#define UKUI_THEME_BLACK "ukui-dark" //深色主题
#define PORT_NUM 5

//为平板模式提供设置音量值
#define UKUI_VOLUME_BRIGHTNESS_GSETTING_ID "org.ukui.quick-operation.panel"
#define UKUI_VOLUME_KEY "volumesize" //音量大小
#define UKUI_VOLUME_STATE "soundstate" //音量状态


#define KEY_SOUNDS_SCHEMA   "org.ukui.sound"
#define TIMER_TIMEOUT   (2*1000)

#define PA_VOLUME_NORMAL 65536.0
#define UKMEDIA_VOLUME_NORMAL 100.0
#define DBUS_NAME       "org.ukui.SettingsDaemon"
#define DBUS_PATH       "/org/ukui/SettingsDaemon/wayland"
#define DBUS_INTERFACE  "org.ukui.SettingsDaemon.wayland"

#define DNS_NOISE_REDUCTION "dns-noise-reduction"
#define VOLUME_INCREASE "volume-increase"
//第一次运行时初始化音量
#define UKUI_AUDIO_SCHEMA "org.ukui.audio"  //定制音量
#define FIRST_RUN "first-run" //是否第一次运行
#define HEADPHONE_OUTPUT_VOLUME "headphone-output-volume"
#define PLUGIN_INIT_VOLUME "plugin-init-volume"
#define INTEL_MIC "intel-mic"
#define REAR_MIC "rear-mic"
#define HEADSET_MIC "headset-mic"
#define LINEIN "linein"
#define SPEAKER "speaker"
#define HDMI "hdmi"
#define BLUEZ "bluez"
#define HEADPHONE "headphone"
#define HEADPHONES_1 "headphones-1"
#define HEADPHONES_2 "headphones-2"

#define HEADPHONE_VOLUME 11141
#define HDMI_VOLUME 65536
#define OUTPUT_VOLUME 43909
#define MIC_VOLUME 65536

const QByteArray TRANSPARENCY_GSETTINGS = "org.ukui.control-center.personalise";

static const gchar *iconNameOutputs[] = {
        "audio-volume-muted-symbolic",
        "audio-volume-low-symbolic",
        "audio-volume-medium-symbolic",
        "audio-volume-high-symbolic",
        NULL
};

static const gchar *iconNameInputs[] = {
        "microphone-sensitivity-muted-symbolic",
        "microphone-sensitivity-low-symbolic",
        "microphone-sensitivity-medium-symbolic",
        "microphone-sensitivity-high-symbolic",
        NULL
};

typedef struct {
        const pa_card_port_info *headphones;
        const pa_card_port_info *headsetmic;
        const pa_card_port_info *headphonemic;
        const pa_card_port_info *internalmic;
        const pa_card_port_info *internalspk;
} headsetPorts;

class UkmediaMainWidget : public QMainWindow
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.ukui.media")//ukui-media的dbus接口
public:
    explicit UkmediaMainWidget(QMainWindow *parent = nullptr);
    ~UkmediaMainWidget();

    void UkmediaDbusRegister(); //注册Dbus信号
    void initSystemTrayIcon(); //初始化系统托盘
    void initWidget(); //初始化弹出框
    void initVolumeLed();//初始化静音灯
    void initGsettings(); //初始化gsetting
    void updateOutputListWidgetFont();
    void initAlertSound();
    void initSystemVolume(); //初始化系统音量
    void myLine(QFrame *volumeLine,QFrame *volumeSettingLine);//添加分隔线
    void dealSlot(); //处理槽函数
    void systemTrayMenuInit(); //初始化右键菜单

    void initOutputListWidgetItem();//初始化默认选择的输出设备
    void initInputListWidgetItem();//初始化默认选择的输输入设备

    QList<char *> listExistsPath(); //动态gseting列出存在的路径
    QString findFreePath(); //动态gsetting找到下一个为空的路径
    void addValue(QString name,QString filename); //动态gsetting添加键值
    QPixmap drawLightColoredPixmap(const QPixmap &source); //绘制高亮颜色图标
    QPixmap drawDarkColoredPixmap(const QPixmap &source); //绘制深色颜色图标
    void themeChangeIcons(); //主题更改时更新图标颜色

    void advancedWidgetShow(); //显示advance widget
    void hideWindow(); //隐藏窗口
    void inputVolumeDarkThemeImage(int value,bool status); //绘制input button颜色
    void outputVolumeDarkThemeImage(int value,bool status); //绘制output button颜色
    void drawImagColorFromTheme(UkuiButtonDrawSvg *button, QString iconStr); //绘制iamge颜色
    void setVolumeSettingValue(int value); //设置volume gsetting的值
    void setVolumeSettingMute(bool state); //设置volume gsetting的静音

    int valueToPaVolume(int value); //滑动条值转换成音量
    int paVolumeToValue(int value); //音量值转换成滑动条值
    QString outputVolumeToIconStr(bool status,int volume);

    QString getAppName(QString desktopfp); //从desktop中获取应用名称
    QString getAppIcon(QString desktopfp); //从desktop中获取应用图标
    QString appNameToIconName(const gchar *appName,const gchar *appIconName);

    void initSubApplicationWidget(QString str); //子应用窗口布局

    static gboolean verifyAlsaCard (int cardindex,gboolean *headsetmic,gboolean *headphonemic);
    static headsetPorts *getHeadsetPorts (const pa_card_info *c);
    void freePrivPortNames();

    void setDeviceButtonState(int row);
    void addOutputListWidgetItem(QString portName, QString portLabel,QString cardName); //添加output listWidget item
    void addInputListWidgetItem(QString portName, QString cardName); //添加input listwidget item

    int findCardIndex(QString cardName, QMap<int,QString> cardMap);//查找声卡指定的索引
    QString findCardName(int index,QMap<int,QString> cardMap);
    QString findHighPriorityProfile(int index,QString profile);
    QString findPortSink(int index,QString portName);
    QString findPortSource(int index,QString portName);

    bool outputPortIsNeedDelete(int index,QString name);//port是否需要在outputListWidget删除
    bool outputPortIsNeedAdd(int index,QString name);//port是否需要在outputListWidget删除
    bool inputPortIsNeedDelete(int index,QString name);//port是否需要在inputListWidget删除
    bool inputPortIsNeedAdd(int index,QString name);//port是否需要在inputListWidget删除

    int indexOfOutputPortInOutputListWidget(QString portName);
    int indexOfInputPortInInputListWidget(QString portName);

    void deleteNotAvailableOutputPort(); //删除不可用的输出端口
    void addAvailableOutputPort(); //添加可用输出端口
    void deleteNotAvailableInputPort(); //删除不可用的输入端口
    void addAvailableInputPort(); //添加可用输入端口

    QString findOutputPortName(int index,QString portLabel); //找到outputPortLabel对应的portName
    QString findInputPortName(int index,QString portLabel); //找到inputPortLabel对应的portName
    QString findOutputPortLabel(int index,QString portName); //查找名为portName对应的portLabel
    QString findInputPortLabel(int index,QString portName); //查找名为portName对应的portLabel
    void setCardProfile(QString name,QString profile); //设置声卡的配置文件
    void setDefaultOutputPortDevice(QString devName,QString portName); //设置默认的输出端口
    void setDefaultInputPortDevice(QString devName,QString portName); //设置默认的输入端口
    QString findCardActiveProfile(int index); //查找声卡的active profile
    QString stringRemoveUnrecignizedChar(QString str);//移除xml文件中不能识别的字符

    void findOutputListWidgetItem(QString cardName,QString portLabel);
    void findInputListWidgetItem(QString cardName,QString portLabel);
    QString blueCardName(); //记录蓝牙声卡名称
    bool inputDeviceContainBluetooth();
    QString findFile(const QString path,QString str);

    void inhibit();
    void uninhibit();
    void switchModuleEchoCancel(); //加载或卸载降噪模块
    void resetVolumeSliderRange(); //重新设置滑动条的范围

protected:
    bool eventFilter(QObject *obj, QEvent *event);
    void paintEvent(QPaintEvent *event);
    void keyPressEvent(QKeyEvent *event);

Q_SIGNALS:
    void mouse_middle_clicked_signal();
    void mouse_wheel_signal(bool step);
    void app_name_signal(QString app_name);
    void theme_change();
    void font_change();

    void device_changed_signal(QString dev_name);//设备更换信号

private Q_SLOTS:
    void activatedSystemTrayIconSlot(QSystemTrayIcon::ActivationReason reason); //托盘图标
    void jumpControlPanelSlot(); //跳转到控制面板

    void setHeadsetPort(QString str); //根据弹出框选择的切换不同的端口
    void handleTimeout(); //超时播放提示音
    void advancedSystemSliderChangedSlot(int value); //advancedSystemSlider值改变
    void systemVolumeSliderChangedSlot(int value);
    void systemVolumeButtonClickedSlot();

    void mouseMeddleClickedTraySlot(); //鼠标中间贱点击托盘图标
    void trayWheelRollEventSlot(bool step); //鼠标滚轮在托盘图标上滚动

    void appWidgetMuteButtonCLickedSlot();//应用音量静音按钮点击

    void ukuiThemeChangedSlot(const QString &themeStr); //主题改变
    void fontSizeChangedSlot(const QString &themeStr); //字体大小改变
    void volumeSettingChangedSlot(); //volume gseting值改变
    void initVolumeSlider(); //初始化滑动条
    void initDefaultSinkVolume();//初始化默认音量
    void initDefaultSourceVolume();

    void addAppToAppwidget(const gchar *name,const gchar *iconName,int index,int value,int channel); //添加应用
    void removeSubAppWidget(const gchar *m_pAppName); //移除子应用窗口
    void sinkInputVolumeChangedSlot(const gchar *name,const gchar *iconName,int value); //sinkInput音量更新
    void soundSettingChanged(const QString &);

    //添加拔插headset提示
    void checkAudioDeviceSelectionNeeded (const pa_card_info *info);
    void updateDevicePort();
    void updateListWidgetItemSlot(); //更新输出设备列表
    void outputListWidgetCurrentRowChangedSlot(int row); //output list widget选项改变
    void inputListWidgetCurrentRowChangedSlot(int row); //output list widget选项改变
    void updateAppVolume(QString str, int value, bool state);


    void deviceChangedShowSlot(QString dev_name);//osd提示弹窗
    void osdDisplayWidgetHide();                 //osd超时隐藏

    void onTransChanged();
    void paintWithTrans();

    void onPrepareForSleep(bool sleep);

private:
    QLabel *systemWidgetLabel;
    QLabel *appWidgetLabel;
    QHBoxLayout * m_tabBarLayout = nullptr;

    UkmediaVolumeControl *m_pVolumeControl;
    UkmediaSystemVolumeWidget *systemWidget;
    QTabWidget *m_pTabWidget;
    ApplicationVolumeWidget *appWidget; //应用界面窗口
    UkmediaOsdDisplayWidget *osdWidget;
    UkuiMediaSetHeadsetWidget *headsetWidget; //当声卡中有headsetmic 端口时插入4段式耳机的弹窗

    UkmediaOsdDisplayWidget *headset;   //需求:输出设备插拔提示弹出

    Divider *volumeLine;
    Divider *volumeSettingLine;

    MyTimer *timer; //定时器
    QMenu *menu; //右键菜单
    QGSettings *m_pSoundSettings;
    QGSettings *m_pThemeSetting; //主题gsettting
    QGSettings *m_pTransparencySetting; //透明度gestting
    QGSettings *m_pVolumeSetting; //
    QGSettings *m_pFontSetting; //字体gsetting
    QGSettings *m_pInitSystemVolumeSetting; //初始化系统音量

    QGSettings * m_pTransGsettings;   //透明度配置文件
    double m_pTransparency=0.0;  //透明度

    UkmediaTrayIcon *soundSystemTrayIcon; //系统托盘
    QAction *m_pSoundPreferenceAction; //声音首选项菜单项

    QStringList *eventList; //提示声音类型列表
    QStringList *eventIdNameList; //提示声音名称列表

    QMap<int, QString> currentOutputPortLabelMap;
    QMap<int, QString> currentInputPortLabelMap;
    int      headsetCard; //headset 声卡
    gboolean hasHeadsetmic; //是否包含headset mic端口
    gboolean hasHeadphonemic; //是否包含headphone mic端口
    gboolean headsetPluggedIn; //headpset 是否插入
    char *m_pHeadphonesName; //headphone名称
    char *m_pHeadsetmicName; //
    char *m_pHeadphonemicName;
    char *m_pInternalspkName;
    char *m_pInternalmicName;

    QTimer *m_pTimer;
    QTimer *m_pTimer2;
    bool mouseReleaseState = false; //鼠标释放状态
    bool mousePress = false; //鼠标按下状态
    bool shortcutMute = false;
    bool firstEntry = true;
    bool inputFirstEntry = true;
    bool isFirstMuteLed = true;

    QProcess *m_process;
    QString mThemeName = UKUI_THEME_WHITE;
    bool firstEnterSystem = true;
    ca_context *caContext;
    bool firstLoad = true;

    bool isPlay = true; //用于避免运行托盘时第一次响起的提示音
    bool sinkInputMute = false;
    bool isFirstRecive = true;
    bool kylinVideoMuteSignal = false;
    bool kylinVideoVolumeSignal = false;
    bool isAppMuteBtnPress = false;
    bool isLoadEchoCancel = false;
    int updateAppVolumeCount = 0;
    int outputListWidgetRow = -1;

    QDBusUnixFileDescriptor m_inhibitFileDescriptor;
};

#endif // UKMEDIAMAINWIDGET_H
