#include "expertwin.h"
#include "gutil/qgui.h"
#include "crc.h"
#include "screenunit.h"
#include "expertboxlayoutwin.h"
#include "expertsmartpointsetwin.h"
#include "expertscreenconnwin.h"
#include <QTabWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QGroupBox>
#include <QStackedWidget>
#include <QRadioButton>
#include <QCheckBox>
#include <QApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonArray>
#include <QMessageBox>
#include <QFileDialog>

QColor colors[] {QColor(0xdd0000), QColor(0xdd6600), QColor(0x008800), QColor(0x008888), QColor(0x0000ff), QColor(0x777777), QColor(0xaaaaaa)};

ExpertWin::ExpertWin(QWidget *parent) : BaseWin{parent} {
    //setWindowModality(Qt::WindowModal);
    setAttribute(Qt::WA_DeleteOnClose);
    setWindowTitle("专家调屏");
    resize(1024, 720);

    auto vBox = new QVBoxLayout(center);
    vBox->setContentsMargins(0,0,0,0);
    vBox->setSpacing(3);
    vBox->addLayout(addBtns(new QHBoxLayout()));

    auto tab = new QTabWidget;
    tab->setStyleSheet(R"rrr(
QTabWidget::pane {border: 1px solid #888; margin-top:-1px;}
QTabBar::tab {margin-top: 4px; padding: 6px 20px; border: 1px solid #888; border-radius: 0 0 3px 3px;}
QTabBar::tab:selected {margin-top: 0; border-bottom: none; color: #acf; background-color: #000;}
)rrr");
    vBox->addWidget(tab);

    auto sendPanel = new QWidget;
    tab->addTab(sendPanel, "发送设备");
    {
        auto hhh = new QHBoxLayout(sendPanel);
        hhh->setContentsMargins(6,6,6,6);

        auto wgtLeft = new QWidget;
        wgtLeft->setMaximumWidth(400);
        hhh->addWidget(wgtLeft);

        auto vLeft = new QVBoxLayout(wgtLeft);
        vLeft->setContentsMargins(0,0,0,0);

        auto hBox = new QHBoxLayout;
        hBox->addWidget(new QLabel("分辨率: "));

        auto fdW = new QLineEdit(QString::number(screenWidth));
        hBox->addWidget(fdW);

        hBox->addWidget(new QLabel("X"));

        auto fdH = new QLineEdit(QString::number(screenHeight));
        hBox->addWidget(fdH);

        vLeft->addLayout(hBox);

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

        auto btnGet = new QPushButton("刷新");
        btnGet->setMinimumWidth(80);
        hBox->addWidget(btnGet);

        hBox->addSpacing(40);

        auto btnSet = new QPushButton("设置");
        btnSet->setMinimumWidth(80);
        hBox->addWidget(btnSet);

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

        auto table = new Table{
            {"face", "网口", 40},
            {"x", "X", 0, QHeaderView::Stretch},
            {"y", "Y", 0, QHeaderView::Stretch},
            {"w", "宽度", 0, QHeaderView::Stretch},
            {"h", "高度", 0, QHeaderView::Stretch},
            {"audio", "音频开关", 0, QHeaderView::Stretch},
            {"backup", "备份开关", 0, QHeaderView::Stretch}
        };
        table->setDefs();
        vLeft->addWidget(table);
        table->setRowCount(4);

        auto canvas = new ResizeEmitedWgt;
        auto screen = new QWidget(canvas);
        screen->setGeometry(0, 0, screenWidth, screenHeight);
        screen->setAutoFillBackground(true);
        auto pal = palette();
        pal.setColor(QPalette::Window, QColor(0, 0, 0));
        screen->setPalette(pal);
        connect(canvas, &ResizeEmitedWgt::resized, this, [this, canvas, screen] {
            rate = qMin(canvas->width()/(double)screenWidth, canvas->height()/(double)screenHeight);
            if(rate==0) return;
            screen->resize(qRound(screenWidth*rate), qRound(screenHeight*rate));
            auto children = screen->children();
            foreach(auto childObj, children) {
                auto unit = static_cast<ScreenUnit*>(childObj);
                unit->setGeometry(qRound(unit->mX*rate), qRound(unit->mY*rate), qRound(unit->mW*rate), qRound(unit->mH*rate));
            }
        });
        hhh->addWidget(canvas);

        int idx = 0;
        for(int rr=0; rr<4; rr++) {
            QString name = "P"+QString::number(rr+1);
            table->setText(rr, "name", name);
            table->setText(rr, "x", QString::number(idx));
            table->setText(rr, "y", "0");
            table->setText(rr, "w", "128");
            table->setText(rr, "h", "128");
            table->setText(rr, "audio", "0");
            table->setText(rr, "backup", "0");

            auto unit = new ScreenUnit(this, name, idx, 0, 128, 128, screen);
            unit->setAutoFillBackground(true);
            pal.setColor(QPalette::Window, colors[rr]);
            unit->setPalette(pal);
            idx += 128;
        }


    }
    {
        auto file = QApplication::applicationDirPath()+"/temp.screen";
        QFile qFile(file);
        if(qFile.open(QFile::ReadOnly)) {
            auto data = qFile.readAll();
            qFile.close();
            QJsonParseError err;
            auto json = QJsonDocument::fromJson(data, &err);
            if(err.error==QJsonParseError::NoError && json.isObject() && ! json.isEmpty()) {
                mBox = json["ModuleConnectionInfo"].toObject();
                mModule = mBox["ModuleInfo"].toObject();
            }
        } else {
            auto file = QApplication::applicationDirPath()+"/temp.module";
            QFile qFile(file);
            if(qFile.open(QFile::ReadOnly)) {
                auto data = qFile.readAll();
                qFile.close();
                QJsonParseError err;
                auto json = QJsonDocument::fromJson(data, &err);
                if(err.error==QJsonParseError::NoError && json.isObject() && ! json.isEmpty()) mModule = json.object();
            }
        }
    }

    auto receivePanel = new QWidget;
    tab->addTab(receivePanel, "接收卡");
    {
        auto vBox = new VBox(receivePanel);
        auto gBox = new QGroupBox("模组信息");
        vBox->addWidget(gBox);
        {
            auto hh = new HBox(gBox);
            hh->addSpacing(20);
            auto vvv = new VBox(hh);

            auto lb = new QLabel("驱动芯片: ");
            vvv->addWidget(lb);

            lb = new QLabel("译码方式: ");
            vvv->addWidget(lb);

            vvv = new VBox(hh);

            fdChipType = new QLabel(mModule["ChipType"].toString());
            vvv->addWidget(fdChipType);

            fdDecodeMode = new QLabel(mModule["DecodeMode"].toString());//译码方式
            vvv->addWidget(fdDecodeMode);

            hh->addSpacing(20);
            vvv = new VBox(hh);

            lb = new QLabel("模组宽度: ");
            vvv->addWidget(lb);

            lb = new QLabel("模组高度: ");
            vvv->addWidget(lb);

            vvv = new VBox(hh);

            fdModuleWidth = new QLabel(QString::number(mModule["ModuleWidth"].toInt()));
            vvv->addWidget(fdModuleWidth);

            fdModuleHeight = new QLabel(QString::number(mModule["ModuleHeight"].toInt()));
            vvv->addWidget(fdModuleHeight);

            hh->addSpacing(20);
            vvv = new VBox(hh);

            lb = new QLabel("扫描数: ");
            vvv->addWidget(lb);

            lb = new QLabel("数据数组: ");
            vvv->addWidget(lb);

            vvv = new VBox(hh);

            fdScanNum = new QLabel(QString::number(mModule["ScanNum"].toInt()));
            vvv->addWidget(fdScanNum);

            fdGroupNum = new QLabel(QString::number(mModule["GroupNum"].toInt()));
            vvv->addWidget(fdGroupNum);

            hh->addSpacing(20);
            vvv = new VBox(hh);

            auto btn = new QPushButton(tr("数据线颜色"));
            btn->setStyleSheet("QPushButton {border: none; }");
            vvv->addWidget(btn);

            btn = new QPushButton(tr("模组抽行设置"));
            btn->setStyleSheet("QPushButton {border: none; }");
            vvv->addWidget(btn);


            hh->addStretch();
            vvv = new VBox(hh);

            btn = new QPushButton("模组选择");
            btn->setProperty("ss","blue");
            vvv->addWidget(btn);

            btn = new QPushButton("智能设置");
            btn->setProperty("ss","blue");
            connect(btn, &QPushButton::clicked, this, [this] {
                (new ExpertSmartPointSetWin(this))->show();
            });
            vvv->addWidget(btn);
        }


        gBox = new QGroupBox("单卡带载");
        vBox->addWidget(gBox);
        {
            auto hh = new HBox(gBox);
            hh->addSpacing(20);
            auto vvv = new VBox(hh);

            auto fdNormal = new QRadioButton("常规设计");
            fdNormal->setChecked(true);
            vvv->addWidget(fdNormal);

            auto fdAdvacned = new QRadioButton("高级设计");
            vvv->addWidget(fdAdvacned);

            hh->addSpacing(20);

            auto line = new QFrame;
            line->setFrameShadow(QFrame::Sunken);
            line->setFrameShape(QFrame::VLine);
            hh->addWidget(line);

            auto stack = new QStackedWidget;
            auto poli = stack->sizePolicy();
            poli.setVerticalPolicy(QSizePolicy::Maximum);
            stack->setSizePolicy(poli);
            hh->addWidget(stack);

            auto normalPanel = new QWidget;
            stack->addWidget(normalPanel);
            {
                auto hh = new HBox(normalPanel);
                hh->setContentsMargins(0,0,0,0);
                auto vvv = new VBox(hh);

                auto lb = new QLabel(tr("宽度"));
                vvv->addWidget(lb);

                lb = new QLabel(tr("高度"));
                vvv->addWidget(lb);

                vvv = new VBox(hh);

                fdCardWidth = new QSpinBox;
                fdCardWidth->setRange(0, 99999);
                fdCardWidth->setValue(mBox["ModuleRow"].toInt() * mModule["ModuleWidth"].toInt());
                vvv->addWidget(fdCardWidth);

                fdCardHeight = new QSpinBox;
                fdCardHeight->setRange(0, 99999);
                fdCardHeight->setValue(mBox["ModuleCol"].toInt() * mModule["ModuleHeight"].toInt());
                vvv->addWidget(fdCardHeight);
                hh->addSpacing(20);

                vvv = new VBox(hh);

                lb = new QLabel(tr("多开设置"));
                vvv->addWidget(lb);

                lb = new QLabel(tr("级联方向"));
                vvv->addWidget(lb);

                vvv = new VBox(hh);

                fdSectorCount = new QComboBox;
                fdSectorCount->addItem(tr("无"), 1);
                fdSectorCount->addItem(tr("双开"), 2);
                fdSectorCount->addItem(tr("三开"), 3);
                fdSectorCount->addItem(tr("四开"), 4);
                fdSectorCount->addItem(tr("五开"), 5);
                fdSectorCount->addItem(tr("六开"), 6);
                fdSectorCount->addItem(tr("七开"), 7);
                fdSectorCount->addItem(tr("八开"), 8);
                setCurrentData(fdSectorCount, mBox["SectorCount"].toInt());
                vvv->addWidget(fdSectorCount);

                fdDirection = new QComboBox();
                fdDirection->addItem(tr("从左到右"));
                fdDirection->addItem(tr("从右到左"));
                fdDirection->addItem(tr("从上到下"));
                fdDirection->addItem(tr("从下到上"));
                fdDirection->setCurrentIndex(mBox["ModuleDirection"].toInt());
                vvv->addWidget(fdDirection);

                hh->addStretch();

                vvv = new VBox(hh);

                auto cb = new QCheckBox(tr("旋转180°"));
                vvv->addWidget(cb);

                auto btn = new QPushButton(tr("数据交换"));
                btn->setProperty("ss","blue");
                vvv->addWidget(btn);
            }

            auto advacnedPanel = new QWidget;
            stack->addWidget(advacnedPanel);
            {
                auto hh = new HBox(advacnedPanel);
                hh->setContentsMargins(0,0,0,0);
                vvv = new VBox(hh);

                auto btn = new QPushButton(tr("平面造型"));
                btn->setProperty("ss","blue");
                btn->setMaximumWidth(100);
                connect(btn, &QPushButton::clicked, this, [=] {
                    auto win = new ExpertBoxLayoutWin(this);
                    win->show();
                });
                vvv->addWidget(btn);
            }
            connect(fdNormal, &QRadioButton::toggled, this, [=](bool checked) {
                stack->setCurrentWidget(checked ? normalPanel : advacnedPanel);
            });
        }

        gBox = new QGroupBox(tr("效果测试"));
        vBox->addWidget(gBox);
        {
            auto hh = new HBox(gBox);
            hh->addSpacing(20);

            auto vvv = new VBox(hh);
            auto hhh = new HBox(vvv);
            auto lb = new QLabel(tr("视觉刷新率:"));
            hhh->addWidget(lb);

            auto cbFresh = new QComboBox();
            cbFresh->addItem("960");
            cbFresh->addItem("1920");
            cbFresh->addItem("2880");
            cbFresh->addItem("3840");
            hhh->addWidget(cbFresh);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("DCLK频率:"));
            hhh->addWidget(lb);
            auto cbDCLKf = new QComboBox();
            cbDCLKf->addItem("25M");
            cbDCLKf->addItem("20.83M");
            cbDCLKf->addItem("17.86M");
            cbDCLKf->addItem("15.63M");
            cbDCLKf->addItem("13.89M");
            cbDCLKf->addItem("12.5M");
            cbDCLKf->addItem("11.36M");
            cbDCLKf->addItem("10.42M");
            cbDCLKf->addItem("9.62M");
            hhh->addWidget(cbDCLKf);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("DCLK相位:"));
            hhh->addWidget(lb);
            auto spinDclkXw = new QSpinBox;
            spinDclkXw->setRange(0, 99999);
            hhh->addWidget(spinDclkXw);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("DCLK占空比:"));
            hhh->addWidget(lb);
            auto spinDclkZkb = new QSpinBox;
            spinDclkZkb->setRange(20, 80);
            hhh->addWidget(spinDclkZkb);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("换行时间(ns):"));
            hhh->addWidget(lb);
            auto spinLineNs = new QSpinBox;
            spinLineNs->setRange(2, 9999);
            hhh->addWidget(spinLineNs);

            hh->addSpacing(20);
            vvv = new VBox(hh);
            hhh = new HBox(vvv);
            lb = new QLabel(tr("亮度有效率:"));
            hhh->addWidget(lb);
            lb = new QLabel(tr("100%"));
            hhh->addWidget(lb);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("GCLK频率:"));
            hhh->addWidget(lb);
            auto cbGCLKf = new QComboBox();
            cbGCLKf->addItem("25M");
            cbGCLKf->addItem("20.83M");
            cbGCLKf->addItem("17.86M");
            cbGCLKf->addItem("15.63M");
            cbGCLKf->addItem("13.89M");
            cbGCLKf->addItem("12.5M");
            cbGCLKf->addItem("11.36M");
            cbGCLKf->addItem("10.42M");
            cbGCLKf->addItem("9.62M");
            hhh->addWidget(cbGCLKf);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("灰度级数:"));
            hhh->addWidget(lb);
            auto cbGryLevel = new QComboBox();
            cbGryLevel->addItem("256");
            cbGryLevel->addItem("1024");
            cbGryLevel->addItem("4096");
            cbGryLevel->addItem("8192");
            cbGryLevel->addItem("16384");
            cbGryLevel->addItem("32768");
            cbGryLevel->addItem("65536");
            hhh->addWidget(cbGryLevel);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("GCLK占空比:"));
            hhh->addWidget(lb);
            auto spinGclkZkb = new QSpinBox;
            spinGclkZkb->setRange(20, 80);
            hhh->addWidget(spinGclkZkb);

            hhh = new HBox(vvv);
            lb = new QLabel(tr("换行位置(ns):"));
            hhh->addWidget(lb);
            auto spinLineWz = new QSpinBox;
            spinLineWz->setRange(2, 9999);
            hhh->addWidget(spinLineWz);

            hh->addStretch();

            vvv = new VBox(hh);
            hhh = new HBox(vvv);

            auto btn = new QPushButton(tr("更多设置"));
            btn->setProperty("ss","blue");
            hhh->addWidget(btn);

        }
        vBox->addStretch();

//保存,发送,固话,回读区
        auto hBox = new HBox(vBox);
        hBox->addSpacing(20);

        auto btn = new QPushButton(tr("打开配置"));
        btn->setProperty("ss","blue");
        hBox->addWidget(btn);
        hBox->addSpacing(20);

        btn = new QPushButton(tr("保存配置"));
        btn->setProperty("ss","blue");
        connect(btn, &QPushButton::clicked, this, [=] {
            auto dir = QApplication::applicationDirPath()+"/BoxFiles";
            QDir(dir).mkdir(".");
            auto file = QFileDialog::getSaveFileName(this, tr("保存文件"), dir, tr("Box file (*.box)"));
            if(file.isEmpty()) return;
            QFile qFile(file);
            if(! qFile.open(QFile::WriteOnly)) {
                QMessageBox::critical(this, tr("失败"), QString(tr("准备写入 %1 文件失败")).arg(file));
                return;
            }
            auto res = qFile.write(savedData());
            qFile.close();
            if(res < 0) {
                QMessageBox::critical(this, tr("失败"), QString(tr("写入 %1 文件失败")).arg(file));
                return;
            }
            QMessageBox::information(this, tr("保存成功"), tr("保存成功"));
        });
        hBox->addWidget(btn);
        hBox->addStretch();

        btn = new QPushButton(tr("保存Map"));
        btn->setProperty("ss","blue");
        connect(btn, &QPushButton::clicked, this, [=] {
            auto dir = QApplication::applicationDirPath();
            auto file = QFileDialog::getSaveFileName(this, tr("保存文件"), dir);
            if(file.isEmpty()) return;
            QFile qFile(file);
            if(! qFile.open(QFile::WriteOnly)) {
                QMessageBox::critical(this, tr("失败"), QString(tr("准备写入 %1 文件失败")).arg(file));
                return;
            }
            QByteArray data;
            addMapData(data);
            auto res = qFile.write(data);
            qFile.close();
            if(res < 0) {
                QMessageBox::critical(this, tr("失败"), QString(tr("写入 %1 文件失败")).arg(file));
                return;
            }
            QMessageBox::information(this, tr("保存成功"), tr("保存成功"));

        });
        hBox->addWidget(btn);
        hBox->addSpacing(20);

        btn = new QPushButton(tr("发送数据"));
        btn->setProperty("ss","blue");
        connect(btn, &QPushButton::clicked, this, [=] {
            QByteArray data;
            addMapData(data);


            QMessageBox::information(this, tr("发送成功"), tr("发送成功"));
        });
        hBox->addWidget(btn);
        hBox->addSpacing(20);

        btn = new QPushButton(tr("固化数据"));
        btn->setProperty("ss","blue");
        hBox->addWidget(btn);
        hBox->addSpacing(20);

        btn = new QPushButton(tr("回读数据"));
        btn->setProperty("ss","blue");
        hBox->addWidget(btn);

        vBox->addStretch();

//状态栏
        auto statusWgt = new QWidget;
        statusWgt->setStyleSheet("QWidget{background-color:#222;}");
        vBox->addWidget(statusWgt);
        {
            auto hh = new HBox(statusWgt);
            auto lb = new QLabel(tr("状态:"));
            hh->addWidget(lb);
        }
    }

    auto connPanel = new QWidget;
    tab->addTab(connPanel, tr("显示屏连接(正面看屏)"));
    {
        auto vBox = new QVBoxLayout(connPanel);
        vBox->setContentsMargins(4, 4, 4, 4);

        auto hhh = new QHBoxLayout;
        vBox->addLayout(hhh);

        auto bnScreen = new QPushButton("屏1");
        hhh->addWidget(bnScreen);

        hhh->addStretch();

        auto lb = new QLabel("显示屏数目:");
        hhh->addWidget(lb);

        auto fdScreenCnt = new QSpinBox;
        fdScreenCnt->setRange(1, 99);
        fdScreenCnt->setValue(1);
        hhh->addWidget(fdScreenCnt);

        auto stack = new QStackedLayout;
        vBox->addLayout(stack);

        stack->addWidget(new ExpertScreenConnWin());
    }
}
void ExpertWin::closeEvent(QCloseEvent *event) {
    BaseWin::closeEvent(event);
    QFile qFile(QApplication::applicationDirPath()+"/temp.screen");
    if(! qFile.open(QFile::WriteOnly)) return;
    qFile.write(savedData());
    qFile.close();
}
QByteArray ExpertWin::savedData() {
    mBox.insert("ModuleInfo", mModule);
    auto ModuleWidth = mModule["ModuleWidth"].toInt();
    auto ModuleHeight = mModule["ModuleHeight"].toInt();
    mBox.insert("ModuleRow", (fdCardWidth->value() + ModuleWidth - 1) / ModuleWidth);
    mBox.insert("ModuleCol", (fdCardHeight->value() + ModuleHeight - 1) / ModuleHeight);
    mBox.insert("ModuleDirection", fdDirection->currentIndex());
    mBox.insert("SectorCount", fdSectorCount->currentData().toInt());
    QJsonObject obj{{"ModuleConnectionInfo", mBox}};
    return QJsonDocument(obj).toJson(QJsonDocument::Indented);
}
void ExpertWin::addMapData(QByteArray &data) {
    auto ModuleWidth = mModule["ModuleWidth"].toInt();
    auto ModuleHeight = mModule["ModuleHeight"].toInt();
    auto ModuleRow = (fdCardWidth->value() + ModuleWidth - 1) / ModuleWidth;
    auto ModuleCol = (fdCardHeight->value() + ModuleHeight - 1) / ModuleHeight;
    auto CardWidth = ModuleRow * ModuleWidth;
    auto CardHeight = ModuleCol * ModuleHeight;
    auto ModuleDirection = fdDirection->currentIndex();
    //auto SectorCount = fdSectorCount->currentData().toInt();
    QMap<uint, uint> map;
    int memY = 0, memX = 0;
    for(int boxY=0; boxY<CardHeight; boxY++) {
        for(int boxX=0; boxX<CardWidth; boxX++) {
            if(memX > 255) {
                memX = 0;
                memY++;
            }
            map.insert(boxY<<16|boxX, memY<<16|memX);
            memX++;
        }
        memX = 0;
        memY++;
    }

    auto points = mModule["Points"].toArray();
    auto scans = mModule["Scans"].toArray();
    auto GroupNum = mModule["GroupNum"].toInt();
    auto jCnt = ModuleCol * GroupNum;

    foreach(auto scan, scans) {
        QList<QList<QByteArray>> chunkses;
        for(int j=0; j<jCnt; j++) {
            int lastMemY = INT_MIN;
            int lastMemX = -1;
            int cnt = 1, ttl = 1;
            bool isAnti = false;
            QList<QByteArray> chunks;
            QByteArray chunk;
            QString chstr;
            for(int mm=0; mm<ModuleRow; mm++) {
                int m = ModuleDirection==0 ? ModuleRow-1-mm : mm;
                foreach(auto point, points) {
                    uint boxY = j * scans.size() + scan.toInt();
                    uint boxX = m * ModuleWidth + point.toInt();
                    if(boxX < 0) { //虚点
                        if(lastMemY==-1) memX = lastMemX + 1;
                        else {
                            memY = -1;
                            memX = 0;
                        }
                    } else {
                        auto mem = map[boxY<<16 | boxX];
                        memY = mem >> 16;
                        memX = mem & 0xffff;
                    }
                    if(memY==lastMemY && ttl < 64 && qAbs(memX-lastMemX)==1) {
                        if(cnt==1) {
                            isAnti = memX < lastMemX;
                            cnt++;
                            ttl++;
                            lastMemX = memX;
                            continue;
                        } else if(memX < lastMemX == isAnti) {
                            cnt++;
                            ttl++;
                            lastMemX = memX;
                            continue;
                        }
                    }
                    if(lastMemY > INT_MIN) {
                        uint y = lastMemY==-1 ? 0 : lastMemY;
                        uint x = isAnti ? lastMemX : lastMemX-cnt+1;
                        chunk.append((j << 2) + (y >> 8)).append(y).append(x).append((isAnti << 7)+cnt);
                        chstr += QString("j%1 行%2 列%3 序%4 长%5").arg(j).arg(y).arg(x).arg(isAnti).arg(cnt);
                    }
                    if(ttl>=64) {
                        chunks.append(chunk);
                        chunk = QByteArray();
                        qDebug() << chstr;
                        chstr.clear();
                        ttl = 1;
                    }
                    cnt = 1;
                    lastMemY = memY;
                    lastMemX = lastMemY==-1 ? 0 : memX;
                }
            }
            uint y = lastMemY==-1 ? 0 : lastMemY;
            uint x = isAnti ? lastMemX : lastMemX-cnt+1;
            chunk.append((j << 2) + (y >> 8)).append(y).append(x).append((isAnti << 7)+cnt);
            chstr += QString("j%1 行%2 列%3 序%4 长%5").arg(j).arg(y).arg(x).arg(isAnti).arg(cnt);
            chunks.append(chunk);
            chunkses.append(chunks);
            qDebug() << chstr;
        }
        data.append(0xAA).append(scan.toInt()).append(2, 0);
        auto chend = chunkses[0].size()-1;
        auto start = data.size();
        for(int ch=0; ch<=chend; ch++) {
            data.append(0x55).append(ch==chend ? (char)(1<<7) : 0).append(2, 0);
            auto start = data.size();
            foreach(auto chunks, chunkses) data.append(chunks[ch]);
            auto num = (data.size() - start) / 4;
            data[start-2] = num;
            data[start-3] = num>>8;
        }
        auto len = data.size() - start;
        data[start-1] = len;
        data[start-2] = len>>8;
    }
}

#define MAX_ONCE 1482
void run() {
//    quint32 idx = 0;
//    while(2) {
//        QByteArray bytes;
//        bytes.append("\x55\x55\x9a\x3d"); //前导, 版本号, 服务类型
//        bytes.append("\0\x4", 2); //数据长度
//        bytes.append(4, '\xff'); //目的地址
//        bytes.append(4, 0); //源地址
//        bytes.append("\xB1\x04\0\0", 4); //内存指针
//        bytes.append(2, 0); //应答填充项
//        auto crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2);
//        bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32); //包头校验

//        crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-4, 4);
//        bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32);
//        //发送帧开始指令包
//        auto queue = pcap_sendqueue_alloc(img.width()*img.height()*4);
//        {
//            struct pcap_pkthdr pktheader;
//            pktheader.len = pktheader.caplen = bytes.size();
//            if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) {
//                onErr(QString("添加开始失败: ")+pcap_geterr(pcap));
//                goto end;
//            }
//            idx = 0;
//            //按行发送图像数据包
//            for(int i=0; i<img.height(); i++) for(int j=0; j<lineLen; j+=once) {
//                int dataLen = lineLen - j;
//                if(dataLen > once) dataLen = once;
//                dataLen += 4;
//                bytes.clear();
//                bytes.append("\x55\x55\x1\x33"); //前导, 版本号, 服务类型
//                bytes.append(dataLen>>8).append(dataLen); //数据长度
//                bytes.append(4, '\xff'); //目的地址
//                bytes.append(4, 0); //源地址
//                bytes.append(i>>8).append(i).append(j>>8).append(j); //内存指针
//                bytes.append(2, 0); //应答填充项
//                crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2);
//                bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32);
//                bytes.append(idx>>24).append(idx>>16).append(idx>>8).append(idx);//包序号
//                idx++;
//                bytes.append((const char*)bits + i * bytesPerLine + j, dataLen - 4);
//                crc32 = crc32_calc((uint8_t*)bytes.data()+bytes.length()-dataLen, dataLen);
//                bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32);
//                pktheader.len = pktheader.caplen = bytes.size();
//                if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) {
//                    onErr(QString("添加数据失败: ")+pcap_geterr(pcap));
//                    goto end;
//                }
//            }
//            bytes.clear();
//            bytes.append("\x55\x55\x9a\x3d"); //前导, 版本号, 服务类型
//            bytes.append(2, 0); //数据长度
//            bytes.append(4, '\xff'); //目的地址
//            bytes.append(4, 0); //源地址
//            bytes.append("\x35\0\xc\xcc", 4); //内存指针
//            bytes.append(2, 0); //应答填充项
//            crc32 = crc32_calc((uint8_t*)bytes.data()+2, bytes.length()-2);
//            bytes.append(crc32>>24).append(crc32>>16).append(crc32>>8).append(crc32);
//            pktheader.len = pktheader.caplen = bytes.size();
//            //发送帧结束指令包
//            if(pcap_sendqueue_queue(queue, &pktheader, (u_char*)bytes.data()) == -1) {
//                onErr(QString("添加结束失败: ")+pcap_geterr(pcap));
//                goto end;
//            }
//            u_int res;
//            if((res = pcap_sendqueue_transmit(pcap, queue, 0)) < queue->len) {
//                onErr(QString::asprintf("发送包出错: %s. 仅发了 %d / %d bytes", pcap_geterr(pcap), res, queue->len));
//                goto end;
//            }
//        }
//        end:
//        pcap_sendqueue_destroy(queue);
//    }
}