#include "progeditorwin.h"
#include "progpanel.h"
#include "base/customprogressindicator.h"
#include "base/loemptydialog.h"
#include "base/loqtitlebar.h"
#include "cfg.h"
#include "ebase.h"
#include "pagelistitem.h"
#include "player/playwin.h"
#include "tools.h"
#include "globaldefine.h"
#include "base/waitingdlg.h"
#include "program/ebase.h"
#include "program/etext.h"
#include "program/ephoto.h"
#include "program/evideo.h"
#include "program/eaudio.h"
#include "program/egif.h"
#include "program/edclock.h"
#include "program/eaclock.h"
#include "program/eenviron.h"
#include "program/eweb.h"
#include "program/etimer.h"
#include "program/emultiwin.h"
#include "program/gentmpthread.h"
#include "program/sendprogramdialog.h"
#include "progcreatedlg.h"
#include <QBoxLayout>
#include <QCloseEvent>
#include <QGraphicsDropShadowEffect>
#include <QInputDialog>
#include <QJsonArray>
#include <QMessageBox>
#include <QSettings>
#include <QToolBar>
#include <QUdpSocket>

ProgItem *gProgItem{0};
QWidget *gProgEditorWin;

ProgEditorWin::ProgEditorWin(ProgItem *progItem, QWidget *parent) : BaseWin(parent), mProgItem(progItem) {
    gProgEditorWin = this;
    gProgItem = progItem;
    setWindowModality(Qt::WindowModal);
    setAttribute(Qt::WA_AlwaysShowToolTips);
    if(parent && ! parent->isMaximized()) resize(parent->size());
    else resize(1280, 720);
    setWindowFlag(Qt::Window);
    setAttribute(Qt::WA_DeleteOnClose);
    auto plt = palette();
    plt.setBrush(QPalette::Window, QColor(0xdddddd));
    setPalette(plt);
    setWindowTitle(progItem->mName);
    icon = QPixmap(":/res/Logo.ico").scaledToHeight(16);

    auto vBox = new QVBoxLayout(center);
    vBox->setContentsMargins(0, 0, 0, 0);
    vBox->setSpacing(0);

    auto titleBar = new LoQTitleBar(this);
    titleBar->bn_Minimize->setVisible(false);
    auto hBox = new QHBoxLayout(titleBar);
    hBox->setContentsMargins(0, 0, 0, 0);
    hBox->setSpacing(0);
    hBox->addStretch();
    hBox->addWidget(titleBar->bn_Minimize);
    hBox->addWidget(titleBar->bn_Maximize);
    hBox->addWidget(titleBar->bn_Close);

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

    auto toolBar = new QToolBar();
    toolBar->setFloatable(false);
    toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    toolBar->setIconSize(QSize(46, 40));

    auto action = new QAction(QIcon(":/res/program/Save.png"), tr("Save"));
    connect(action, &QAction::triggered, this, &ProgEditorWin::onSave);
    toolBar->addAction(action);
    action = new QAction(QIcon(":/res/program/SaveAs.png"), tr("Save as"));
    connect(action, &QAction::triggered, this, [this] {
        auto saveThread = QThread::create([this](){
            save();
        });
        connect(saveThread, SIGNAL(finished()), saveThread, SLOT(deleteLater()));
        connect(saveThread, &QThread::finished, this, [this] {
            this->mProgItem->m_last = QDateTime::currentDateTime();
            this->mProgItem->m_fsize = dirFileSize(this->mProgItem->mProgDir);
            this->mProgItem->onSetProgram();
        });
        saveThread->start();
        bool isOK;
        QString progName = QInputDialog::getText(this, tr("Save as"), tr("Save as"), QLineEdit::Normal, QString(), &isOK, Qt::Dialog | Qt::WindowCloseButtonHint);
        if(! isOK || progName.isEmpty()) return;
        mProgItem->mProgDir = this->mProgItem->mProgsDir + "/" + progName;
        LoEmptyDialog *dlgTip = new LoEmptyDialog(this);
        saveThread = QThread::create([this](){
            save();
        });
        dlgTip->lock(tr("Saving..."),tr("Success"),tr("Save failed"));
        connect(saveThread, SIGNAL(finished()), dlgTip, SLOT(unlock()));//显示正在保存提示对话框
        connect(saveThread, SIGNAL(finished()), saveThread, SLOT(deleteLater()));
        connect(saveThread, &QThread::finished, this, [this] {
            mProgItem->m_last = QDateTime::currentDateTime();
            mProgItem->m_fsize = dirFileSize(mProgItem->mProgDir);
            mProgItem->onSetProgram();
        });
        saveThread->start();
        dlgTip->exec();
        close();
        setWindowTitle(progName);
        mProgItem->mProgPanel->onCreateNewProgramOnOpenEditProgramWidget(progName, QSize(mProgItem->mWidth, mProgItem->mHeight), mProgItem->mRemark, mProgItem->mSplitWidths, mProgItem->mMaxWidth);
    });
    toolBar->addAction(action);
    action = new QAction(QIcon(":/res/program/Setting.png"), tr("Setting"));
    connect(action, &QAction::triggered, this, [this]() {
        QString widthsStr;
        foreach(auto width, mProgItem->mSplitWidths) {
            if(! widthsStr.isEmpty()) widthsStr.append(" ");
            widthsStr.append(QString::number(width));
        }
        ProgCreateDlg dlg(mProgItem->mName, mProgItem->mWidth, mProgItem->mHeight, mProgItem->mRemark, widthsStr, this);
        if(dlg.exec() != QDialog::Accepted) return;
        mProgItem->mWidth = dlg.fdWidth->value();
        mProgItem->mHeight = dlg.fdHeight->value();
        mProgItem->mRemark = dlg.fdRemark->toPlainText();
        mProgItem->mSplitWidths.clear();
        mProgItem->mMaxWidth = 0;
        auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts);
        int ttl = 0;
        foreach(auto splitWidth, splitWidths) {
            int val = splitWidth.toInt();
            if(val==0) continue;
            if(mProgItem->mMaxWidth < val) mProgItem->mMaxWidth = val;
            ttl += val;
            mProgItem->mSplitWidths.append(val);
        }
        if(mProgItem->mMaxWidth) {
            while(ttl < mProgItem->mWidth) {
                mProgItem->mSplitWidths.append(mProgItem->mMaxWidth);
                ttl += mProgItem->mMaxWidth;
            }
            if(ttl > mProgItem->mWidth) mProgItem->mSplitWidths.last() -= ttl - mProgItem->mWidth;
        }

        mProgItem->m_last = QDateTime::currentDateTime();
        mProgItem->m_fsize = dirFileSize(mProgItem->mProgDir);
        mProgItem->onSetProgram();
        int n = listPage->count();
        for(int i=0; i<n; i++) {
            auto page = static_cast<PageListItem*>(listPage->item(i));
            page->mScene->setSceneRect(0, 0, mProgItem->mWidth, mProgItem->mHeight);
            page->mGraView->resetTransform();
            qreal scale = qMin(page->mGraView->width() / page->mScene->width(), page->mGraView->height() / page->mScene->height());
            page->mGraView->scale(scale, scale);

            auto items = page->mScene->items();
            foreach(auto item, items) {
                auto element = static_cast<EBase*>(item);
                if(element->mMultiWin == 0) element->fitProgSize();
            }
            page->mScene->update();
        }
        onSave();
    });
    toolBar->addAction(action);
    toolBar->addSeparator();

    if(progItem->mSplitWidths.isEmpty()) {
        action = new QAction(QIcon(":/res/program/Window.png"), tr("MuliContentWindow"));
        action->setToolTip(tr("In this window, a plurality of different program materials can be added and played according to the order of joining the list;"));
        action->setData(EBase::Window);
        toolBar->addAction(action);
        toolBar->addSeparator();
    }
    action = new QAction(QIcon(":/res/program/Text.png"), tr("Text"));
    action->setData(EBase::Text);
    toolBar->addAction(action);
    action = new QAction(QIcon(":/res/program/Photo.png"), tr("Photo"));
    action->setData(EBase::Photo);
    toolBar->addAction(action);
    action = new QAction(QIcon(":/res/program/Movie.png"), tr("Video"));
    action->setData(EBase::Video);
    toolBar->addAction(action);
    if(progItem->mSplitWidths.isEmpty()) {
        action = new QAction(QIcon(":/res/program/Gif.png"), tr("Gif"));
        action->setData(EBase::Gif);
        toolBar->addAction(action);
        action = new QAction(QIcon(":/res/program/DClock.png"), tr("Clock"));
        action->setData(EBase::DClock);
        toolBar->addAction(action);
        action = new QAction(QIcon(":/res/program/AClock.png"), tr("Analog Clock"));
        action->setData(EBase::AClock);
        toolBar->addAction(action);
        action = new QAction(QIcon(":/res/program/Temp.png"), tr("Environment"));
        action->setData(EBase::Environ);
        toolBar->addAction(action);
        action = new QAction(QIcon(":/res/program/Web.png"), tr("Web"));
        action->setData(EBase::Web);
        toolBar->addAction(action);
        action = new QAction(QIcon(":/res/program/Timer.png"), tr("Timer"));
        action->setData(EBase::Timer);
        toolBar->addAction(action);
    }

    toolBar->addSeparator();

    action = new QAction(QIcon(":/res/program/preview.png"), tr("Play")+"/"+tr("Stop"));
    connect(action, &QAction::triggered, this, [this] {
        if(PlayWin::self!=nullptr) PlayWin::self->close();
        else {
             if(isProgChanged()) onSave();
             auto waitingDlg = new WaitingDlg(this, tr("Generate preview data")+" ...");
             auto converter = new GenTmpThread(mProgItem, mProgItem->mName, "", "" ,this);
             connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::close);
             connect(converter, &GenTmpThread::sProgress, waitingDlg->mIndicator, &CustomProgressIndicator::onProgress);
             converter->start();
             waitingDlg->exec();
             QFile file(mProgItem->mProgDir+"_tmp/program");
             if(! file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
             QString value = file.readAll();
             file.close();
             QJsonParseError jsErr;
             QJsonObject prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object();
             if(jsErr.error) return;
             int www = mProgItem->mWidth, hhh = mProgItem->mHeight;
             if(mProgItem->mMaxWidth) {
                 www = mProgItem->mMaxWidth;
                 hhh *= mProgItem->mSplitWidths.size();
             }
             PlayWin::self = PlayWin::newIns(www, hhh, mProgItem->mProgDir+"_tmp", prog);
         }
     });
    toolBar->addAction(action);
    action = new QAction(QIcon(":/res/program/Send.png"), tr("Publish"));
    connect(action, &QAction::triggered, this, [this]{
        onSave();
        auto waitingDlg = new WaitingDlg(this, tr("Convertering")+" ...");
        auto converter = new GenTmpThread(mProgItem, mProgItem->mName, "", "", this);
        connect(converter, &QThread::finished, waitingDlg, &WaitingDlg::close);
        connect(converter, &GenTmpThread::sProgress, waitingDlg->mIndicator, &CustomProgressIndicator::onProgress);
        converter->start();
        waitingDlg->exec();
        SendProgramDialog dlg(mProgItem->mName, this);
        dlg.exec();
    });
    toolBar->addAction(action);

    connect(toolBar, &QToolBar::actionTriggered, this, [this](QAction *act) {
        auto data = act->data();
        if(data.type()!=QVariant::Int) return;
        auto scene = progEditorMid->graphicsView->scene();
        if(nullptr == scene) return;
        int order = progEditorMid->sortedEles().count();
        EBase *element = nullptr;
        int iNewWidth = mProgItem->mWidth;
        int iNewHeight = mProgItem->mHeight;
        if(iNewWidth>128) iNewWidth = iNewWidth * 2 / 3;
        if(iNewHeight>128) iNewHeight = iNewHeight * 2 / 3;
        if(mNewEleX+iNewWidth>mProgItem->mWidth) mNewEleX=0;
        if(mNewEleY+iNewHeight>mProgItem->mHeight) mNewEleY=0;
        auto type = data.toInt();
        if(type==EBase::Photo) {
            auto files = QFileDialog::getOpenFileNames(this, tr("Select File"), gFileHome, EPhoto::filters());
            for(int i=0; i<files.count(); i++) {
                auto ePhoto = EPhoto::create(files[i], mPageItem);
                if(ePhoto==nullptr) continue;
                auto rect = Tools::centerRect(ePhoto->img.width(), ePhoto->img.height(), mProgItem->mWidth, mProgItem->mHeight);
                ePhoto->setPos(rect.topLeft());
                ePhoto->setSize(rect.width(), rect.height());
                ePhoto->setZValue(order++);
                scene->addItem(ePhoto);
                if(i==files.count()-1) {
                    auto scene = progEditorMid->graphicsView->scene();
                    if(nullptr != scene) {
                        auto list = scene->selectedItems();
                        if(list.count() == 1) static_cast<EBase*>(list.at(0))->setSelected(false);
                    }
                    ePhoto->setSelected(true);
                    gFileHome = ePhoto->mDir;
                }
            }
        } else if(type==EBase::Gif) {
            auto files = QFileDialog::getOpenFileNames(this, tr("Select File"), gFileHome, EGif::filters());
            for(int i=0; i<files.count(); i++) {
                auto eGif = EGif::create(files[i], mPageItem);
                if(eGif==nullptr) continue;
                auto img = eGif->mMovie->currentPixmap();
                auto rect = Tools::centerRect(img.width(), img.height(), mProgItem->mWidth, mProgItem->mHeight);
                eGif->setPos(rect.topLeft());
                eGif->setSize(rect.width(), rect.height());
                eGif->setZValue(order++);
                scene->addItem(eGif);
                if(i == files.count()-1){
                    auto scene = progEditorMid->graphicsView->scene();
                    if(nullptr != scene) {
                        auto list = scene->selectedItems();
                        if(list.count() == 1) static_cast<EBase*>(list.at(0))->setSelected(false);
                    }
                    eGif->setSelected(true);
                    gFileHome = eGif->mDir;
                }
            }
        } else if(type==EBase::Video) {
            auto file = QFileDialog::getOpenFileName(this, tr("Select File"), gFileHome, EVideo::filters());
            if(file.isEmpty()) return;
            auto eVideo = EVideo::create(file, mPageItem);
            if(eVideo==nullptr) return;
            auto rect = Tools::centerRect(eVideo->mCoverImg.width(), eVideo->mCoverImg.height(), mProgItem->mWidth, mProgItem->mHeight);
            eVideo->setPos(rect.topLeft());
            eVideo->setSize(rect.width(), rect.height());
            gFileHome = eVideo->mRawDir;
            element = eVideo;
        } else if(type== EBase::Audio) {
            auto file = QFileDialog::getOpenFileName(this, tr("Select File"), gFileHome, EAudio::filters());
            if(file.isEmpty()) return;
            auto eAudio = EAudio::create(file, mPageItem);
            if(eAudio==nullptr) return;
            int i=0;
            for(; i<mProgItem->mWidth; i+=50) if(nullptr==scene->itemAt(i+20, mProgItem->mHeight+20, QTransform())) break;
            eAudio->setPos(i, mProgItem->mHeight);
            eAudio->setSize(50, 50);
            gFileHome = eAudio->mDir;
            element = eAudio;
        }
        else if(type==EBase::Text) {
            if(iNewHeight > 80 && (mProgItem->mWidth >= mProgItem->mHeight)) iNewHeight = 80;
            element = new EText();
        }
        else if(type==EBase::DClock) {
            if(iNewHeight>80 && (mProgItem->mWidth>=mProgItem->mHeight)) iNewHeight=80;
            element = new EDClock();
        }
        else if(type==EBase::AClock) {
            if(iNewWidth > 120) iNewWidth = 120;
            if(iNewHeight > 120) iNewHeight = 120;
            element = new EAClock();
        }
        else if(type==EBase::Environ) element = new EEnviron();
        else if(type==EBase::Web) {
            element = new EWeb();
            element->setSize(mProgItem->mWidth, mProgItem->mHeight);
        }
        else if(type==EBase::Timer) element = new ETimer();
        else if(type==EBase::Audio) ;
        else if(type==EBase::Window) element = new EMultiWin(mPageItem);
        if(element) {
            if(element->mWidth==0) {
                element->setPos(mNewEleX, mNewEleY);
                element->setSize(iNewWidth, iNewHeight);
            }
            element->setZValue(order);
            scene->addItem(element);
            mNewEleX+=8;
            mNewEleY+=8;
            QGraphicsScene *scene = progEditorMid->graphicsView->scene();
            if(nullptr != scene){
                QList<QGraphicsItem *> list = scene->selectedItems();
                if(list.count() == 1) static_cast<EBase*>(list.at(0))->setSelected(false);
            }
            element->setSelected(true);
        }
    });
    vBox->addWidget(toolBar);

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

    //主区域横向布局（幻灯片页列表，编辑窗，属性窗）
    hBox = new QHBoxLayout();
    hBox->setContentsMargins(0, 0, 0, 0);
    hBox->setSpacing(0);

    auto vBoxPage = new QVBoxLayout();
    vBoxPage->setContentsMargins(0, 0, 0, 0);
    vBoxPage->setSpacing(0);
    auto lbName = new QLabel(tr("program"));
    lbName->setStyleSheet("QLabel{background-color: #bbbbbb;}");
    lbName->setAlignment(Qt::AlignCenter);
    vBoxPage->addWidget(lbName);

    toolBar = new QToolBar();
    toolBar->setIconSize(QSize(22,16));
    toolBar->setStyleSheet("QToolBar{spacing: 8px;}");

    QAction *actAdd = new QAction(QIcon(":/res/program/Add.png"),    tr("Add page"));
    connect(actAdd, &QAction::triggered, this, &ProgEditorWin::onAddPage);
    toolBar->addAction(actAdd);

    QAction *actCopy = new QAction(QIcon(":/res/program/Copy.png"),   tr("Copy page"));
    connect(actCopy, &QAction::triggered, this, [this] {
        if(listPage->count() > 0) {
            auto cur = static_cast<PageListItem*>(listPage->currentItem());
            cur->updateJson();
            auto item = new PageListItem(cur->mAttr, cur->mPageDir);
            item->mAttr["name"] = QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
            item->mAttr["order"] = listPage->count();
            listPage->addItem(item);
            listPage->setItemWidget(item, item->itemWgt());
            listPage->setCurrentItem(item);
        }
    });
    toolBar->addAction(actCopy);

    QAction *actDel = new QAction(QIcon(":/res/program/Delete.png"), tr("Delete page"));
    connect(actDel, &QAction::triggered, this, [this] {
        if(listPage->count() == 1) progEditorMid->onClean();
        else if(listPage->count() > 1) {
            auto item = static_cast<PageListItem*>(listPage->currentItem());
            auto res = QMessageBox::information(this, tr("Tip Info"), tr("Are you sure you want to delete this program page?"), QMessageBox::Ok, QMessageBox::Cancel);
            if(res == QMessageBox::Ok) {
                delete item;
                if(listPage->count() > 0) listPage->setCurrentRow(0);
                int n = listPage->count();
                for(int i=0; i<n; i++) static_cast<PageListItem*>(listPage->item(i))->mAttr["order"] = QJsonValue(i);
            }
        }
    });
    toolBar->addAction(actDel);

    QAction *actMoveUp = new QAction(QIcon(":/res/program/GoUp.png"),   tr("Move up"));
    connect(actMoveUp, &QAction::triggered, this, [this] {
        if(listPage->count() > 1) {
            int index = listPage->currentRow();
            if(index > 0) {
                auto item = static_cast<PageListItem*>(listPage->takeItem(index));
                listPage->insertItem(index-1, item);
                listPage->setItemWidget(item, item->itemWgt());
                listPage->setCurrentRow(index-1);
            }
            int n = listPage->count();
            for(int i=0; i<n; i++) static_cast<PageListItem*>(listPage->item(i))->mAttr["order"] = QJsonValue(i);
        }
    });
    toolBar->addAction(actMoveUp);

    QAction *actMoveDown = new QAction(QIcon(":/res/program/GoDown.png"), tr("Move down"));
    connect(actMoveDown, &QAction::triggered, this, [this] {
        if(listPage->count() > 1) {
            int index = listPage->currentRow();
            if(index < listPage->count()-1) {
                auto item = static_cast<PageListItem*>(listPage->takeItem(index));
                listPage->insertItem(index+1, item);
                listPage->setItemWidget(item, item->itemWgt());
                listPage->setCurrentRow(index+1);
            }
            int n = listPage->count();
            for(int i=0; i<n; i++) static_cast<PageListItem*>(listPage->item(i))->mAttr["order"] = QJsonValue(i);
        }
    });
    toolBar->addAction(actMoveDown);

    vBoxPage->addWidget(toolBar);

    listPage = new QListWidget();
    listPage->setMaximumWidth(190);
    connect(listPage, &QListWidget::currentItemChanged, this, [this](QListWidgetItem *current, QListWidgetItem *previous) {
        auto curItem = static_cast<PageListItem*>(current);
        auto preItem = static_cast<PageListItem*>(previous);
        if(nullptr != preItem) preItem->mScene->clearSelection();
        mPageItem = curItem;
        auto scene = progEditorMid->graphicsView->scene();
        if(scene != nullptr) disconnect(scene, &QGraphicsScene::selectionChanged, this, 0);
        if(progEditorMid->curScale != 100) {
            progEditorMid->curScale = 100;
            progEditorMid->fdScale->setText("100");
            progEditorMid->graphicsView->resetTransform();
        }
        if(curItem == nullptr) progEditorMid->graphicsView->setScene(nullptr);
        else {
            progEditorMid->graphicsView->setScene(scene = curItem->mScene);
            connect(scene, &QGraphicsScene::selectionChanged, this, [this] {
                auto scene = progEditorMid->graphicsView->scene();
                if(scene==nullptr) return;
                auto sels = scene->selectedItems();
                auto scroll = static_cast<QScrollArea*>(mTabsAttr->widget(0));
                if(sels.size() != 1) {
                    mTabsAttr->setCurrentIndex(1);
                    auto wgt = scroll->takeWidget();
                    if(wgt!=nullptr) delete wgt;
                } else {
                    mTabsAttr->setCurrentIndex(0);
                    scroll->setWidget(static_cast<EBase*>(sels[0])->attrWgt());
                    scroll->updateGeometry();
                }
            });
        }
        auto scroll = static_cast<QScrollArea*>(mTabsAttr->widget(1));
        scroll->takeWidget();
        if(curItem != nullptr) {
            scroll->setWidget(curItem->attrWgt());
            scroll->updateGeometry();
        }
        mTabsAttr->setCurrentIndex(1);
    });
    vBoxPage->addWidget(listPage);
    hBox->addLayout(vBoxPage);

    hBox->addWidget(progEditorMid = new PageEditor(this), 1);

    mTabsAttr = new QTabWidget();
    mTabsAttr->setMinimumWidth(360);
    mTabsAttr->setStyleSheet("QTabWidget::pane{border:none;}");

    QPalette backTrans;
    backTrans.setColor(QPalette::Window, Qt::transparent);

    auto scroll = new QScrollArea();
    scroll->setFrameShape(QFrame::NoFrame);
    scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    scroll->setWidgetResizable(true);
    scroll->setPalette(backTrans);
    mTabsAttr->addTab(scroll, tr("widget properties"));

    scroll = new QScrollArea();
    scroll->setFrameShape(QFrame::NoFrame);
    scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    scroll->setWidgetResizable(true);
    scroll->setPalette(backTrans);
    mTabsAttr->addTab(scroll, tr("Page properties"));
    mTabsAttr->setCurrentIndex(0);

    hBox->addWidget(mTabsAttr);

    vBox->addLayout(hBox);

    QGraphicsDropShadowEffect *shadow_effect = new QGraphicsDropShadowEffect(progEditorMid);
    shadow_effect->setOffset(0, 0);
    shadow_effect->setColor(QColor(38, 78, 119, 127));//阴影颜色
    shadow_effect->setBlurRadius(8);//阴影半径
    progEditorMid->setGraphicsEffect(shadow_effect);

    QDir progQDir(mProgItem->mProgDir);
    if(progQDir.exists()) {
        QStringList pageNames = progQDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
        foreach(QString pageName, pageNames) {
            if(pageName.endsWith(PAGEDEL_SUFFIX)) {
                QDir(mProgItem->mProgDir + "/" + pageName).removeRecursively();
                continue;
            }
            QFile pageFile(mProgItem->mProgDir + "/" + pageName + "/page.json");
            if(pageFile.exists()) {
                pageFile.open(QIODevice::ReadOnly);
                mPageJsons.push_back(QJsonDocument::fromJson(pageFile.readAll()).object());
                pageFile.close();
            } else QDir(mProgItem->mProgDir + "/" + pageName).removeRecursively();
        }
    }
    if(mPageJsons.isEmpty()) onAddPage();
    else {
        std::sort(mPageJsons.begin(), mPageJsons.end(), [](const QJsonObject &a, const QJsonObject &b) {
            return a["order"].toInt() < b["order"].toInt();
        });
        foreach(QJsonObject pageJson, mPageJsons) {
            auto pageDir = mProgItem->mProgDir+"/"+pageJson["name"].toString();
            QDir dir(pageDir);
            if(! dir.exists() && ! dir.mkdir(".")) continue;
            auto item = new PageListItem(pageJson, pageDir);
            listPage->addItem(item);
            listPage->setItemWidget(item, item->itemWgt());
        }
    }
    listPage->setCurrentRow(0);
}
bool ProgEditorWin::isProgChanged() {
    if(mPageJsons.size() != listPage->count()) return true;
    for(int i=0; i<mPageJsons.count(); i++) {
        auto page = static_cast<PageListItem*>(listPage->item(i));
        if(page->mAttrWgt==0) continue;
        page->updateJson();
        if(page->mAttr != mPageJsons[i]) return true;
    }
    return false;
}
void ProgEditorWin::closeEvent(QCloseEvent *event) {
    mProgItem->m_last = QDateTime::currentDateTime();
    mProgItem->m_fsize = dirFileSize(mProgItem->mProgDir);
    mProgItem->onSetProgram();
    if(! isProgChanged()) return;
    auto res = QMessageBox::question(this, tr("Tip Info"), tr("Do you want to save the modifications?"), QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel);
    if(res == QMessageBox::Yes) onSave();
    else if(res == QMessageBox::Cancel) event->ignore();
}
//停止每个页面元素的播放，将节目目录下的每个页面的文件夹另命名
void ProgEditorWin::save() {
    //停止每个幻灯片的元素
    int cnt = listPage->count();
    for(int i=0; i<cnt; i++) {
        auto items = static_cast<PageListItem*>(listPage->item(i))->mScene->items();
        foreach(auto item, items) static_cast<EBase*>(item)->freeFiles();
    }
    QDir progDir(mProgItem->mProgDir);
    if(! progDir.exists() && ! progDir.mkdir(".")) return;
    QStringList pageNames = progDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
    foreach(QString pageName, pageNames) {
        if(! progDir.rename(pageName, pageName + PAGEDEL_SUFFIX)) QMessageBox::critical(this, tr("Error"), tr("Rename fail when saving")+" "+pageName);
    }
    //保存每个页面的元素和页面属性到page.json文档
    mPageJsons.clear();
    for(int i=0; i<cnt; i++) {
        auto page = static_cast<PageListItem*>(listPage->item(i));
        if(page->saveFiles()) mPageJsons.append(page->mAttr);
    }
    pageNames = progDir.entryList(QStringList("*" PAGEDEL_SUFFIX));
    foreach(QString pageName, pageNames) {
        if(! QDir(mProgItem->mProgDir + "/" + pageName).removeRecursively()) QMessageBox::critical(this, tr("Error"), tr("Remove Recursively fail when saving")+" "+pageName);
    }
    for(int i=0; i<cnt; i++) {
        auto items = static_cast<PageListItem*>(listPage->item(i))->mScene->items();
        foreach(auto item, items) static_cast<EBase*>(item)->loadFiles();
    }
}

void ProgEditorWin::onSave() {
    auto waitingDlg = new WaitingDlg(this, tr("Saving..."), tr("Success"));
    waitingDlg->btnAbort->hide();
    //dlg->lock(tr("Saving..."),tr("Success"),tr("Save failed"));
    waitingDlg->show();
    save();
    waitingDlg->success();
    waitingDlg->exec();
    this->mProgItem->m_last = QDateTime::currentDateTime();
    this->mProgItem->m_fsize = dirFileSize(this->mProgItem->mProgDir);
    this->mProgItem->onSetProgram();
}

void ProgEditorWin::UdpSendJson(QJsonObject json) {
    QUdpSocket *tempUdpSocket= new QUdpSocket(this);
    if(!tempUdpSocket->bind(QHostAddress("127.0.0.1"))) {
        QMessageBox::critical(this, tr("Warning"), "udp bind failed");
        return;
    }
    QJsonDocument resultJson;
    resultJson.setObject(json);
    QByteArray byteArray=resultJson.toJson();
    QHostAddress localAddress("127.0.0.1");
    int iSendLength=tempUdpSocket->writeDatagram(byteArray.data(),byteArray.size(),localAddress,2000);
    if(iSendLength != byteArray.size()) {
        char *aa=byteArray.data();
        tempUdpSocket->writeDatagram(&aa[iSendLength],byteArray.size()-iSendLength,localAddress,2000);
    }
    delete tempUdpSocket;
}

void ProgEditorWin::onAddPage() {
    QDateTime now = QDateTime::currentDateTime();
    auto name = now.toString("yyyyMMddhhmmsszzz");
    auto pageDir = mProgItem->mProgDir+"/"+name;
    QDir dir(pageDir);
    if(! dir.exists() && ! dir.mkpath(".")) return;
    QJsonObject attr;
    attr["name"] = name;
    attr["order"] = listPage->count();
    attr["repeat"] = 1;
    attr["validDate"] = QJsonObject{
        {"isValid", false},
        {"start", now.date().toString("yyyy-MM-dd")},
        {"end", now.addSecs(2678400).date().toString("yyyy-MM-dd")}
    };
    attr["plans"] = QJsonArray();
    auto item = new PageListItem(attr, pageDir);
    listPage->addItem(item);
    listPage->setItemWidget(item, item->itemWgt());
    listPage->setCurrentItem(item);
}
