#include "etimer.h"
#include "tools.h"
#include "globaldefine.h"
#include "base/lodateselector.h"
#include "base/locolorselector.h"
#include <QBoxLayout>
#include <QLabel>
#include <QRadioButton>
#include <QCheckBox>
#include <QButtonGroup>
#include <QTextEdit>
#include <QDateTimeEdit>
#include <QFontComboBox>
#include <QSpinBox>
#include <QTextOption>
#include <QPainter>
#include <QJsonObject>
#include <QToolButton>

ETimer::ETimer(EBase *multiWin) : EBase(multiWin) {
    mType = EBase::Timer;
    attr.isDown = true;
    attr.targetTime = QDateTime::currentDateTime();
    attr.hasDay  = true;
    attr.hasHour = true;
    attr.hasMin  = true;
    attr.hasSec  = true;
    attr.isMultiline = true;
    attr.font = QFont("Arial", 9);
    attr.textColor = Qt::red;
    attr.backColor = Qt::transparent;
    attr.duration = 10;
    init();
}

ETimer::ETimer(const QJsonObject &json, EBase *multiWin) : EBase(multiWin){
    mType = EBase::Timer;
    setBaseAttr(json);
    attr.isDown = json["isDown"].toBool();
    attr.targetTime = QDateTime::fromString(json["targetTime"].toString(), "yyyy-MM-dd HH:mm:ss");
    attr.hasDay = json["hasDay"].toBool();
    attr.hasHour = json["hasHour"].toBool();
    attr.hasMin = json["hasMin"].toBool();
    attr.hasSec = json["hasSec"].toBool();
    attr.text = json["text"].toString();
    attr.isMultiline = json["isMultiline"].toBool();
    attr.font = QFont(json["font"].toString(), json["fontSize"].toInt());
    attr.font.setBold(json["fontBold"].toBool());
    attr.font.setItalic(json["fontItalic"].toBool());
    attr.font.setUnderline(json["fontUnderline"].toBool());
    attr.textColor = json["textColor"].toString();
    auto color = json["backColor"].toString();
    attr.backColor = color.isEmpty() ? QColor(0,0,0,0) : color;
    attr.duration = json["duration"].toInt();
    init();
}

void ETimer::init() {
    connect(Tools::getInstance(), &Tools::sTick, this, [this]() {
        QDateTime cDateTime = QDateTime::currentDateTime();
        qint64 ofs = attr.isDown ? cDateTime.secsTo(attr.targetTime) : attr.targetTime.secsTo(cDateTime);
        if(ofs < 0) ofs = 0;
        secs = ofs;
        update();
    });
}

void ETimer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
    QString text;
    if(!attr.text.isEmpty()) {
        text += attr.text;
        if(attr.isMultiline) text += '\n';
        else text += " ";
    }
    int secs = this->secs;
    if(attr.hasDay) {
        text.append(QString::number(secs/86400)).append(" ").append(tr("day")).append(" ");
        secs %= 86400;
    }
    if(attr.hasHour) {
        text.append(QString::asprintf("%02d ", secs/3600)).append(tr("hour")).append(" ");
        secs %= 3600;
    }
    if(attr.hasMin) {
        text.append(QString::asprintf("%02d ", secs/60)).append(tr("min")).append(" ");
        secs %= 60;
    }
    if(attr.hasSec) text.append(QString::asprintf("%02d ", secs)).append(tr("sec")).append(" ");
    text = text.trimmed();
    attr.font.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias);
    if(attr.backColor.alpha() != 0) painter->fillRect(0, 0, mWidth, mHeight, attr.backColor);
    painter->setFont(attr.font);
    painter->setPen(attr.textColor);
    painter->drawText(innerRect(), text, QTextOption(Qt::AlignCenter));
    EBase::paint(painter, option, widget);
}

QWidget* ETimer::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->addStretch();
    auto fdCntDown = new QRadioButton(tr("Count Down"));
    auto fdCntUp = new QRadioButton(tr("Count Up"));
    if(attr.isDown) fdCntDown->setChecked(true);
    else fdCntUp->setChecked(true);
    auto cntGroup = new QButtonGroup(wgtAttr);
    cntGroup->addButton(fdCntDown);
    cntGroup->addButton(fdCntUp);
    connect(fdCntDown, &QRadioButton::toggled, this, [this](bool checked) {
        attr.isDown = checked;
        update();
    });
    hBox->addWidget(fdCntDown);
    hBox->addStretch();
    hBox->addWidget(fdCntUp);
    hBox->addStretch();

    vBox->addLayout(hBox);

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

    auto fdTime = new QDateTimeEdit(attr.targetTime);
    fdTime->setDisplayFormat("yyyy-MM-dd HH:mm:ss");
    connect(fdTime, &QTimeEdit::dateTimeChanged, this, [this](const QDateTime &dateTime) {
        attr.targetTime = dateTime;
        update();
    });
    hBox->addWidget(fdTime);

    auto wDateSelector = new LoDateSelector();
    connect(wDateSelector, &LoDateSelector::sDateSelected, fdTime, &QDateTimeEdit::setDate);
    hBox->addWidget(wDateSelector);
    hBox->addStretch();

    vBox->addLayout(hBox);

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

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

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

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

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

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

    vBox->addLayout(hBox);

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

    auto fdText = new QTextEdit(attr.text);
    fdText->setMaximumHeight(50);
    connect(fdText, &QTextEdit::textChanged, this, [this, fdText]() {
        attr.text = fdText->toPlainText();
        update();
    });
    hBox->addWidget(fdText);

    vBox->addLayout(hBox);

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

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

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

    vBox->addLayout(hBox);

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

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

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

    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(attr.font.underline());
    connect(fdFontUnderline, &QCheckBox::toggled, this, [this](bool checked) {
        attr.font.setUnderline(checked);
        update();
    });
    hBox->addWidget(fdFontUnderline);
    hBox->addStretch();

    auto fdTextColor = new LoColorSelector("T", attr.textColor);
    fdTextColor->setFixedSize(30, 30);
    fdTextColor->setFlat(true);
    connect(fdTextColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) {
        attr.textColor = color;
        update();
    });
    hBox->addWidget(fdTextColor);

    auto fdBackColor = new LoColorSelector("B", attr.backColor);
    fdBackColor->setFixedSize(30, 30);
    fdBackColor->setFlat(true);
    connect(fdBackColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) {
        attr.backColor = color;
        update();
    });
    hBox->addWidget(fdBackColor);

    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(attr.duration);
    connect(fdDuration, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
        attr.duration = value;
    });
    hBox->addWidget(fdDuration);

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

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

QJsonObject ETimer::attrJson() const {
    QJsonObject obj;
    addBaseAttr(obj);
    obj["elementType"] = "Timer";
    obj["isDown"] = attr.isDown;
    obj["targetTime"] = attr.targetTime.toString("yyyy-MM-dd HH:mm:ss");
    obj["hasDay"] = attr.hasDay;
    obj["hasHour"] = attr.hasHour;
    obj["hasMin"] = attr.hasMin;
    obj["hasSec"] = attr.hasSec;
    obj["text"] = attr.text;
    obj["isMultiline"] = attr.isMultiline;
    obj["font"] = attr.font.family();
    obj["fontSize"] = attr.font.pixelSize();
    obj["fontBold"] = attr.font.bold();
    obj["fontItalic"] = attr.font.italic();
    obj["fontUnderline"] = attr.font.underline();
    obj["textColor"] = attr.textColor.name();
    obj["backColor"] = attr.backColor.alpha()==0 ? "" : attr.backColor.name();
    obj["duration"] = attr.duration;
    return obj;
}
