#include "base/locolorselector.h"
#include "cfg.h"
#include "etext.h"
#include "globaldefine.h"
#include "tools.h"
#include <QBoxLayout>
#include <QButtonGroup>
#include <QFontComboBox>
#include <QJsonArray>
#include <QMessageBox>
#include <QRadioButton>
#include <QSpinBox>
#include <QStackedLayout>
#include <QTextBlock>
#include <QTextCodec>
#include <QTimeEdit>
#include <QToolButton>

static QColor charColors[]{"#fff","#f00","#f00","#f0f","#c0c","#ff0","#f80","#0f0","#0f0","#0a0","#0a0","#7b0","#00f","#00f","#0af","#0ef"};

EText::EText(EBase *multiWin) : EBase(multiWin) {
    mType = EBase::Text;
    m_attr.text = "<body>"+tr("Enter your text")+"</body>";
    connect(this, &EText::sizeChanged, this, &EText::updImg);
    updImg();
}
EText::EText(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) {
    mType = EBase::Text;
    setBaseAttr(json);
    setElement(json, m_attr);
    connect(this, &EText::sizeChanged, this, &EText::updImg);
    updImg();
}

void EText::setElement(const QJsonObject &json, Data &attr) {
    auto widget = json["widget"];
    attr.text = widget["text"].toString();
    attr.align = static_cast<Qt::Alignment>(widget["align"].toInt());
    auto backColor = widget["backColor"].toString();
    attr.backColor = backColor.isEmpty() ? QColor(0,0,0,0) : QColor(backColor);
    auto play = json["play"];
    attr.playMode = play["style"].toInt();
    auto turning = play["turning"];
    attr.flip.effect = turning["strEffect"].toString();
    attr.flip.pageDuration = turning["iEffectTime"].toInt();
    attr.flip.effectDuration = turning["iEffectSpeed"].toInt();
    auto rolling = play["rolling"];
    attr.scroll.effect = rolling["rollingStyle"].toInt();
    attr.scroll.effectSpeed = rolling["rollingSpeed"].toInt();
    attr.scroll.headTailSpacing = rolling["headTailSpacing"].toInt();
    attr.scroll.duration = rolling["playDuration"].toInt();
    attr.duration = play["static"]["playDuration"].toInt();
}

class TTextEdit : public QTextEdit {
public:
    TTextEdit() {}
    explicit TTextEdit(const QString &text) : QTextEdit(text){}
    QSize minimumSizeHint() const override {
        return sizeHint();
    };
    QSize sizeHint() const override {
        auto size = QTextEdit::sizeHint();
        auto minH = minimumHeight();
        if(minH > 0) size.setHeight(minH+0xfff);
        return size;
    };
};
QWidget* EText::attrWgt() {
    auto wgtAttr = new QWidget;
    auto vBox = new QVBoxLayout(wgtAttr);
    vBox->setContentsMargins(4, 0, 4, 0);
    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;

    auto fdText = new TTextEdit("");

    auto fdFontFamily = new QFontComboBox;
    fdFontFamily->setEditable(false);
    fdFontFamily->setCurrentFont(QFont("黑体"));
    connect(fdFontFamily, &QFontComboBox::currentFontChanged, fdText, [fdText](const QFont &f) {
        QTextCharFormat fmt;
        fmt.setFontFamilies({f.family()});
        QTextCursor cursor = fdText->textCursor();
        if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
        cursor.mergeCharFormat(fmt);
    });
    hBox->addWidget(fdFontFamily);

    hBox->addStretch();

    auto fdFontSize = new QSpinBox;
    fdFontSize->setRange(4, 9999);
    fdFontSize->setValue(16);
    connect(fdFontSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, fdText, [fdText](int value) {
        if(value <= 0) return;
        QTextCharFormat fmt;
        fmt.setProperty(QTextFormat::FontPixelSize, value);
        QTextCursor cursor = fdText->textCursor();
        if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
        cursor.mergeCharFormat(fmt);
    });
    hBox->addWidget(fdFontSize);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout;
    hBox->setSpacing(3);

    auto wTextAlignHL = new QPushButton(QIcon(":/res/program/TextAlignHL.png"), "");
    wTextAlignHL->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
    wTextAlignHL->setFixedSize(30, 30);
    wTextAlignHL->setIconSize(QSize(30, 30));
    wTextAlignHL->setCheckable(true);
    wTextAlignHL->setChecked(true);
    hBox->addWidget(wTextAlignHL);

    auto wTextAlignHC = new QPushButton(QIcon(":/res/program/TextAlignHC.png"), "");
    wTextAlignHC->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
    wTextAlignHC->setFixedSize(30, 30);
    wTextAlignHC->setIconSize(QSize(30, 30));
    wTextAlignHC->setCheckable(true);
    hBox->addWidget(wTextAlignHC);

    auto wTextAlignHR = new QPushButton(QIcon(":/res/program/TextAlignHR.png"), "");
    wTextAlignHR->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
    wTextAlignHR->setFixedSize(30, 30);
    wTextAlignHR->setIconSize(QSize(30, 30));
    wTextAlignHR->setCheckable(true);
    hBox->addWidget(wTextAlignHR);

    hBox->addStretch();

    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);
    connect(fdFontBold, &QToolButton::toggled, fdText, [fdText](bool checked) {
        QTextCharFormat fmt;
        fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
        Tools::mergeFormat(fdText, fmt);
    });
    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);
    connect(fdFontItalic, &QToolButton::toggled, fdText, [fdText](bool checked) {
        QTextCharFormat fmt;
        fmt.setFontItalic(checked);
        Tools::mergeFormat(fdText, fmt);
    });
    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);
    connect(fdFontUnderline, &QToolButton::toggled, fdText, [fdText](bool checked) {
        QTextCharFormat fmt;
        fmt.setFontUnderline(checked);
        Tools::mergeFormat(fdText, fmt);
    });
    hBox->addWidget(fdFontUnderline);

    hBox->addStretch();

    auto fdTextColor = new LoColorSelector("T", Qt::white);
    fdTextColor->setToolTip(tr("Text Color"));
    fdTextColor->setFixedSize(30, 30);
    connect(fdTextColor, &LoColorSelector::sColorChanged, fdText, [fdText](const QColor &color) {
        if(! color.isValid()) return;
        QTextCharFormat fmt;
        fmt.setForeground(color);
        Tools::mergeFormat(fdText, fmt);
    });
    hBox->addWidget(fdTextColor);

    auto fdBackColor = new LoColorSelector("B", m_attr.backColor);
    fdBackColor->setToolTip(tr("Back Color"));
    fdBackColor->setFixedSize(30, 30);
    connect(fdBackColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) {
        if(! color.isValid()) return;
        m_attr.backColor = color;
        updImg();
    });
    hBox->addWidget(fdBackColor);

    auto fdRandomColor = new QPushButton(QIcon(":/res/random.png"), "");
    fdRandomColor->setToolTip(tr("Colorful Text"));
    fdRandomColor->setFixedSize(30, 30);
    fdRandomColor->setIconSize(QSize(30, 30));
    connect(fdRandomColor, &QPushButton::clicked, fdText, [fdText] {
        auto cursor = fdText->textCursor();
        auto len = fdText->document()->characterCount();
        QTextCharFormat fmt;
        int last = -1, idx;
        for(int i=0; i<len; i++) {
            cursor.setPosition(i, QTextCursor::MoveAnchor);
            cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
            while((idx = rand()%(sizeof(charColors)/sizeof(charColors[0])))==last) ;
            last = idx;
            fmt.setForeground(charColors[idx]);
            cursor.mergeCharFormat(fmt);
        }
    });
    hBox->addWidget(fdRandomColor);

    vBox->addLayout(hBox);

    hBox = new QHBoxLayout;
    hBox->setSpacing(3);

    auto wTextAlignVT = new QPushButton(QIcon(":/res/program/TextAlignVT.png"), "");
    wTextAlignVT->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
    wTextAlignVT->setFixedSize(30, 30);
    wTextAlignVT->setIconSize(QSize(30, 30));
    wTextAlignVT->setCheckable(true);
    hBox->addWidget(wTextAlignVT);

    auto wTextAlignVC = new QPushButton(QIcon(":/res/program/TextAlignVC.png"), "");
    wTextAlignVC->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
    wTextAlignVC->setFixedSize(30, 30);
    wTextAlignVC->setIconSize(QSize(30, 30));
    wTextAlignVC->setCheckable(true);
    hBox->addWidget(wTextAlignVC);

    auto wTextAlignVB = new QPushButton(QIcon(":/res/program/TextAlignVB.png"), "");
    wTextAlignVB->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
    wTextAlignVB->setFixedSize(30, 30);
    wTextAlignVB->setIconSize(QSize(30, 30));
    wTextAlignVB->setCheckable(true);
    hBox->addWidget(wTextAlignVB);

    hBox->addStretch();

    auto lb = new QLabel(tr("Kerning"));
    lb->setToolTip(lb->text());
    hBox->addWidget(lb);

    auto fdLetterSpacing = new QSpinBox();
    fdLetterSpacing->setMaximum(999);
    connect(fdLetterSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdText](int value) {
        QTextCharFormat fmt;
        fmt.setFontLetterSpacing(value);
        QTextCursor cursor = fdText->textCursor();
        if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
        cursor.mergeCharFormat(fmt);
        updImg();
    });
    hBox->addWidget(fdLetterSpacing);

    lb = new QLabel(tr("Line Spacing"));
    lb->setToolTip(lb->text());
    hBox->addWidget(lb);

    auto fdLineSpacing = new QSpinBox();
    fdLineSpacing->setRange(-99, 999);
    connect(fdLineSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdText](int value) {
        QTextBlockFormat fmt;
        fmt.setLineHeight(value, QTextBlockFormat::LineDistanceHeight);
        QTextCursor cursor = fdText->textCursor();
        if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
        cursor.mergeBlockFormat(fmt);
        updImg();
    });
    hBox->addWidget(fdLineSpacing);

    vBox->addLayout(hBox);

    auto wTextAlignH = new QButtonGroup(wgtAttr);
    wTextAlignH->addButton(wTextAlignHL, Qt::AlignLeft);
    wTextAlignH->addButton(wTextAlignHC, Qt::AlignHCenter);
    wTextAlignH->addButton(wTextAlignHR, Qt::AlignRight);
    connect(wTextAlignH, &QButtonGroup::idClicked, this, [this, fdText](int value) {
        QTextBlockFormat fmt;
        fmt.setAlignment((Qt::Alignment) value);
        QTextCursor cursor = fdText->textCursor();
        cursor.mergeBlockFormat(fmt);
        updImg();
    });

    auto wTextAlignV = new QButtonGroup(wgtAttr);
    wTextAlignV->addButton(wTextAlignVT, Qt::AlignTop);
    wTextAlignV->addButton(wTextAlignVC, Qt::AlignVCenter);
    wTextAlignV->addButton(wTextAlignVB, Qt::AlignBottom);
    connect(wTextAlignV, &QButtonGroup::idClicked, this, [this](int value) {
        m_attr.align = (Qt::Alignment) value;
        updImg();
    });

    auto v_align = m_attr.align & Qt::AlignVertical_Mask;
    if(v_align==Qt::AlignTop) wTextAlignVT->setChecked(true);
    if(v_align==Qt::AlignVCenter) wTextAlignVC->setChecked(true);
    if(v_align==Qt::AlignBottom) wTextAlignVB->setChecked(true);

    fdText->setMinimumHeight(160);
    auto doc = fdText->document();
    if(doc) doc->setDocumentMargin(2);
    auto font = fdText->font();
    font.setFamilies({"Arial","黑体"});
    font.setPixelSize(16);
    if(! gTextAntialiasing) font.setStyleStrategy(QFont::NoAntialias);
    fdText->setFont(font);
    auto pal = fdText->palette();
    pal.setColor(QPalette::Base, Qt::black);
    pal.setColor(QPalette::Text, Qt::white);
    fdText->setPalette(pal);
    fdText->setFrameShape(QFrame::NoFrame);
    fdText->setAcceptRichText(false);
    fdText->setHtml(m_attr.text);
    connect(fdText, &QTextEdit::textChanged, this, [this, fdText] {
        m_attr.text = fdText->toHtml();
        updImg();
    });
    vBox->addWidget(fdText);

    hBox = new QHBoxLayout;
    hBox->addStretch();

    auto pageInfoWgt = new QWidget;
    auto hhh = new QHBoxLayout(pageInfoWgt);
    hhh->setContentsMargins(0,0,0,0);

    hhh->addWidget(new QLabel(tr("PageCount:")));

    auto fdPageCnt = new QLabel(QString::number(mImgs.size()));
    hhh->addWidget(fdPageCnt);

    hhh->addSpacing(20);
    hhh->addWidget(new QLabel(tr("page")));

    auto fdPageIdx = new QSpinBox();
    fdPageIdx->setRange(1, mImgs.size());
    connect(fdPageIdx, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int idx) {
        curIdx = idx - 1;
        update();
    });
    hhh->addWidget(fdPageIdx);
    hBox->addWidget(pageInfoWgt);

    hBox->addStretch();

    auto btnImport = new QPushButton(tr("Import txt File"));
    btnImport->setProperty("ssType", "progManageTool");
    connect(btnImport, &QPushButton::clicked, fdText, [fdText] {
        auto filePath = QFileDialog::getOpenFileName(gMainWin, tr("Select File"), gFileHome, "Txt(*.txt)");
        if(filePath.isEmpty()) return;
        QFile file(filePath);
        if(! file.open(QFile::ReadOnly)) {
            QMessageBox::critical(gMainWin, tr("Fail"), tr("File Open Fail"));
            return;
        }
        auto data = file.readAll();
        file.close();
        QTextCodec::ConverterState state;
        QString text = QTextCodec::codecForName("UTF-8")->toUnicode(data.constData(), data.size(), &state);
        if(state.invalidChars > 0) text = QString::fromLocal8Bit(data);
        fdText->setText(text);
    });
    hBox->addWidget(btnImport);

    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->addStretch();

    auto fdFlip = new QRadioButton(tr("Flip"));
    hBox->addWidget(fdFlip);
    hBox->addStretch();

    auto fdScroll = new QRadioButton(tr("Scroll"));
    hBox->addWidget(fdScroll);
    hBox->addStretch();

    auto fdStatic = new QRadioButton(tr("Static"));
    hBox->addWidget(fdStatic);
    hBox->addStretch();

    vBox->addLayout(hBox);

    auto fdPlayStyle = new QButtonGroup(wgtAttr);
    fdPlayStyle->addButton(fdFlip, EText::Flip);
    fdPlayStyle->addButton(fdScroll, EText::Scroll);
    fdPlayStyle->addButton(fdStatic, EText::Static);
    if(m_attr.playMode==EText::Flip) fdFlip->setChecked(true);
    else if(m_attr.playMode==EText::Scroll) fdScroll->setChecked(true);
    else if(m_attr.playMode==EText::Static) fdStatic->setChecked(true);

    auto wgtAttrFlip = new QWidget();
    auto fdDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.flip.pageDuration * mImgs.size() * 1000));
    auto fdPageDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.flip.pageDuration * 1000));
    {
        auto vBox = new QVBoxLayout(wgtAttrFlip);
        vBox->setContentsMargins(2, 0, 2, 0);
        vBox->setSpacing(3);

        hBox = new QHBoxLayout;

        auto label = new QLabel(tr("Play Duration"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        fdDur->setReadOnly(true);
        fdDur->setButtonSymbols(QAbstractSpinBox::NoButtons);
        fdDur->setDisplayFormat("H:mm:ss");
        fdDur->setStyleSheet("QTimeEdit{background-color:#ddd;}");
        hBox->addWidget(fdDur);
        hBox->addStretch();

        vBox->addLayout(hBox);

        hBox = new QHBoxLayout();

        label = new QLabel(tr("Duration/Page"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        fdPageDur->setDisplayFormat("H:mm:ss");
        fdPageDur->setCurrentSection(QTimeEdit::SecondSection);
        hBox->addWidget(fdPageDur);
        hBox->addStretch();

        vBox->addLayout(hBox);

        hBox = new QHBoxLayout();

        label = new QLabel(tr("Entrance Effect"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto fdEff = new QComboBox();
        fdEff->addItem(tr("no"), "no");
        fdEff->addItem(tr("random"), "random");
        fdEff->addItem(tr("right to left"), "right to left");
        fdEff->addItem(tr("bottom to top"), "bottom to top");
        fdEff->addItem(tr("left to right"), "left to right");
        fdEff->addItem(tr("top to bottom"), "top to bottom");
        int idx = fdEff->findData(m_attr.flip.effect);
        if(idx!=-1) fdEff->setCurrentIndex(idx);
        connect(fdEff, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this, fdEff] {
            m_attr.flip.effect = fdEff->currentData().toString();
            update();
        });
        hBox->addWidget(fdEff);
        hBox->addStretch();

        vBox->addLayout(hBox);

        hBox = new QHBoxLayout();

        label = new QLabel(tr("Effect time"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto wEffectSpeed = new QSpinBox();
        wEffectSpeed->setValue(m_attr.flip.effectDuration);
        hBox->addWidget(wEffectSpeed);
        hBox->addWidget(new QLabel(tr("s")));
        hBox->addStretch();

        vBox->addLayout(hBox);
        vBox->addStretch();

        connect(fdPageDur, &QTimeEdit::timeChanged, this, [this, wEffectSpeed, fdPageDur, fdDur](const QTime &time) {
            int effDur = wEffectSpeed->value();
            int pageDur = time.msecsSinceStartOfDay()/1000;
            if(pageDur < effDur) {
                QMessageBox::warning(gMainWin, tr("Tip Info"), tr("Effect time cannot be longer than duration time"));
                pageDur = effDur;
                fdPageDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur*1000));
                fdPageDur->setFocus();
            }
            m_attr.flip.pageDuration = pageDur;
            fdDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur * mImgs.size() * 1000));
        });
        connect(wEffectSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, wEffectSpeed, fdPageDur](int value) {
            int pageDur = fdPageDur->time().msecsSinceStartOfDay()/1000;
            if(value > pageDur) {
                QMessageBox::warning(gMainWin, tr("Tip Info"), tr("Effect time cannot be longer than duration time"));
                if(pageDur>1) value = pageDur-1;
                else value = 0;
                wEffectSpeed->setValue(value);
                wEffectSpeed->setFocus();
            }
            m_attr.flip.effectDuration = value;
        });
    }
    auto wgtAttrScroll = new QWidget();
    {
        auto vBox = new QVBoxLayout(wgtAttrScroll);
        vBox->setContentsMargins(2, 0, 2, 0);
        vBox->setSpacing(3);

        auto hBox = new QHBoxLayout();

        auto label = new QLabel(tr("Play Duration"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.scroll.duration*1000));
        timeEdit->setDisplayFormat("H:mm:ss");
        timeEdit->setCurrentSectionIndex(2);
        connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) {
            m_attr.scroll.duration = time.msecsSinceStartOfDay()/1000;
        });
        hBox->addWidget(timeEdit);
        hBox->addStretch();

        vBox->addLayout(hBox);

        hBox = new QHBoxLayout();

        label = new QLabel(tr("Head-Tail Spacing"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto wHeadTailSpacing = new QSpinBox;
        wHeadTailSpacing->setRange(0, 9999);
        wHeadTailSpacing->setValue(m_attr.scroll.headTailSpacing);
        connect(wHeadTailSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
            m_attr.scroll.headTailSpacing = value;
        });
        hBox->addWidget(wHeadTailSpacing);
        hBox->addStretch();

        vBox->addLayout(hBox);

        hBox = new QHBoxLayout();

        label = new QLabel(tr("Scroll Style"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto wRollingStyle = new QComboBox;
        wRollingStyle->addItem(tr("Right -> Left"));
        wRollingStyle->addItem(tr("Bottom -> Top"));
        wRollingStyle->addItem(tr("Left -> Right"));
        wRollingStyle->addItem(tr("Top -> Bottom"));
        wRollingStyle->setCurrentIndex(m_attr.scroll.effect);
        connect(wRollingStyle, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) {
            m_attr.scroll.effect  = index;
            updImg();
        });
        hBox->addWidget(wRollingStyle);
        hBox->addStretch();

        vBox->addLayout(hBox);

        hBox = new QHBoxLayout();

        label = new QLabel(tr("Scroll Speed"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto wRollingSpeed = new QSpinBox();
        wRollingSpeed->setMaximum(9999);
        wRollingSpeed->setValue(m_attr.scroll.effectSpeed);
        connect(wRollingSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
            m_attr.scroll.effectSpeed = value;
        });
        hBox->addWidget(wRollingSpeed);
        hBox->addStretch();

        vBox->addLayout(hBox);
        vBox->addStretch();
    }
    auto wgtAttrStatic = new QWidget();
    {
        auto vBox = new QVBoxLayout(wgtAttrStatic);
        vBox->setContentsMargins(2, 0, 2, 0);
        vBox->setSpacing(3);

        hBox = new QHBoxLayout();
        auto label = new QLabel(tr("Play Duration"));
        label->setMinimumWidth(100);
        hBox->addWidget(label);

        auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.duration*1000));
        timeEdit->setDisplayFormat("H:mm:ss");
        timeEdit->setCurrentSectionIndex(2);
        connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) {
            m_attr.duration = time.msecsSinceStartOfDay() / 1000;
        });
        hBox->addWidget(timeEdit);
        hBox->addStretch();

        vBox->addLayout(hBox);
        vBox->addStretch();
    }
    auto stackBox = new QStackedLayout;
    vBox->addLayout(stackBox);
    stackBox->addWidget(wgtAttrFlip);
    stackBox->addWidget(wgtAttrScroll);
    stackBox->addWidget(wgtAttrStatic);
    stackBox->setCurrentIndex(m_attr.playMode);
    connect(fdPlayStyle, &QButtonGroup::idToggled, this, [this, stackBox, pageInfoWgt](int value, bool checked) {
        if(! checked) return;
        m_attr.playMode = value;
        updImg();
        stackBox->setCurrentIndex(value);
        pageInfoWgt->setVisible(value==Flip);
    });
    connect(this, &EText::updPageCnt, wgtAttr, [this, fdPageCnt, fdPageIdx, fdPageDur, fdDur] {
        fdPageCnt->setText(QString::number(mImgs.size()));
        fdPageIdx->setRange(1, mImgs.size());
        fdPageIdx->setValue(1);
        fdDur->setTime(QTime::fromMSecsSinceStartOfDay(fdPageDur->time().msecsSinceStartOfDay() * mImgs.size()));
    });
    return wgtAttr;
}

bool EText::save(const QString &pageDir) {
    QString idDir = pageDir + QString("/%1-%2-%3-%4-%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight);
    QDir(idDir).mkdir(".");
    for(int i=0; i<mImgs.count(); i++) mImgs[i].save(idDir + QString("/text%1.png").arg(i));
    return true;
}
QJsonObject EText::attrJson() const {
    QJsonArray files;
    for(int i=0; i<mImgs.count(); i++) files.append(QString("text%1.png").arg(i)); //上下滚动，生成一张纵向长图
    QJsonObject obj;
    addBaseAttr(obj);
    obj["elementType"] = "Text";
    obj["widget"] = QJsonObject{
        {"text", m_attr.text},
        {"align", (int) m_attr.align},
        {"backColor", m_attr.backColor.name(QColor::HexArgb)},
        {"files", files},
        {"idDir", QString("%1-%2-%3-%4-%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight)}
    };
    obj["play"] = QJsonObject{
        {"style", m_attr.playMode},
        {"turning", QJsonObject{
            {"strEffect", m_attr.flip.effect},
            {"iEffectTime", m_attr.flip.pageDuration},
            {"iEffectSpeed", m_attr.flip.effectDuration}
        }},
        {"rolling", QJsonObject{
            {"rollingStyle", m_attr.scroll.effect},
            {"rollingSpeed", m_attr.scroll.effectSpeed},
            {"headTailSpacing", m_attr.scroll.headTailSpacing},
            {"playDuration", m_attr.scroll.duration}
        }},
        {"static", QJsonObject{{"playDuration", m_attr.duration}}}
    };
    return obj;
}

void EText::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    painter->save();
    auto rect = innerRect();
    if(m_attr.playMode!=EText::Flip) curIdx = 0;
    else if(curIdx>=mImgs.size()) curIdx = mImgs.size() - 1;
    else if(curIdx < 0) curIdx = 0;
    if(m_attr.playMode==EText::Scroll) painter->drawImage(rect.x(), rect.y(), mImgs[0], 0, 0, rect.width(), rect.height());
    else painter->drawImage(rect.x(), rect.y(), mImgs[curIdx]);
    painter->restore();
    EBase::paint(painter, option, widget);
}

void EText::updImg() {
    auto innerRect = this->innerRect();
    int width = innerRect.width();
    int height = innerRect.height();
    if(width<1 || height<1) return;
    QTextDocument doc;
    doc.setDocumentMargin(0);
    QFont font;
    font.setFamilies({"Arial","黑体"});
    font.setPixelSize(16);
    if(! gTextAntialiasing) font.setStyleStrategy(QFont::NoAntialias);
    doc.setDefaultFont(font);
    doc.setDefaultStyleSheet("body {color: #fff;}");
    doc.setHtml(m_attr.text);
    if(m_attr.playMode==EText::Flip) {
        doc.setPageSize(innerRect.size());
        auto pageHeight = height;
        auto pageCnt = doc.pageCount();
        QImage img(width, pageHeight*pageCnt, QImage::Format_ARGB32);
        img.fill(m_attr.backColor);
        {
            QPainter painter(&img);
            doc.drawContents(&painter);
        }
        if(pageCnt > 1) {
            check:
            for(int y=pageHeight-1; y<img.height(); y+=pageHeight) for(int x=0; x<width; x++) if(img.pixelColor(x, y)!=m_attr.backColor) {
                pageHeight *= 2;
                doc.setPageSize(QSizeF(width, pageHeight));
                pageCnt = doc.pageCount();
                img = QImage(width, pageHeight*pageCnt, QImage::Format_ARGB32);
                img.fill(m_attr.backColor);
                {
                    QPainter painter(&img);
                    doc.drawContents(&painter);
                }
                if(pageHeight/height <= 16) goto check;
                else goto forend;
            }
            if(pageCnt > 1) {
                for(int y=img.height()-pageHeight; y<img.height(); y++) for(int x=0; x<width; x++) if(img.pixelColor(x, y)!=m_attr.backColor) goto forend;
                pageCnt--;
            }
        }
        forend:
        QRect rect(0, 0, width, pageHeight);
        mImgs.clear();
        for(int i=0; i<pageCnt; i++) {
            auto pageImg = img.copy(rect);
            alignV(pageImg, height);
            mImgs.append(pageImg);
            rect.translate(0, pageHeight);
        }
        emit updPageCnt();
    } else if(m_attr.playMode==EText::Scroll) {//生成一张大图
        if(m_attr.scroll.effect==0||m_attr.scroll.effect==2) width = qMax(width, ((int)doc.idealWidth()) + m_attr.scroll.headTailSpacing);
        else {
            doc.setTextWidth(width);
            height = doc.size().height() + m_attr.scroll.headTailSpacing;
        }
        QImage img(width, height, QImage::Format_ARGB32);
        img.fill(m_attr.backColor);
        {
            QPainter painter(&img);
            doc.drawContents(&painter);
        }
        if(m_attr.scroll.effect==0||m_attr.scroll.effect==2) alignV(img);
        mImgs.clear();
        mImgs.append(img);
//        if(img.width()<=8192) mImgs.append(img);
//        else {
//            for(int i=0; i<img.width(); i+=8192) {
//                QImage imgpart(8192, height, QImage::Format_ARGB32);
//                imgpart.fill(m_attr.backColor);
//                {
//                    QPainter painter(&imgpart);
//                    painter.drawImage(-i, 0, img);
//                }
//                mImgs.append(imgpart);
//            }
//        }
    } else if(m_attr.playMode==EText::Static) {//生成一张图
        doc.setTextWidth(width);
        QImage img(width, height, QImage::Format_ARGB32);
        img.fill(m_attr.backColor);
        {
            QPainter painter(&img);
            doc.drawContents(&painter);
        }
        alignV(img);
        mImgs.clear();
        mImgs.append(img);
    }
    update();
}
void EText::alignV(QImage &img, int cutHeight) {
    int width = img.width(), height = img.height();
    if(cutHeight==0) cutHeight = height;
    if(m_attr.align & Qt::AlignTop) {
        int ss = 0;
        for(; ss<height; ss++) for(int i=0; i<width; i++) if(img.pixelColor(i, ss)!=m_attr.backColor) goto l12;
        if(cutHeight==height) return;
        ss = 0;
        l12:
        img = copy(img, 0, ss, width, cutHeight);
    } else if(m_attr.align & Qt::AlignVCenter) {
        int ss = 0, ee = height - 1;
        for(; ss<height; ss++) for(int i=0; i<width; i++) if(img.pixelColor(i, ss)!=m_attr.backColor) goto l2;
        if(cutHeight==height) return;
        ss = 0;
        goto l3;
        l2:
        for(; ee>ss; ee--) for(int i=0; i<width; i++) if(img.pixelColor(i, ee)!=m_attr.backColor) goto l3;
        l3:
        img = copy(img, 0, (ss+ee-cutHeight+2)/2, width, cutHeight);
    } else if(m_attr.align & Qt::AlignBottom) {
        int ee = height - 1;
        for(; ee>=0; ee--) for(int i=0; i<width; i++) if(img.pixelColor(i, ee)!=m_attr.backColor) goto l32;
        if(cutHeight==height) return;
        ee = height - 1;
        l32:
        img = copy(img, 0, ee+1-cutHeight, width, cutHeight);
    } else if(cutHeight != height) img = copy(img, 0, 0, width, cutHeight);
}

QImage EText::copy(QImage &img, int x, int y, int w, int h) {
    QImage imgpart(w, h, QImage::Format_ARGB32);
    imgpart.fill(m_attr.backColor);
    {
        QPainter painter(&imgpart);
        painter.drawImage(-x, -y, img);
    }
    return imgpart;
}
