/*
* 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/&gt;.
*
*/

#include "calendarbuttontext.h"
#include "../panel/common/common.h"
#include <QtDBus/QtDBus>

#define HOUR_SYSTEM_CONTROL "org.ukui.control-center.panel.plugins"
#define DATA_FORMAT     "date"          //日期格式：yyyy/MM/dd、yyyy-MM-dd
#define TIME_FORMAT     "hoursystem"    //时间格式：12小时制、24小时制

#define SYSTEM_FONT_SET  "org.ukui.style"
#define SYSTEM_FONT_SIZE "systemFontSize"
#define SYSTEM_FONT      "systemFont"
#define SYSTEM_MIN_FONT      10

#define PANEL_SETTINGS      "org.ukui.panel.settings"
#define PANEL_POSITION_KEY  "panelposition"
#define ICON_SIZE_KEY       "iconsize"
#define PANEL_SIZE_KEY      "panelsize"

#define CALENDAR_BUTTON_WIDTH  120
#define PANEL_SIZE_LARGE  92
#define PANEL_SIZE_MEDIUM 70
#define PANEL_SIZE_SMALL  46
#define PANEL_SIZE_KEY    "panelsize"

#define  UKUI_CONTROL_CENTER_SERVER     "org.freedesktop.Accounts"
#define  UKUI_CONTROL_CENTER_PATH       "/org/freedesktop/Accounts/User1000"
#define  UKUI_CONTROL_CENTER_INTERFACE  "org.freedesktop.Accounts.User"
#define  PROPERTIES_NAME                "FormatsLocale"
#define  US_FORMATS                        "en_US.UTF-8"
#define  ZH_CN_FORMATS                     "zh_CN.UTF-8"
#define  BO_CN_FORMATS                     "bo_CN.UTF-8"  //藏文
#define  EN_FORMATS                        "en_US"

#define INSIDE_SPAC 6


CalendarButtonText::CalendarButtonText(IUKUIPanelPlugin *plugin, QPushButton *parent):
    m_plugin(plugin),
    m_parent(parent)
{
    m_dataTime = QDateTime::currentDateTime();
    const QByteArray controlId(HOUR_SYSTEM_CONTROL);
    if (QGSettings::isSchemaInstalled(controlId)) {
        m_timeFormat = new QGSettings(controlId);
    }
    const QByteArray fontId(SYSTEM_FONT_SET);
    if (QGSettings::isSchemaInstalled(fontId)) {
        m_fontGsettings = new QGSettings(fontId);
    }
    const QByteArray panelId(PANEL_SETTINGS);
    if (QGSettings::isSchemaInstalled(panelId)) {
        m_panelGsettings = new QGSettings(panelId);
    }
}

CalendarButtonText::~CalendarButtonText()
{
    if(m_fontGsettings) {
        m_fontGsettings->deleteLater();
    }
    if(m_panelGsettings) {
        m_panelGsettings->deleteLater();
    }
}

/*
 * 更新时间文字显示
 * 横向任务栏显示格式(中文)：
 *      24小时制：
 *              hh:mm ddd
 *              yyyy/MM/dd
 *      12小时制：
 *              AM hh:mm ddd
 *              yyyy/MM/dd
 *
 * 纵向任务栏显示格式:
 *      24小时制：
 *              hh:mm        或   hh:mm
 *               ddd               ddd
 *              yyyy/MM/dd        MM/dd
 *      12小时制：
 *               AM                  AM
 *              hh:mm               hh:mm
 *               ddd          或     ddd
 *              yyyy/MM/dd          MM/dd
*/
QString CalendarButtonText::getBtnText()
{
    QString formatsLocale = getFormatsLocale();
    if(formatsLocale == ZH_CN_FORMATS) {
        return getZhCnBtnText();
    } else if(formatsLocale == US_FORMATS) {
        return getEnUsBtnText();
    } else {
        return getOtherBtnText();
    }
}

QString CalendarButtonText::getEnUsBtnText()
{
    QString amPmStr = getAmPm();
    QString timeStr = getTime();
    QString weekStr = getWeek();
    QString dataStr;
    QString btnTextStr;
    if(m_plugin->panel()->isHorizontal()) {
        dataStr = getDate(DateStyle::YEAR_MON_DAY);
        if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
            btnTextStr = timeStr + " " + amPmStr + " " + weekStr + "\n" + dataStr;
        } else {
            btnTextStr = timeStr + " " + weekStr + "\n" + dataStr;
        }
    } else {
        if(m_panelGsettings->get(PANEL_SIZE_KEY).toInt() < PANEL_SIZE_LARGE) {
            dataStr = getDate(DateStyle::MON_DAY);
        } else {
            dataStr = getDate(DateStyle::YEAR_MON_DAY);
        }

        if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
            btnTextStr = timeStr + "\n" + amPmStr  + "\n" + weekStr + "\n" + dataStr;
        } else {
            btnTextStr = timeStr + "\n" + weekStr + "\n" + dataStr;
        }
    }
    updateFontSize(btnTextStr);
    return btnTextStr;
}

QString CalendarButtonText::getZhCnBtnText()
{
    QString amPmStr = getAmPm();
    QString timeStr = getTime();
    QString weekStr = getWeek();
    QString dataStr;

    QString btnTextStr;
    if(m_plugin->panel()->isHorizontal()) {
        dataStr = getDate(DateStyle::YEAR_MON_DAY);
        if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
            btnTextStr = amPmStr + " " + timeStr + " " + weekStr + "\n" + dataStr;
        } else {
            btnTextStr = timeStr + " " + weekStr + "\n" + dataStr;
        }
    } else {
        if(m_panelGsettings->get(PANEL_SIZE_KEY).toInt() < PANEL_SIZE_LARGE) {
            dataStr = getDate(DateStyle::MON_DAY);
        } else {
            dataStr = getDate(DateStyle::YEAR_MON_DAY);
        }

        if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
            btnTextStr = amPmStr + "\n" + timeStr + "\n" + weekStr + "\n" + dataStr;
        } else {
            btnTextStr = timeStr + "\n" + weekStr + "\n" + dataStr;
        }
    }
    updateFontSize(btnTextStr);
    return btnTextStr;
}

QString CalendarButtonText::getOtherBtnText()
{
    QString amPmStr = getAmPm();
    QString timeStr = getTime();
    QString dataStr;

    QString btnTextStr;
    if(m_plugin->panel()->isHorizontal()) {
        dataStr = getDate(DateStyle::YEAR_MON_DAY);
        if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
            btnTextStr = amPmStr + " " + timeStr + "\n" + dataStr;
        } else {
            btnTextStr = timeStr + "\n" + dataStr;
        }
    } else {
        //任务栏纵向状态下，大尺寸以下均不显示year
        if(m_panelGsettings->get(PANEL_SIZE_KEY).toInt() < PANEL_SIZE_LARGE) {
            dataStr = getDate(DateStyle::MON_DAY);
        } else {
            dataStr = getDate(DateStyle::YEAR_MON_DAY);
        }
        if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
            btnTextStr = amPmStr + "\n" + timeStr + "\n" + dataStr;
        } else {
            btnTextStr = timeStr + "\n" + dataStr;
        }
    }
    updateFontSize(btnTextStr);
    return btnTextStr;
}

QString CalendarButtonText::getToolTipText()
{
    QString formatsLocale = getFormatsLocale();
    if(formatsLocale == ZH_CN_FORMATS) {
        return getZhCnToolTipText();
    } else if(formatsLocale == US_FORMATS) {
        return getEnUsToolTipText();
    } else if(formatsLocale == BO_CN_FORMATS) {
        return getBoCnToolTipText();
    } else {
        return getOtherToolTipText();
    }
}

//英语ToolTip格式：28 August 2023
QString CalendarButtonText::getEnUsToolTipText()
{
    QDateTime dataTime = QDateTime::currentDateTime();
    return QString(dataTime.toString("d")+" "
                   +dataTime.toString("MMMM")+" "
                   +dataTime.toString("yyyy"));
}

//中文ToolTip格式：2023年8月28日
QString CalendarButtonText::getZhCnToolTipText()
{
    QDateTime dataTime = QDateTime::currentDateTime();
    return QString(dataTime.toString("yyyy")+tr("year")+
                   dataTime.toString("M")+tr("month")+
                   dataTime.toString("d")+tr("day"));
}

//藏文ToolTip格式：2023年8月28日（藏文）
QString CalendarButtonText::getBoCnToolTipText()
{
    QDateTime dataTime = QDateTime::currentDateTime();
    return QString(dataTime.toString("yyyy")+tr("year")+
                   dataTime.toString("M")+tr("month")+
                   dataTime.toString("d")+tr("day"));
}

//其他语种ToolTip格式：28 August 2023
QString CalendarButtonText::getOtherToolTipText()
{
    QDateTime dataTime = QDateTime::currentDateTime();
    return QString(dataTime.toString("d")+" "
                   +dataTime.toString("MMMM")+" "
                   +dataTime.toString("yyyy"));
}

QString CalendarButtonText::getAmPm()
{
    QString time = m_dataTime.toString("A hh:mm");
    QStringList timeList = time.split(" ", QString::SkipEmptyParts);
    return timeList.first();
}

QString CalendarButtonText::getTime()
{
    QString time = m_dataTime.toString("A hh:mm");
    QStringList timeList = time.split(" ", QString::SkipEmptyParts);
    QString time12 = timeList.last();
    QString time24 = m_dataTime.toString("hh:mm");

    if(m_timeFormat && m_timeFormat->get(TIME_FORMAT).toString() == "12") {
        return time12;
    } else {
        return time24;
    }
}

QString CalendarButtonText::getWeek()
{
    QDBusInterface interface(UKUI_CONTROL_CENTER_SERVER,
                             UKUI_CONTROL_CENTER_PATH,
                             UKUI_CONTROL_CENTER_INTERFACE,
                             QDBusConnection::systemBus());
    QString language = interface.property(PROPERTIES_NAME).toString();
    if(language == US_FORMATS) {
        return m_dataTime.toString("ddd");
    } else if(language == ZH_CN_FORMATS) {
        return m_dataTime.toString("dddd");
    }
}

QString CalendarButtonText::getDate(DateStyle dateStyle)
{
    QString year = m_dataTime.toString("yyyy");
    QString mon = m_dataTime.toString("MM");
    QString day = m_dataTime.toString("dd");
    QString spacer = "/";
    if(m_timeFormat && m_timeFormat->get(DATA_FORMAT).toString() == "en") {
        spacer = "-";
    } else {
        spacer = "/";
    }
    if(dateStyle == DateStyle::YEAR_MON_DAY) {
        return year + spacer + mon + spacer + day;
    }
    else {
        return mon + spacer + day;
    }
}

void CalendarButtonText::updateFontSize(QString btnText)
{
    if (m_panelGsettings == nullptr) {
        qWarning()<<Q_FUNC_INFO<<__LINE__<<"gsettings init error!";
        return;
    }
    QStringList textList = btnText.split("\n", QString::SkipEmptyParts);

    int maxLength;
    if(m_plugin->panel()->isHorizontal()) {
        if(m_panelGsettings->get(PANEL_SIZE_KEY).toInt() < PANEL_SIZE_MEDIUM) {
            if (m_fontGsettings != nullptr) {
                QString systemFont = m_fontGsettings->get(SYSTEM_FONT).toString();
                m_parent->setFont(QFont(systemFont, SYSTEM_MIN_FONT));
            }
            return;
        }
        maxLength = CALENDAR_BUTTON_WIDTH;
        setOptimalFont(textList, maxLength);
    } else {
        int m_panelSize = m_panelGsettings->get(PANEL_SIZE_KEY).toInt();
        if(m_panelSize >= PANEL_SIZE_SMALL && m_panelSize < PANEL_SIZE_MEDIUM) {
            maxLength = PANEL_SIZE_SMALL;
        } else if(m_panelSize >= PANEL_SIZE_MEDIUM && m_panelSize < PANEL_SIZE_LARGE) {
            maxLength = PANEL_SIZE_MEDIUM;
        } else if(m_panelSize == PANEL_SIZE_LARGE) {
            maxLength = PANEL_SIZE_LARGE;
        } else {
            maxLength = PANEL_SIZE_SMALL;
        }
        setOptimalFont(textList, maxLength);
    }
}

//判断最长字体的是否可以显示下，选取最优字体大小显示
void CalendarButtonText::setOptimalFont(QStringList textList, int btnMaxLength)
{
    if (m_fontGsettings == nullptr) {
        qWarning()<<Q_FUNC_INFO<<__LINE__<<"gsettings init error!";
        return;
    }
    QString systemFont = m_fontGsettings->get(SYSTEM_FONT).toString();
    double fontSizeCurrent = m_fontGsettings->get(SYSTEM_FONT_SIZE).toDouble();
    QList<double> systemFonts;
    systemFonts<<10<<12<<13.5<<15;

    //获取最长的行
    QFontMetrics fontMetrics(QFont(systemFont, fontSizeCurrent));
    int fontWidth = fontMetrics.width(textList.first());
    int maxIndex = 0;
    for(int i=1; i<textList.size(); i++) {
        int width = fontMetrics.width(textList.at(i));
        if(width > fontWidth) {
            fontWidth = width;
            maxIndex = i;
        }
    }

    //判断最长字体的是否可以显示下，选取最优字体
    int maxFontWidth = fontMetrics.width(textList.at(maxIndex));
    if(maxFontWidth > btnMaxLength-INSIDE_SPAC) {
        int index = systemFonts.indexOf(fontSizeCurrent);
        if(index>0) {
            for(int i=index-1; i>=0; i--) {
                QFontMetrics fontMetrics(QFont(systemFont, systemFonts.at(i)));
                int width = fontMetrics.width(textList.at(maxIndex));
                if(width <= btnMaxLength-INSIDE_SPAC) {
                    m_parent->setFont(QFont(systemFont, systemFonts.at(i)));
                    break;
                }
            }
        } else {
            //容错处理，如果系统 org.ukui.style system-font-size 设置错误，也可保证日期正常显示不遮挡
            m_parent->setFont(QFont(systemFont, systemFonts.first()));
        }
    } else {
        m_parent->setFont(QFont(systemFont, fontSizeCurrent));
    }
}

QString CalendarButtonText::getFormatsLocale()
{
    QDBusInterface interface(UKUI_CONTROL_CENTER_SERVER,
                             UKUI_CONTROL_CENTER_PATH,
                             UKUI_CONTROL_CENTER_INTERFACE,
                             QDBusConnection::systemBus());
    QVariant ret = interface.property(PROPERTIES_NAME);
    return ret.toString();
}
