/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
 * -*- coding: utf-8 -*-
 *
 * 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
 * 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 "keyboard-widget.h"
#include <QTimer>
#include <QPainter>
#include <QBitmap>
#include <QScreen>
#include "clib-syslog.h"
#include <QDebug>
#include <QLayout>
#include <QPixmap>
#include <QIcon>
#include <QPainterPath>
#include <KWindowSystem>
#include <KWindowEffects>
#include <QDBusMessage>
#include <QDBusConnection>

#include <QApplication>

#include "usd_base_class.h"

#define QT_THEME_SCHEMA             "org.ukui.style"

#define PANEL_SCHEMA "org.ukui.panel.settings"
#define PANEL_SIZE_KEY "panelsize"

#define DEFAULT_LOCALE_ICON_NAME ":/ukui_res/ukui/"
#define INTEL_LOCALE_ICON_NAME ":/ukui_res/ukui_intel/"

KeyboardWidget::KeyboardWidget(QWidget *parent) :
    QWidget(parent)
{
    initWindowHelper();
    initWidgetInfo();
}

KeyboardWidget::~KeyboardWidget()
{
}

void KeyboardWidget::initWidgetInfo()
{
    setWindowFlags(Qt::FramelessWindowHint |
                   Qt::Tool |
                   Qt::WindowStaysOnTopHint |
                   Qt::X11BypassWindowManagerHint |
                   Qt::Popup);

    setAttribute(Qt::WA_TranslucentBackground, true);
    setAutoFillBackground(true);

    m_LocalIconPath = DEFAULT_LOCALE_ICON_NAME;

    m_styleSettings = new QGSettings(QT_THEME_SCHEMA);
    connect(m_styleSettings,SIGNAL(changed(const QString&)),
            this,SLOT(onStyleChanged(const QString&)));


    m_timer = new QTimer(this);
    connect(m_timer,SIGNAL(timeout()),this,SLOT(timeoutHandle()));

    connect(QApplication::primaryScreen(), &QScreen::geometryChanged, this, &KeyboardWidget::geometryChangedHandle);

    connect(static_cast<QApplication *>(QCoreApplication::instance()),
            &QApplication::primaryScreenChanged, this, &KeyboardWidget::geometryChangedHandle);


    this->setFixedSize(OSD_SIZE);
    m_frame = new QFrame(this);
    m_frame->setFixedSize(QSize(OSD_FREME_SIZE));
    m_frame->move((this->width() - m_frame->width())/2, (this->height() - m_frame->height())/2);
    m_btnStatus = new QLabel(m_frame);
    m_btnStatus->setFixedSize(QSize(OSD_ICON_SIZE));
    m_btnStatus->move((m_frame->width() - m_btnStatus->width())/2, (m_frame->height() - m_btnStatus->height())/2);

    geometryChangedHandle();

    QDBusConnection::sessionBus().connect(
        QString(),
        QString(DBUS_GC_SIGNAL_PATH),
        DBUS_GC_SIGNAL_INTERFACE,
        DBUS_GC_SIGNAL_SIGNAL_HIDE_OSD,
        this,
        SLOT(doHideOsd(int)));

}


void KeyboardWidget::timeoutHandle()
{
    m_timer->stop();
    hide();
}
void KeyboardWidget::showWidget()
{
    show();
    geometryChangedHandle();
    repaintWidget();
    m_timer->start(2500);

}


void KeyboardWidget::setIcons(QString icon)
{
    m_iconName = icon;
    USD_LOG(LOG_DEBUG,"%s",m_iconName.toLatin1().data());
    hideOtherOsd();
}

void KeyboardWidget::geometryChangedHandle()
{
    int x=QApplication::primaryScreen()->geometry().x();
    int y=QApplication::primaryScreen()->geometry().y();
    int width = QApplication::primaryScreen()->size().width();
    int height = QApplication::primaryScreen()->size().height();

    int ax,ay;
    ax = x + width * 0.5 - this->size().width() / 2;
    ay = y + height*0.88  - m_frame->size().width()-20;
    setGeometry(QRect(ax, ay, this->width(), this->height()));
    USD_LOG(LOG_DEBUG,"move %s it to %dx%d",m_iconName.toLatin1().data(), ax, ay);
}

void KeyboardWidget::onStyleChanged(const QString& key)
{
    Q_UNUSED(key)
    if(!this->isHidden()) {
        hide();
        repaintWidget();
        show();
    }
}

void KeyboardWidget::doHideOsd(int tye)
{
    if (tye != UsdBaseClass::eOsdType::keyboardIcon) {
        this->hide();
    }
}

void KeyboardWidget::hideOtherOsd()
{
    QDBusMessage notifySignal =
            QDBusMessage::createSignal(DBUS_GC_SIGNAL_PATH, DBUS_GC_SIGNAL_INTERFACE, DBUS_GC_SIGNAL_SIGNAL_HIDE_OSD);
    notifySignal.setArguments({(UsdBaseClass::eOsdType::keyboardIcon)});
    QDBusConnection::sessionBus().send(notifySignal);
}

QPixmap KeyboardWidget::drawLightColoredPixmap(const QPixmap &source, const QString &style)
{

    int value = 255;
    if(style == "ukui-light")
    {
        value = 0;
    }

    QColor gray(255,255,255);
    QColor standard (0,0,0);
    QImage img = source.toImage();
    for (int x = 0; x < img.width(); x++) {
        for (int y = 0; y < img.height(); y++) {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0) {
                if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) {
                    color.setRed(value);
                    color.setGreen(value);
                    color.setBlue(value);
                    img.setPixelColor(x, y, color);
                }
                else {
                    color.setRed(value);
                    color.setGreen(value);
                    color.setBlue(value);
                    img.setPixelColor(x, y, color);
                }
            }
        }
    }
    return QPixmap::fromImage(img);
}

void KeyboardWidget::repaintWidget()
{

    setPalette(QApplication::palette());
    QString m_LocalIconName;
    m_LocalIconName = m_LocalIconPath + m_iconName + QString(".svg");
    QPixmap m_pixmap = QIcon::fromTheme(m_iconName, QIcon(m_LocalIconName)).pixmap(QSize(OSD_ICON_SIZE));
    m_btnStatus->setPixmap(drawLightColoredPixmap(m_pixmap,m_styleSettings->get("style-name").toString()));
}


double KeyboardWidget::getGlobalOpacity()
{
    double transparency=0.0;
    if(QGSettings::isSchemaInstalled(QString("org.ukui.control-center.personalise").toLocal8Bit()))
    {
        QGSettings gsetting(QString("org.ukui.control-center.personalise").toLocal8Bit());
        if(gsetting.keys().contains(QString("transparency")))
            transparency=gsetting.get("transparency").toDouble();
    }
    return transparency;
}

QT_BEGIN_NAMESPACE
extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
QT_END_NAMESPACE

void KeyboardWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QPainterPath rectPath;
    rectPath.addRoundedRect(this->rect().adjusted(10, 10, -10, -10), 12, 12);
    // 画一个黑底
    QPixmap pixmap(this->rect().size());
    pixmap.fill(Qt::transparent);
    QPainter pixmapPainter(&pixmap);
    pixmapPainter.setRenderHint(QPainter::Antialiasing);

    pixmapPainter.setPen(Qt::transparent);
    pixmapPainter.setBrush(this->palette().base());
    pixmapPainter.setCompositionMode(QPainter::CompositionMode_Difference);
    pixmapPainter.setOpacity(0.16);
    pixmapPainter.drawPath(rectPath);
    pixmapPainter.end();
    // 模糊这个黑底
    QImage img = pixmap.toImage();
    qt_blurImage(img, 8, false, false);

    // 挖掉中心
    pixmap = QPixmap::fromImage(img);
    QPainter pixmapPainter2(&pixmap);
    pixmapPainter2.setRenderHint(QPainter::Antialiasing);
    pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear);
    pixmapPainter2.setPen(Qt::transparent);
    pixmapPainter2.setBrush(Qt::transparent);
    pixmapPainter2.drawPath(rectPath);
        // 绘制阴影
    painter.drawPixmap(this->rect(), pixmap, pixmap.rect());

    //绘制描边
    QPainterPath linePath;
    linePath.addRoundedRect(QRect(9,9,m_frame->width()+1,m_frame->height()+1),12,12);
    painter.setCompositionMode(QPainter::CompositionMode_Difference);
    painter.setPen(this->palette().color(QPalette::ColorRole::BrightText));
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(Qt::transparent);
    painter.setOpacity(0.15);
    painter.drawPath(linePath);

    //毛玻璃
    qreal opacity = getGlobalOpacity();
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::transparent);
    painter.setBrush(this->palette().base());
    painter.setOpacity(opacity);
    painter.drawPath(linePath);

    m_windowHelper->setBlurEffect(QRegion(linePath.toFillPolygon().toPolygon()));

    QWidget::paintEvent(event);
}


void KeyboardWidget::initWindowHelper()
{
    m_windowHelper = new UkuiWindowHelper(this);
    m_windowHelper->setWindowState(UkuiWindowHelper::State::KeepAbove);
    m_windowHelper->removeTitleBar();
    m_windowHelper->setSkipTaskBar(true);
    m_windowHelper->setSkipSwitcher(true);
    m_windowHelper->setWindowRole(UkuiWindowHelper::WindowRole::OnScreenDisplay);
}

