/*
 * 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/>.
 *
**/
#include "brightnessFrame.h"
#include <QHBoxLayout>
#include <QtConcurrent>
#include <QGSettings>
#include <QDBusConnection>
#include <QDBusMessage>
#include <unistd.h>
#include <QDBusReply>
#include <QDBusInterface>
#include "ukcccommon.h"
using namespace ukcc;

#define POWER_SCHMES                     "org.ukui.power-manager"
#define POWER_KEY                        "brightness-ac"
#define POWER_KEY_C                      "brightnessAc"

BrightnessFrame::BrightnessFrame(const QString &name, const bool &isBattery, const QString &edidHash, QWidget *parent)
    : UkccFrame(parent, UkccFrame::BorderRadiusStyle::None, false)
{
    QHBoxLayout *layout = new QHBoxLayout;
    layout->setSpacing(6);
    layout->setMargin(0);

    QHBoxLayout *layout_2 = new QHBoxLayout;
    layout->setMargin(0);

    QVBoxLayout *fLayout = new QVBoxLayout(this);
    fLayout->setContentsMargins(16, 0, 16, 0);
    fLayout->setSpacing(4);
    fLayout->addLayout(layout);
    fLayout->addLayout(layout_2);

    labelMsg = new LightLabel(this);
    layout_2->addWidget(labelMsg);
    labelMsg->setDisabled(true);
    labelMsg->setText(tr("Failed to get the brightness information of this monitor"));//未能获得该显示器的亮度信息

    labelName = new FixLabel(this);
    labelName->setFixedWidth(118);

    slider = new KSlider(Qt::Horizontal, this);
    slider->setSliderType(KSliderType::SmoothSlider);
    slider->setPageStep(1);
    slider->setRange(0, 100);
    slider->setNodeVisible(false);

    labelValue = new QLabel(this);
    labelValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

    layout->addWidget(labelName);
    layout->addWidget(slider);
    layout->addWidget(labelValue);

    this->outputEnable = true;
    this->connectFlag = true;
    this->exitFlag = false;
    this->isBattery = isBattery;
    this->outputName = name;
    this->edidHash = edidHash;
    this->i2cBus = "-1";
    this->mGetBrightnessThread = nullptr;

    labelValue->setText("0"); //最低亮度10,获取前显示为0
    slider->setEnabled(false); //成功连接了再改为true，否则表示无法修改亮度
    if (getTabletMode()) {
        this->setFixedHeight(TABLET_HEIGHT + 48);
    } else {
        this->setFixedHeight(PC_HEIGHT + 36);
    }

    connect(this, &BrightnessFrame::tabletModeChanged, this, [=](bool isTablet) {
        if (isTablet) {
            if (labelMsg) {
                this->setFixedHeight(TABLET_HEIGHT + 48);
            } else {
                this->setFixedHeight(TABLET_HEIGHT);
            }
        } else {
            if (labelMsg) {
                this->setFixedHeight(PC_HEIGHT + 36);
            } else {
                this->setFixedHeight(PC_HEIGHT);
            }
        }
    });
}

BrightnessFrame::~BrightnessFrame()
{
    exitFlag = true;
    if (mGetBrightnessThread && mGetBrightnessThread->isRunning()) {
        mGetBrightnessThread->setExit(true);
        mGetBrightnessThread->terminate();
        mGetBrightnessThread->quit();
        mGetBrightnessThread->wait();
    }
}

void BrightnessFrame::setTextLabelName(QString text)
{
    this->labelName->setText(text);
}

void BrightnessFrame::setTextLabelValue(QString text)
{
    qDebug() << Q_FUNC_INFO << text;
    this->labelValue->setText(text + "%");
}

void BrightnessFrame::runConnectThread(const bool &openFlag)
{
    outputEnable = openFlag;
    if (false == isBattery) {
        if (!mGetBrightnessThread) {
            mGetBrightnessThread = new GetBrightnessThread(this->edidHash, this->i2cBus);
            connect(mGetBrightnessThread, &GetBrightnessThread::finished, this, [=](){
                mGetBrightnessThread->deleteLater();
                mGetBrightnessThread = nullptr;
            });

            connect(mGetBrightnessThread, &GetBrightnessThread::getBrightnessFinished, this, [=](int brightnessValue){
                if (brightnessValue < 0 || !slider || exitFlag) {
                    return;
                }
                slider->blockSignals(true);
                slider->setValue(brightnessValue);
                slider->blockSignals(false);
                setTextLabelValue(QString::number(brightnessValue));
                setSliderEnable(true);
                labelMsg->hide();
                if (getTabletMode()) {
                    this->setFixedHeight(TABLET_HEIGHT);
                } else {
                    this->setFixedHeight(PC_HEIGHT);
                }
                disconnect(slider,&QSlider::valueChanged,this,0);
                connect(slider, &QSlider::valueChanged, this, [=](){
                     qDebug()<<outputName<<"brightness"<<" is changed, value = "<<slider->value();
                     setTextLabelValue(QString::number(slider->value()));
                     setDDCBrightness(slider->value());
                     UkccCommon::buriedSettings(QString("display"), QString("Brightness-pc"), QString("settings"), QString::number(slider->value()));
                });
            });
            mGetBrightnessThread->start();
        }
    } else {
        QByteArray powerId(POWER_SCHMES);
        if (QGSettings::isSchemaInstalled(powerId)) {
            QGSettings *mPowerGSettings = new QGSettings(powerId, QByteArray(), this);
            if (!mPowerGSettings->keys().contains(POWER_KEY_C)) {
                setTextLabelValue("-1");
            } else {
                int brightnessValue = mPowerGSettings->get(POWER_KEY).toInt();
                setTextLabelValue(QString::number(brightnessValue));
                slider->blockSignals(true);
                slider->setValue(brightnessValue);
                slider->blockSignals(false);
                setSliderEnable(true);
                labelMsg->hide();
                if (getTabletMode()) {
                    this->setFixedHeight(TABLET_HEIGHT);
                } else {
                    this->setFixedHeight(PC_HEIGHT);
                }
                disconnect(slider,&QSlider::valueChanged,this,0);
                connect(slider, &QSlider::valueChanged, this, [=](){
                    qDebug()<<outputName<<"brightness"<<" is changed, value = "<<slider->value();
                    mPowerGSettings->blockSignals(true);
                    mPowerGSettings->set(POWER_KEY, slider->value());
                    mPowerGSettings->blockSignals(false);
                    setTextLabelValue(QString::number(mPowerGSettings->get(POWER_KEY).toInt()));
                    UkccCommon::buriedSettings(QString("display"), QString("Brightness-book"), QString("settings"), QString::number(slider->value()));
                });
                disconnect(mPowerGSettings,&QGSettings::changed,this,0);
                connect(mPowerGSettings,&QGSettings::changed,this,[=](QString key){
                   if (key == POWER_KEY_C) {
                       int value = mPowerGSettings->get(POWER_KEY).toInt();
                       slider->blockSignals(true);
                       slider->setValue(value);
                       slider->blockSignals(false);
                       setTextLabelValue(QString::number(value));
                   }
                });
            }
        }
    }
}

void BrightnessFrame::setOutputEnable(const bool &enable)
{
    outputEnable = enable;
}

bool BrightnessFrame::getSliderEnable()
{
    return slider->isEnabled();
}

void BrightnessFrame::setSliderEnable(const bool &enable)
{
    if (getSliderEnable() != enable) {
        this->slider->setEnabled(enable);
        Q_EMIT sliderEnableChanged();
    }
    if (false == enable) {
        labelMsg->show();
        if (getTabletMode()) {
            this->setFixedHeight(TABLET_HEIGHT + 48);
        } else {
            this->setFixedHeight(PC_HEIGHT + 36);
        }
        slider->blockSignals(true);
        slider->setValue(0);
        slider->blockSignals(false);
        setTextLabelValue("0");
    }
    return;
}

bool BrightnessFrame::getOutputEnable()
{
    return outputEnable;
}

QString BrightnessFrame::getOutputName()
{
    return outputName;
}

void BrightnessFrame::setDDCBrightness(const int &value)
{
    if (this->edidHash == "")
        return;

    QDBusInterface ukccIfc("com.control.center.qt.systemdbus",
                           "/",
                           "com.control.center.interface",
                           QDBusConnection::systemBus());


    if (mLock.tryLock()) {
        ukccIfc.call("setDisplayBrightness", QString::number(value), this->edidHash, this->i2cBus);
        mLock.unlock();
    }
}

void BrightnessFrame::updateEdidHash(const QString &edid)
{
    this->edidHash = edid;
}

QString BrightnessFrame::getEdidHash()
{
    return this->edidHash;
}
void BrightnessFrame::setI2cbus(QString busNum)
{
    this->i2cBus = busNum;
    return;
}
