#include "edclock.h"
#include "base/locolorselector.h"
#include "globaldefine.h"
#include "tools.h"
#include <QBoxLayout>
#include <QCheckBox>
#include <QFontComboBox>
#include <QLabel>
#include <QSpinBox>
#include <QToolButton>

EDClock::EDClock(EBase *multiWin) : EBase(multiWin) {
    mType = EBase::DClock;
    m_attr.timeZoneId = QTimeZone::systemTimeZoneId();
    m_attr.font = QFont("Arial", 9);
    m_attr.year          = true;
    m_attr.month         = true;
    m_attr.day           = true;
    m_attr.hour          = true;
    m_attr.min           = true;
    m_attr.sec           = true;
    m_attr.weekly        = true;
    m_attr.fullYear      = true;
    m_attr.hour12        = true;
    m_attr.AmPm          = true;
    m_attr.dateStyle     = 0;
    m_attr.timeStyle     = 0;
    m_attr.multiline     = true;
    m_attr.textColor     = Qt::red;
    init();
}

EDClock::EDClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) {
    mType = EBase::DClock;
    setBaseAttr(json);
    auto widget = json["widget"];
    auto font = widget["font"];
    m_attr.font = QFont(font["family"].toString(), font["size"].toInt());
    m_attr.font.setBold(font["bold"].toBool());
    m_attr.font.setItalic(font["italics"].toBool());
    m_attr.font.setUnderline(font["underline"].toBool());
    m_attr.textColor = Tools::int2Color(font["color"].toInt());
    m_attr.timeZoneId    = widget["timeZone"].toString().toUtf8();
    m_attr.year          = widget["year"].toBool();
    m_attr.month         = widget["month"].toBool();
    m_attr.day           = widget["day"].toBool();
    m_attr.hour          = widget["hour"].toBool();
    m_attr.min           = widget["min"].toBool();
    m_attr.sec           = widget["sec"].toBool();
    m_attr.weekly        = widget["weekly"].toBool();
    m_attr.fullYear      = widget["fullYear"].toBool();
    m_attr.hour12        = widget["12Hour"].toBool();
    m_attr.AmPm          = widget["AmPm"].toBool();
    m_attr.dateStyle     = widget["dateStyle"].toInt();
    m_attr.timeStyle     = widget["timeStyle"].toInt();
    m_attr.multiline     = widget["multiline"].toBool();
    m_attr.playDuration  = json["play"]["duration"].toInt();
    isSingleMD = m_attr.dateStyle==1||m_attr.dateStyle==2||m_attr.dateStyle==4||m_attr.dateStyle==6||m_attr.dateStyle==8||m_attr.dateStyle==10||m_attr.dateStyle==12;
    init();
}

void EDClock::init() {
    connect(Tools::getInstance(), &Tools::sTick, this, [this]() {
        datetime = QDateTime::currentDateTime().toTimeZone(QTimeZone(m_attr.timeZoneId));
        update();
    });
}

void EDClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
    QString text;
    QDate date = datetime.date();
    QTime time = datetime.time();
    QString spacer = m_attr.multiline ? "\n" : "  ";
    QString yearFmt = m_attr.fullYear ? "yyyy" : "yy";
    QString monthFmt = isSingleMD ? "M" : "MM";
    QString dateFmt = isSingleMD ? "d" : "dd";
    QString sep;
    if(m_attr.dateStyle > 7) sep = "-";
    else if(m_attr.dateStyle > 1) sep = "/";
    switch(m_attr.dateStyle) {
    case 0: case 1:
        if(m_attr.year) text += date.toString(yearFmt) + "年";
        if(m_attr.month) text += date.toString(monthFmt) + "月";
        if(m_attr.day) text += date.toString(dateFmt) + "日";
        break;
    case 2: case 3: case 8: case 9:
        if(m_attr.month) text += date.toString(monthFmt) + sep;
        if(m_attr.day) text += date.toString(dateFmt) + sep;
        if(m_attr.year) text += date.toString(yearFmt);
        if(text.endsWith(sep)) text.chop(1);
        break;
    case 4: case 5: case 10: case 11:
        if(m_attr.day) text += date.toString(dateFmt) + sep;
        if(m_attr.month) text += date.toString(monthFmt) + sep;
        if(m_attr.year) text += date.toString(yearFmt);
        if(text.endsWith(sep)) text.chop(1);
        break;
    case 6: case 7: case 12: case 13:
        if(m_attr.year) text += date.toString(yearFmt) + sep;
        if(m_attr.month) text += date.toString(monthFmt) + sep;
        if(m_attr.day) text += date.toString(dateFmt);
        if(text.endsWith(sep)) text.chop(1);
        break;
    default:
        break;
    }
    if(! text.isEmpty()) text += spacer;

    if(m_attr.weekly) {
        auto dayOfWeek = date.dayOfWeek();
        if(dayOfWeek==1) text += tr("MON");
        else if(dayOfWeek==2) text += tr("TUE");
        else if(dayOfWeek==3) text += tr("WED");
        else if(dayOfWeek==4) text += tr("THU");
        else if(dayOfWeek==5) text += tr("FRI");
        else if(dayOfWeek==6) text += tr("SAT");
        else if(dayOfWeek==7) text += tr("SUN");
        text += spacer;
    }
    QString timeFmt;
    if(m_attr.hour12 && m_attr.AmPm) timeFmt += (time.hour()<12 ? tr("AM") : tr("PM")) + " ";
    if(m_attr.hour) timeFmt += (m_attr.timeStyle!=1 ? "hh:" : "h:");
    if(m_attr.min) timeFmt += "mm:";
    if(m_attr.sec) timeFmt += "ss";
    if(timeFmt.endsWith(":")) timeFmt.chop(1);
    if(! timeFmt.isEmpty()) text += time.toString(timeFmt);
    text = text.trimmed();
    painter->save();
    painter->setPen(m_attr.textColor);
    m_attr.font.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias);
    painter->setFont(m_attr.font);
    painter->drawText(innerRect(), text, QTextOption(Qt::AlignCenter));
    painter->restore();
    EBase::paint(painter, option, widget);
}

QWidget* EDClock::attrWgt() {
    auto wgtAttr = new QWidget();
    auto vBox = new QVBoxLayout(wgtAttr);
    vBox->setContentsMargins(6, 0, 6, 0);
    if(mMultiWin!=nullptr) vBox->setSpacing(3);

    addBaseAttrWgt(vBox);

    auto hBox = new QHBoxLayout();
    hBox->addWidget(new QLabel(tr("Basic Properties")));

    auto line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    hBox->addWidget(line, 1);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Time Zone")));

    auto wTimeZone = new QComboBox();
    auto zoneIds = QTimeZone::availableTimeZoneIds();
    foreach(QByteArray zoneId, zoneIds) wTimeZone->addItem(QString::fromUtf8(zoneId));
    wTimeZone->setCurrentText(QString::fromUtf8(m_attr.timeZoneId));
    connect(wTimeZone, &QComboBox::currentTextChanged, this, [this](const QString &text) {
        m_attr.timeZoneId = text.toUtf8();
        update();
    });
    hBox->addWidget(wTimeZone);
    hBox->addStretch();

    vBox->addLayout(hBox);

    line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);

    vBox->addWidget(line);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);

    auto fdYear = new QCheckBox(tr("Year"));
    fdYear->setChecked(m_attr.year);
    connect(fdYear, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.year = checked;
        update();
    });
    hBox->addWidget(fdYear);

    auto fdMonth = new QCheckBox(tr("Month"));
    fdMonth->setChecked(m_attr.month);
    connect(fdMonth, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.month = checked;
        update();
    });
    hBox->addWidget(fdMonth);

    auto fdDay = new QCheckBox(tr("Day"));
    fdDay->setChecked(m_attr.day);
    connect(fdDay, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.day = checked;
        update();
    });
    hBox->addWidget(fdDay);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);

    auto fdHour = new QCheckBox(tr("Hour"));
    fdHour->setChecked(m_attr.hour);
    connect(fdHour, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.hour = checked;
        update();
    });
    hBox->addWidget(fdHour);

    auto fdMin = new QCheckBox(tr("Min."));
    fdMin->setChecked(m_attr.min);
    connect(fdMin, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.min = checked;
        update();
    });
    hBox->addWidget(fdMin);

    auto fdSec = new QCheckBox(tr("Sec."));
    fdSec->setChecked(m_attr.sec);
    connect(fdSec, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.sec = checked;
        update();
    });
    hBox->addWidget(fdSec);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    auto fdHasWeek = new QCheckBox(tr("Weekly"));
    fdHasWeek->setChecked(m_attr.weekly);
    connect(fdHasWeek, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.weekly = checked;
        update();
    });
    hBox->addWidget(fdHasWeek);

    auto fdFullYear = new QCheckBox(tr("Full Year"));
    fdFullYear->setChecked(m_attr.fullYear);
    connect(fdFullYear, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.fullYear = checked;
        update();
    });
    hBox->addWidget(fdFullYear);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);

    auto fdIs12Hour = new QCheckBox(tr("12-Hour"));
    fdIs12Hour->setChecked(m_attr.hour12);
    hBox->addWidget(fdIs12Hour);

    auto fdAmPm = new QCheckBox(tr("AM")+"/"+tr("PM"));
    fdAmPm->setChecked(m_attr.AmPm);
    connect(fdIs12Hour, &QCheckBox::toggled, this, [this, fdAmPm](bool checked) {
        m_attr.hour12 = checked;
        fdAmPm->setVisible(checked);
        if(! checked) fdAmPm->setChecked(false);
        update();
    });
    connect(fdAmPm, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.AmPm = checked;
        update();
    });
    hBox->addWidget(fdAmPm);

    vBox->addLayout(hBox);

    line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    vBox->addWidget(line);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Date Style")));

    auto fdDateFmt = new QComboBox();
    fdDateFmt->addItem("1955年02月04日");
    fdDateFmt->addItem("1955年2月4日");
    fdDateFmt->addItem("2/24/1955");
    fdDateFmt->addItem("02/24/1955");
    fdDateFmt->addItem("24/2/1955");
    fdDateFmt->addItem("24/02/1955");
    fdDateFmt->addItem("1955/2/24");
    fdDateFmt->addItem("1955/02/24");
    fdDateFmt->addItem("2-24-1955");
    fdDateFmt->addItem("02-24-1955");
    fdDateFmt->addItem("24-2-1955");
    fdDateFmt->addItem("24-02-1955");
    fdDateFmt->addItem("1955-2-24");
    fdDateFmt->addItem("1955-02-24");
    fdDateFmt->setCurrentIndex(m_attr.dateStyle);
    connect(fdDateFmt, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) {
        m_attr.dateStyle = index;
        isSingleMD = index==1||index==2||index==4||index==6||index==8||index==10||index==12;
        update();
    });
    hBox->addWidget(fdDateFmt);
    hBox->addStretch();

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Time Style")));

    auto fdTimeFmt = new QComboBox();
    fdTimeFmt->addItem("HH:MM:SS");
    fdTimeFmt->addItem("H:MM:SS");
    fdTimeFmt->setCurrentIndex(m_attr.timeStyle);
    connect(fdTimeFmt, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) {
        m_attr.timeStyle = index;
        update();
    });
    hBox->addWidget(fdTimeFmt);
    hBox->addStretch();

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Display Style")));

    auto fdIsMultiline = new QCheckBox(tr("Multiline"));
    fdIsMultiline->setChecked(m_attr.multiline);
    connect(fdIsMultiline, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.multiline = checked;
        update();
    });
    hBox->addWidget(fdIsMultiline);
    hBox->addStretch();

    vBox->addLayout(hBox);

    line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    vBox->addWidget(line);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);

    auto fdFontFamily = new QFontComboBox();
    fdFontFamily->setEditable(false);
    fdFontFamily->setCurrentText(m_attr.font.family());
    connect(fdFontFamily, &QFontComboBox::currentFontChanged, this, [this](const QFont &f) {
        QFont font(f.family());
        font.setPixelSize(m_attr.font.pixelSize());
        font.setBold(m_attr.font.bold());
        font.setItalic(m_attr.font.italic());
        font.setUnderline(m_attr.font.underline());
        m_attr.font = font;
        update();
    });
    hBox->addWidget(fdFontFamily);

    auto fdFontSize = new QSpinBox();
    fdFontSize->setRange(4, 9999);
    fdFontSize->setValue(m_attr.font.pixelSize());
    connect(fdFontSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
        m_attr.font.setPixelSize(value);
        update();
    });
    hBox->addWidget(fdFontSize);
    hBox->addStretch();

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);

    auto fdBold = new QPushButton("B");
    fdBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}");
    fdBold->setFixedSize(30, 30);
    fdBold->setCheckable(true);
    fdBold->setChecked(m_attr.font.bold());
    connect(fdBold, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.font.setBold(checked);
        update();
    });
    hBox->addWidget(fdBold);

    auto fdItalic = new QPushButton("I");
    fdItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}");
    fdItalic->setFixedSize(30, 30);
    fdItalic->setCheckable(true);
    fdItalic->setChecked(m_attr.font.italic());
    connect(fdItalic, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.font.setItalic(checked);
        update();
    });
    hBox->addWidget(fdItalic);

    auto fdFontUnderline = new QPushButton("U");
    fdFontUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}");
    fdFontUnderline->setFixedSize(30, 30);
    fdFontUnderline->setCheckable(true);
    fdFontUnderline->setChecked(m_attr.font.underline());
    connect(fdFontUnderline, &QCheckBox::toggled, this, [this](bool checked) {
        m_attr.font.setUnderline(checked);
        update();
    });
    hBox->addWidget(fdFontUnderline);

    auto fdColor = new LoColorSelector("T", m_attr.textColor);
    fdColor->setFixedWidth(30);
    connect(fdColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) {
        m_attr.textColor = color;
        update();
    });
    hBox->addWidget(fdColor);
    hBox->addStretch();

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addWidget(new QLabel(tr("Play Properties")));

    line = new QFrame();
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    hBox->addWidget(line, 1);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout();
    hBox->addSpacing(6);
    hBox->addWidget(new QLabel(tr("Play Duration")));

    auto fdDuration = new QSpinBox();
    fdDuration->setRange(1, 99999);
    fdDuration->setValue(m_attr.playDuration);
    connect(fdDuration, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
        m_attr.playDuration = value;
    });
    hBox->addWidget(fdDuration);

    hBox->addWidget(new QLabel(tr("s")));
    hBox->addStretch();

    vBox->addLayout(hBox);
    vBox->addStretch();
    return wgtAttr;
}

QJsonObject EDClock::attrJson() const{
    QJsonObject oWidget;
    oWidget["timeZone"] = QString::fromUtf8(m_attr.timeZoneId);
    oWidget["year"]   = m_attr.year;
    oWidget["month"]  = m_attr.month;
    oWidget["day"]    = m_attr.day;
    oWidget["hour"]   = m_attr.hour;
    oWidget["min"]    = m_attr.min;
    oWidget["sec"]    = m_attr.sec;
    oWidget["weekly"] = m_attr.weekly;
    oWidget["fullYear"] = m_attr.fullYear;
    oWidget["12Hour"] = m_attr.hour12;
    oWidget["AmPm"] = m_attr.AmPm;
    oWidget["dateStyle"] = m_attr.dateStyle;
    oWidget["timeStyle"] = m_attr.timeStyle;
    oWidget["multiline"] = m_attr.multiline;
    oWidget["font"] = QJsonObject{
        {"family", m_attr.font.family()},
        {"size", m_attr.font.pixelSize()},
        {"bold", m_attr.font.bold()},
        {"italics", m_attr.font.italic()},
        {"underline", m_attr.font.underline()},
        {"color", Tools::color2Int(m_attr.textColor)}
    };
    QJsonObject oRoot;
    addBaseAttr(oRoot);
    oRoot["elementType"] = "DClock";
    oRoot["widget"] = oWidget;
    oRoot["play"] = QJsonObject{{"duration", m_attr.playDuration}};
    return oRoot;
}
