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

#include <limits>

#include <QMutex>
#include <QWidget>
#include <QVariantMap>
#include <QGSettings>
#include <QSettings>
#include <QButtonGroup>
#include <QDBusInterface>
#include <QDBusConnection>
#include <QDBusError>
#include <QDBusReply>
#include <QStringList>
#include <QSharedPointer>
#include <QHash>
#include <QVariant>
#include <QScreen>
#include <QMultiMap>
#include <QShortcut>
#include <QFuture>
#include <QVBoxLayout>
#include "splicedialog.h"

#include <KF5/KScreen/kscreen/config.h>

#include "outputconfig.h"
#include "brightnessFrame.h"
#include "screenConfig.h"
#include "titlelabel.h"
#include "fixlabel.h"
#include "lightlabel.h"
#include "uslider.h"
#include "switchwidget.h"
#include "kswitchbutton.h"
#include "ukccframe.h"
#include "settinggroup.h"
#include "comboxwidget.h"
#include "sliderwidget.h"

using namespace kdk;

#define USD_CLONE_MODE 1

class QLabel;
class QMLOutput;
class QMLScreen;
class ControlPanel;
class PrimaryOutputCombo;

class QPushButton;
class QComboBox;

class QQuickView;
class QQuickWidget;
class QStyledItemDelegate;

typedef enum {
    SUN,
    CUSTOM,
}MODE;

typedef enum {
#ifndef MAVIS
    FIRST,
    VICE,
#endif
    EXTEND,
    CLONE,
    SPLICE
}MULTISCREEN;

namespace KScreen {
class ConfigOperation;
}

namespace Ui {
class DisplayWindow;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget() override;

    void setConfig(const KScreen::ConfigPtr &config);
    KScreen::ConfigPtr currentConfig() const;

    void initNightModeUi();
    void slotFocusedOutputChangedNoParam();
    void initConnection();
    QString getScreenName(QString name = "");
    void setNightComponent();

    bool writeFile(const QString &filePath);
    void writeGlobal(const KScreen::OutputPtr &output);
    bool writeGlobalPart(const KScreen::OutputPtr &output, QVariantMap &info,
                         const KScreen::OutputPtr &fallback);
    QString globalFileName(const QString &hash);
    QVariantMap getGlobalData(KScreen::OutputPtr output);

    float converToScale(const int value);
    int scaleToSlider(const float value);

    void initUiComponent();
    void hideComponent();
    void addBrightnessFrame(QString name, bool openFlag, QString edidHash);
    void showBrightnessFrame(const int flag = 0);

    QList<ScreenConfig> getPreScreenCfg();
    void setPreScreenCfg(KScreen::OutputList screens);

    void changescale(QSize size = QSize());
    void getAllI2Cbus();
    void getEdidI2Cbus();
    void initUi();

protected:
    bool eventFilter(QObject *object, QEvent *event) override;

Q_SIGNALS:
    void changed();

    void nightModeChanged(const bool nightMode) const;
    void redShiftValidChanged(const bool isValid) const;

private Q_SLOTS:
    void slotFocusedOutputChanged(QMLOutput *output);

    void slotOutputEnabledChanged();
    void slotOutputConnectedChanged();

    void slotUnifyOutputs();

    void slotIdentifyButtonClicked(bool checked = true);
    void slotIdentifyOutputs(KScreen::ConfigOperation *op);
    void clearOutputIdentifiers();

    void outputAdded(const KScreen::OutputPtr &output, bool connectChanged);
    void outputRemoved(int outputId, bool connectChanged);
    void primaryOutputSelected(int index);
    void primaryOutputChanged(const KScreen::OutputPtr &output);

    void showNightWidget(bool judge);

    void primaryButtonEnable(bool);             // 按钮选择主屏确认按钮
    void mainScreenButtonSelect(int index);     // 是否禁用设置主屏按钮
    void checkOutputScreen(bool judge);         // 是否禁用屏幕

    void setNightMode(const bool nightMode);    // 设置夜间模式

    void initNightStatus();                     // 初始化夜间模式

    void setNightModeSetting();                 // 通过配置文件设置夜间模式
    void nightChangedSlot(QHash<QString, QVariant> nightArg);
    QString getSunTime();                          // 获取日出日落时间

    void callMethod(QRect geometry, QString name);// 设置wayland主屏幕
    QString getPrimaryWaylandScreen();
    void usdScreenModeChangedSlot(int status);

    void setMultiScreenSlot(int index);

    void applyNightModeSlot();

    void delayApply();

public Q_SLOTS:
    void save();
    void changedSlot();
    void propertiesChangedSlot(QString, QMap<QString, QVariant>, QStringList);
    void mOutputClicked();
    void scaleChangedSlot(double scale);

private:
    void loadQml();
    void resetPrimaryCombo();
    void addOutputToPrimaryCombo(const KScreen::OutputPtr &output);
    KScreen::OutputPtr findOutput(const KScreen::ConfigPtr &config, const QVariantMap &info);

    void initComponent();
    void initDbusComponent();
    void setHideModuleInfo();
    void writeScale(double scale);
    void initGSettings();
    void setcomBoxScale();
    void initAutoBrihgtUI();
    void initAdvanceScreen();

    bool isRestoreConfig();
    bool isCloneMode();
    bool isBacklight();
    bool isBacklightAllInOne();
    bool isLaptopScreen();
    bool isVisibleBrightness();

    QString getCpuInfo();
    QString getMonitorType();

    int getPrimaryScreenID();

    void setScreenIsApply(bool isApply);

    void setMulScreenVisiable();
    void initMultScreenStatus();
    void updateMultiScreen(); // 屏幕插拔更改状态
    int updateScreenConfig(); // 获取系统最新配置

    void showZoomtips();      // 缩放注销提示框
    void compareScale();
    void outputEnableChanged();

    bool checkSpliceFeasibility();
    void initSpliceFrame();
    void setSpliceFrameVisiable(bool b);

private:
    Ui::DisplayWindow *ui;
    QMLScreen *mScreen = nullptr;

    KScreen::ConfigPtr mConfig     = nullptr;
    KScreen::ConfigPtr mPrevConfig = nullptr;
    KScreen::OutputPtr res         = nullptr;
    OutputConfig *mOutputConfig    = nullptr; // 设置主显示器相关控件

    QList<QQuickView *> mOutputIdentifiers;
    QTimer *mOutputTimer           = nullptr;

    QString mCPU;
    QString mDir;
    QString mScaleDir;
    QString mUsdScaleDir;
    QStringList mPowerKeys;

    KSwitchButton *mUnifyButton   = nullptr;
    KSwitchButton *mAutoBrightBtn = nullptr;
    KSwitchButton *mBackBrightBtn = nullptr;

    TitleLabel *mNightModeLabel = nullptr;
    QLabel *mOpenLabel          = nullptr;
    QLabel *mTimeModeLabel      = nullptr;
    QLabel *mCustomTimeLabel    = nullptr;
    FixLabel *mTemptLabel       = nullptr;
    FixLabel *mWarmLabel        = nullptr;
    FixLabel *mColdLabel        = nullptr;
    QLabel *mLabel_1            = nullptr;

    QLabel *nightLabel          = nullptr;
    QLabel *mMultiScreenLabel   = nullptr;
    QLabel *mAutoBrightLabel    = nullptr;
    QLabel *mBackBrightLabel    = nullptr;
    LightLabel *mBackHintLabel  = nullptr;
    LightLabel *mBrightHintLabel= nullptr;
    LightLabel *mNightHintLabel = nullptr;

    QComboBox *mOpenTimeHCombox   = nullptr;
    QComboBox *mQpenTimeMCombox   = nullptr;
    QComboBox *mCloseTimeHCombox  = nullptr;
    QComboBox *mCloseTimeMCombox  = nullptr;
    QComboBox *mMultiScreenCombox = nullptr;

    QGSettings *scaleGSettings      = nullptr;
    QGSettings *mPowerGSettings     = nullptr;
    QGSettings *m_colorSettings     = nullptr;
    QGSettings *mAutoBrightSettings = nullptr;

    QSettings *mQsettings = nullptr;

    QButtonGroup *singleButton;

    QSharedPointer<QDBusInterface> mUPowerInterface;
    QSharedPointer<QDBusInterface> mUkccInterface;
    QDBusInterface *mUsdDbus;
    QDBusInterface *m_StatusDbus = nullptr;

    QHash<QString, QVariant> mNightConfig;

    double mScreenScale = 1.0;
    double scaleres = 1.0;
    QMap <QString, double> firstChangeScaleList;
    double firstChangeScale = 0.0;

    QSize mScaleSizeRes = QSize();

    bool mIsNightMode     = false;
    bool mRedshiftIsValid = false;
    bool mIsScaleChanged  = false;
    bool mOriApply;
    bool mConfigChanged   = false;
    bool mOnBattery       = false;
    bool mBlockChanges    = false;
    bool mFirstLoad       = true;
    bool mIsWayland       = false;
    bool mIsBattery       = false;
    bool mIsScreenAdd     = false;
    bool mIsRestore       = false;

    bool mIsSCaleRes      = false;
    bool mIsChange        = false;
    bool exitFlag         = false;
    bool unifySetconfig   = false;
    bool mIscloneMode     = false;
    bool mIsEyeCareMode   = false;

    QStringList mTimeModeStringList;

    QString firstAddOutputName;
    QShortcut *mApplyShortcut;
    QVector<BrightnessFrame*> BrightnessFrameV;
    QString mOutputClickedName;
    QDBusInterface *dbusEdid = nullptr;
    QString cpuArchitecture = "";
    QString mMachineType;

    int mKdsStatus = INT_MIN;
    QMap<QString, QString> I2CbusMap;
    QMap<QString, QString> edidI2CbusMap;

    SpliceDialog *spliceDialog;
    int connectedOutputNum;
    QLabel *spliceMethodLabel = nullptr;

private:
    SettingGroup  *modeGroup         = nullptr;
    UkccFrame     *mMultiScreenFrame = nullptr;
    UkccFrame     *spliceFrame       = nullptr;
    SettingGroup  *configGroup       = nullptr;
    UkccFrame     *monitorFrame      = nullptr;
    FixLabel      *monitorLabel      = nullptr;
    QComboBox     *monitorComboBox   = nullptr;
    QPushButton   *monitorBtn        = nullptr;
    ControlPanel  *mControlPanel     = nullptr;
    UkccFrame     *scaleFrame        = nullptr;
    FixLabel      *scaleLabel        = nullptr;
    QComboBox     *scaleComboBox     = nullptr;
    UkccFrame     *openMonitorFrame  = nullptr;
    FixLabel      *openMonitorLabel  = nullptr;
    KSwitchButton *openMonitorButton = nullptr;
    UkccFrame     *mbrightnessFrame  = nullptr;
    QVBoxLayout   *mbrightnesslayout = nullptr;
    SettingGroup  *mNightModeFrame   = nullptr;
    SwitchWidget  *mEyesModeFrame    = nullptr;
    SwitchWidget  *mNightModeWidget  = nullptr;
    ComboxWidget  *mTimeModeWidget   = nullptr;
    UkccFrame     *mCustomTimeWidget = nullptr;
    SliderWidget  *mTemptWidget      = nullptr;

    SwitchWidget *mAutoBrightFrame = nullptr;

};

#endif // WIDGET_H
