/*
 * Copyright (C) 2020, 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/>.
 */
#ifndef CMSGPANE_H
#define CMSGPANE_H

#include "reader.h"
#include "recorder.h"
#include "chatdatabase.h"
#include "systemchat.h"
#include <kysdk/kysdk-system/libkydatacollect.h>
#include <unistd.h>
#include <string>
#include <cmark.h>
#include <iostream>


#include <QAction>
#include <QApplication>
#include <QBuffer>
#include <QByteArray>
#include <QDBusUnixFileDescriptor>
#include <QDBusInterface>
#include <QDBusObjectPath>
#include <QDBusReply>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QImage>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QLabel>
#include <QMenu>
#include <QMenuBar>
#include <QPushButton>
#include <QSystemTrayIcon>
#include <QTextEdit>
#include <QTimer>
#include <QToolButton>
#include <QWidget>
#include <QProcess>
#include <QPrinter>
#include <QImageWriter>

class CPushButtonEx;
class Reader;
class Recorder;
class PhotoViewerPlugin;

#define MAXIMAGESIZE 50 * 1024 * 1024

using namespace kyai::config::model;


class SystemChat;
enum WindowMode
{
    WINDOW_MODE_NORMAL = 0,
    WINDOW_MODE_OCCUPIED =1,
    WINDOW_MODE_SIDEMODE =2,
    WINDOW_MODE_WINDOWMODE=3,
};
enum ActiveModule{
    MODULE_PLUGIN = 0,
    MODULE_CHAT = 1,
};

class CMsgPane : public QObject
{
    Q_OBJECT
public:
    explicit CMsgPane();
    //报错消息头处理
    void errorMessageToJs(QString msgHead, QString modelMsg, QString colorMsg, QString errorMsg);
    void clearJsonMessage();

    WindowMode m_windowMode;
    ActiveModule m_activeModule = ActiveModule::MODULE_CHAT;
    void pushMsg(QString func);
    void pushMsg(QString func, QVariant arg1);
    void pushMsg(QString func, QString jsonMsgHeadToWeb, QString msg);
    bool getIsEnd();
public slots:
    // 切换模型
    //返回主页
    void onBackBtnClicked();
    void onSwitchToPlugin(QString page);
    //消息
    void onClearContext();
    QString onSendMsg(const QString &jsonMsgHead, const QString &msg);
    void onRecvMsg(QString reasoningContentMsg, QString msg, bool is_reasoning_end, bool is_end, int index, int errorCode, QString model = "", QString feedbackURL = "");
    void onAudioRecvMsg(QString msg, bool is_end, int index, int errorCode, QString model);         //处理语音类问题报错
    void onRecvTool(QString msg, QMap<int, QString> imageToolMap, QString imagePath, int errorCode, QString model, QString feedbackURL);
    void onLoadMessageList();
    void onChangedIsReplyingStatus(bool isReplying);
    //图像
    void onSelectFile(int typeNum);
    void onShowImage(const QString &imagePath, int counts);
//    void onSendImage(const QString &imagePath);
    QString onPictureOperateClick(int toolId, const QString &imagePath);
    void onImageDragIn(bool dragin);
    void onShowErrorMoreImage();
    void onShowErrorSizeImage();
    void onShowErrorFormatImage();
    void updateToShowPic(QString imageData, QString errorMessage); // 更新图片处理返回的图片
    void updateToShowOperatePic(QString imageData, QString errorMessage); // 更新图像处理返回的图片
    void sigPictureAutoSpeak(); //语音文生图后触发自动朗读
    //文档
    void onShowDocument(const QString &filePath);
    void onShowErrorFormatFile();
    void onShowErrorFormat();
    //文生图
//    void updateToShowAIPic(VisionImageData *imageData, QString errorMessage); // 更新AI文生图的图片
    void onDownloadImage(const QString &base64Image); // 下载图片
    void onSaveHTML2PDF(const QString &base64Image);
    //系统助手-信息来源
    void updateToShowSource(QMap<int, QString> infoSourceMap); // 更新系统助手信息来源
    void onSelectInfoSource(int toolId); // 跳转到信息来源
    //埋点数据
    void onSendDataCollect(const QString &eventCode, const QString &pageName);
    //会话
    void saveDialog();
    void clearDialog();
    void onShowText(const QString text);
    void onShowSpeech(const QString text);
    void onAppendSpeech(const int speakerID, const QString text);
    void userAccountsChanged();
    void loadPlugin(QString pluginHtmlFile);
    void onAddToSchedule(int operatorId, QString schedule_date, QString msg, QString model, QString feedbackURL);    //添加到日历
    void openSchedule(QString schedule_date);                       //通过AI SDK打开日历
    //功能-语音输入
    void onSendAudio();
    void onStopAudio();
    void onCancelAudio();
    void onStartTimer();        //打开30s定时器
    void onSpeechModeChanged(int speechMode);    // 更新语音状态
    //功能-语音朗读
    void onStartRead(const QString &msg, int index);
    void onPauseRead();
    void onContinueRead(int index);
    void onReadEnd(int index);
    //语音听写
    void onClearDictation();
    //复制成功
    void onCopySuccess();
    void onCopyText(const QString &text);
    void onCopyImage(const QString &base64Image);
    //点赞点踩
    void onLikeAction();
    //新建对话-提示对话进行中
    void onContinueDialog();
    void onTipsContinueDialog();
    //设置会议助手重新生成功能正在运行中
    void onsigReloadIsRunning();
    void onReloadIsRunning();

    void onStopReply();
    //清除所有Session
    void onCloseAllSession();
    void xdgOpen(QString path);
    void xdgOpenForImageOperate(QString base64Image,int operatorId, QString imagePath);
    void saveToDatabase(int msgInex, QString message);  //保存消息进数据库
    void updateFeedbackDatabase(int msgInex, QString message);
    void loadHistory();
    void loadHistoryBySessionId(QString sessionId);

    void getPluginList();
    void getDialogueList();
    void modifyDialogueList(const QVariantList &strings);
    void initDeleteLayout(const QVariantList &strings);
    void closeSession();
    void deleteSessionList(const QVariantList &strings);

    int getCurWinMode(){return m_windowMode;}
    QString convertMarkDownToHtml(const QString &markDown);
    ActiveModule getCurrentActiveModule(){return m_activeModule;}
    void updateCurrentActiveModule(const int pageNumber);
    void initCurrentUser();

    //文档处理
    void openDocument(const QString &documentPath); // 打开文档
    bool isSupportDocumentQA(); //返回是否支持文档问答
    bool isSupportHtml2Docx(); //返回是否支持周报html格式转docx格式

    //图片处理
    bool isSupportImageProcessing(); //返回是否支持图片问答

    int getCurrentSessionId();

    void activateMainWindow();  // 触发信号
    int getShowPage();
    void updateDialogueListSessionId();
    void onStopSpeak(); //停止朗读
    void openUkuiControlCenter();
    void handleInputDeviceChanged();
    void onStartReplyingToChat();

public:
    int m_operatorId = -1; // 图像处理操作id

private:
    void createAllChildWnd();
    void initSolts();
    void initChatOperator();
    void initCommandList();
    void initCurrentUserName();
    void initCurrentUserIcon();


    void saveDialogToFile(const QString &dialogJsonString);
    void saveMessageToFile(const QString &msgJsonString);

    QString getBase64FromImagePath(const QString &imagePath); // 从图片路径获取到Base64编码
    QString getDefaultFace();
    bool isCommunity();
    void initDefaultUserIcon();
    QString markdownToHtml(const std::string& markdown);
    bool checkChatModel(int errorCode);

private slots:
    void updateBubble();

signals:
    void sigSetup();
    void sigSaveDialog(QString filePath);
    void sigLoadMyMessageBox(const QVariantList &strings);
    void addMsg(QString jsonMsgHead, QString msg);
    void addRecvMsg(QString jsonMsgHead, QString msg);
    void updateMsg(QString jsonMsgHead, QString msg);
    void updateReasoningMsg(QString jsonMsgHead, QString msg);
    void addRecvSources(QString jsonMsgHead);
    void appendRecvTool(QString jsonMsgHead);
    void replyEnd(bool isEnd);
    void replyingChanged(bool replying);
    void insertImage(QString base64EncodedImage, int operatorId, QString imagePath);    //向前端發送文生圖生成的圖片
    void sigCancelGenerateImage();
    void insertOperateImage(QString base64EncodedImage, int operatorId, QString imagePath); //图像处理向前端发送生成的图片
    void updateOperateRefresh(); //图像处理更新重新回答为不可用
    void setReadEnd(int index);
    void sendImage(QString imagePath, QString base64Image);
    void setReplyOptions(const QString imagePath);
    void recvImage(const QString scheJsonMsgHeadToWeb, const QString blackAndWhiteImagePath, const QString base64Image);
    void sigReloadIsRunning();//会议助手正在运行重新生成功能
    void sigHasNoModel(const QString errorStr);//未配置模型处理信号
    void sigSetReloadStatus(bool isReloading);//设置正在生成状态
    void contextCleared();
    void loadConversation(QStringList list);
    //侧边栏模式控制前端显示页面
    //0显示全部 1显示主页面 2显示侧边栏  4窗口模式下显示主界面
    void showPage(int num);    void showPluginPage(int num, QString pluginName);//侧边栏模式切换插件页面
    void showWindowPage(int num);   //窗口模式切换页面
    void showWindowPluginPage(int num, QString pluginName); //窗口模式切换插件页面
    void changeToSideMode(int width, int height);
    void changeToWinMode(int height);
    void changeWinModeToChat(int num);
    void loadDialogueList(QStringList list);
    void loadPluginList(QStringList list);
    void deleteDialogueList(QStringList deleteList);
    void changeCurrentUserName(QString name);
    void changeCurrentUserIcon(QString name);
    void copyToClipboard(QString text);     //添加文字到剪切板
    void copySuccess();
    void copyImageToClipboard();
    void tipsContinueDialog();
    void addImagePreview(QString imagePath, QString base64Image);
    void addDocumentPreview(QString filePath, QString icon, QString fileName, QString fileSize);
    void saveToPDF();
    void addReportPath(QString path);
    void showSettingPage();
    void modifyDialogueListFlag(QString sessionID);
    void sigSaveAs(const QString &base64Image); //图片另存为打开filedialog
    void sigOpenFile(int type);

    void sigBtnClicked(const int activeModule);
    void saveLastMsgToDatabase();       //将listmodel最后一条消息存入数据库
    void cancelSendAudio(); //取消语音发送
    void updateCurrentStartTimer();
    void triggerAutoRead(QString msg);
    void clearListModel();
    void moveScrollBar();  //将前端滚动条移动到最新位置
    void changeSessionId(int sessionId);  //发送前端当前的sessionId
    void activateMainWindowSignal();  // 定义一个信号
    void keyReturnPressed();//发送按下回车键信号
    void updateDialogueList();
    void cancelVoiceStopReplying();//取消语音发送
    void sigSendTmpMsgToQML(const QString str); //向前端发送语音识别中间结果
    void sigSendMsgToQML(const QString str);    //向前端发送语音识别修正后结果
    void sigResetPreIndex();
    void sigLikeAction();
    void startReplyingToChat(bool isReplying);
    void sendFocusChanged();

private:
    Reader *m_reader = nullptr;
    Recorder *m_recorder = nullptr;

    CommandTemplateList *m_commandListModel = nullptr;

    CPushButtonEx *m_btnMore = nullptr;
    CPushButtonEx *m_btnVoice = nullptr;
    QLabel *m_labSeparatorLine = nullptr;
    QAction *confAction = nullptr;
    //NLP语言模型
    SystemChat *m_chat = nullptr;

    //文字发送的消息
    QString send_message;
    //语音发送消息到前端
    QString speech_send_message;
    int bubble_show_speech_count;
    uint loading_speech_dot_index;
    QTimer *speech_bubble_update_timer = nullptr;
    bool new_reply = true;                  //标记是否为新回答
    bool m_is_reasoning_end = true; // 标记思考过程是否结束
    QString recv_message;
    QString recv_reasoning_message; // 思考过程接收消息
    QString m_finishedSpeech;
    QString msgHead;                        //消息头
    int promptId = -1;                      //提示词ID
    bool speechFlag;
    QJsonObject jsonObjToWeb;
    QString m_defaultUserIcon;
    ChatDatabase * m_database = nullptr;    //数据库
    QStringList m_pluginList;

    QString imagePath;
    QString imageSrc;

    QString documentPath;
    QString documentIcon;
    QString documentName;
    QString documentSize;
    //待办
    QString m_todolist;
    int toolId = -1;

    // 语音四种状态，对应qml speechMode: 0 点击说话（启动状态）1 点击说话（禁用状态）2 完成说话（启用状态）3 识别中...（禁用状态）
    int speechMode = 0;

    //更新isreplying
    bool  m_isReplying = false;

};

#endif // CMSGPANE_H
