#include "weditprogram.h"
#include "ui_weditprogram.h"
#include "wnewprogram.h"

#include <QSettings>
#include <QFlags>
#include <QMessageBox>
#include <LoUIClass/customprogressindicator.h>
#include <LoUIClass/x_uimsgboxyesnocancel.h>
#include <LoUIClass/x_uimsgboxokcancel.h>
#include <tipdialog.h>
#include <globaldefine.h>
#include <wProgramManager/mconverter.h>
#include <wProgramManager/sendprogramdialog.h>
#include <QGraphicsDropShadowEffect>
wEditProgram::wEditProgram(QString &name, int &w, int &h, QString &remarks, const QString strProgramPath, const QString pRoot, QWidget *parent) :
    LoQMainWindow(parent),
    ui(new Ui::wEditProgram),
    m_strProgramItemPath(strProgramPath),
    m_strSavePath(pRoot),
    m_name(name),
    m_width(w),
    m_height(h),
    m_remarks(remarks)
{

    ui->setupUi(this);
    //this->setWindowFlags(this->windowFlags()&~Qt::WindowMinimizeButtonHint);
    setAttribute(Qt::WA_DeleteOnClose);
    readSettings();
    ui->wMainWnd->setProperty("ssBackground", "dark");
    ui->wStatus ->setProperty("ssBackground", "dark");

    //    // If WA_TranslucentBackground is true, OpenGL can NOT work perfect in the NIVADA.
    //   setAttribute(Qt::WA_TranslucentBackground, false);

    m_title_bar = new LoQWindowTitleBar(m_name, ui->wMainWnd);

    m_tool_bar      = new wMainToolBar();
    m_page_list     = new wPageList(m_strProgramItemPath, m_width, m_height);
    m_drawing_board = new wDrawingBoard(QSizeF(m_width, m_height));
    m_attr_view     = new wAttrView();
    m_attr_view->setProperty("ssType", "progEditor");
    m_attr_view->setProperty("ssName", "pageAttrView");

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

    //    //垂直布局（标题栏，主工具栏，主区域）
    m_pLayout = new QVBoxLayout();
    m_pLayout->addWidget(m_title_bar, 0);
    m_pLayout->addSpacing(1);
    m_pLayout->addWidget(m_tool_bar, 0);
    m_pLayout->addLayout(m_playout_main_area, 1);
    m_pLayout->setSpacing(0);
    m_pLayout->setContentsMargins(0, 0, 0, 0);
    ui->wMainWnd->setLayout(m_pLayout);

    //   connect(m_title_bar, SIGNAL(sigSave()),             this,          SLOT(onSave()));
    connect(m_tool_bar, SIGNAL(sigSave()),             this,          SLOT(onSave()));
    connect(m_tool_bar, SIGNAL(sigSaveAs()),           this,          SLOT(onSaveAs()));
    connect(m_tool_bar, SIGNAL(sigSetting()),          this,          SLOT(onSetting()));
    connect(m_tool_bar, SIGNAL(sigCreateElement(int)), m_drawing_board, SLOT(onCreatElement(int)));
    connect(m_tool_bar, SIGNAL(sigSend()),             this,          SLOT(onSend()));
    connect(m_tool_bar, SIGNAL(sigPreview(int)),           this,          SLOT(onPreview(int)));
    connect(this,SIGNAL(sigProgPlayerQuit()),m_tool_bar, SLOT(OnProgPlayerQuit()));
    //关联左边幻灯片列表窗口切换选中页的信号到两个区域对应的槽函数，1.编辑区 2.幻灯片的属性页
    connect(m_page_list,     SIGNAL(sigPageSelected(wPageItem*)),  m_drawing_board, SLOT(onSlotPageSelected(wPageItem *)));
    connect(m_page_list,     SIGNAL(sigPageSelected(wPageItem*)),  m_attr_view,     SLOT(onSlotPageSelected(wPageItem *)));
    connect(m_page_list,     SIGNAL(sigDeletePageItem(wPageItem*)),  m_drawing_board, SLOT(onClean()));
    //关联编辑区媒体元素选中信号到右边媒体组件属性页的选中槽函数
    connect(m_drawing_board, SIGNAL(sigElementSelected(eObject*)), m_attr_view,     SLOT(onSlotElementSelected(eObject*)));
    m_page_list->Init();
    m_page_list->setCurrentPage(0);

    QGraphicsDropShadowEffect *shadow_effect = new QGraphicsDropShadowEffect(this);
    shadow_effect->setOffset(0, 0);
    //阴影颜色
    shadow_effect->setColor(QColor(38, 78, 119, 127));
    //阴影半径
    shadow_effect->setBlurRadius(8);
    //    ui->wMainWnd->setGraphicsEffect(shadow_effect);
    //    ui->widget->setGraphicsEffect(shadow_effect);
    ui->wMainWnd->layout()->setMargin(6);


    m_drawing_board->setGraphicsEffect(shadow_effect);
    this->m_title_bar->hideMixmumButton();
    m_po= new QProcess(this);


}

wEditProgram::~wEditProgram()
{
    writeSettings();
    delete ui;
    m_title_bar->deleteLater();
    m_tool_bar->deleteLater();
    m_page_list->deleteLater();
    m_drawing_board->deleteLater();
    m_attr_view->deleteLater();
    m_playout_main_area->deleteLater();
    m_pLayout->deleteLater();
    if(m_po!=nullptr)
    {
        m_po->close();
        delete m_po;
    }

}
bool wEditProgram::IsChangedProgram()
{
    wPageList *pl = findChild<wPageList*>();
    return pl->IsChanged();
    //    auto save = QThread::create([pl](){
    //        pl->IsChanged();
    //        QThread::sleep(1);
    //    });
    //    connect(save, SIGNAL(finished()), save,   SLOT(deleteLater()));
    //    connect(save, SIGNAL(finished()), this, SIGNAL(sProgramChanged()));//连接结束信号到节目列表项
    //    save->start();
    //return true;
}
void wEditProgram::closeEvent(QCloseEvent *event)
{
    emit sProgramChanged();
    //判断循环每一个幻灯片，对比对象，即使其中一个参数修改了，只要再次设会原来的值，比较两个对象一直，就不需要保存，只要有其中一个的修改标志位为1，则提醒保存
    if(IsChangedProgram())
    {
        X_UIMsgBoxYesNoCancel *dlg = new X_UIMsgBoxYesNoCancel(tr("Tip Info"),tr("Do you want to save the modifications?"), this);
        int iresult=dlg->exec();
        if(iresult== QDialog::Accepted)
        {
            if(dlg->m_flagSave==1)
            {
                onSave();
                writeSettings();

            }
            else if(dlg->m_flagSave==2)
            {

            }
            event->accept();

        }
        else if(iresult == QDialog::Rejected)
        {
            event->ignore();
        }
    }
    else {
        event->accept();
    }

}
void wEditProgram::onSave()
{
    wPageList *pl = findChild<wPageList*>();
    //显示沙漏光标
    //    QApplication::setOverrideCursor(Qt::WaitCursor);
#if 1
    LoEmptyDialog * dlg = new LoEmptyDialog(this);
    auto save = QThread::create([pl](){
        pl->save();
        QThread::sleep(1);
    });
    dlg->lock(tr("Saving..."),tr("Success"),tr("Save failed"));
    connect(save, SIGNAL(finished()), dlg,    SLOT(unlock()));//显示正在保存提示对话框
    connect(save, SIGNAL(finished()), save,   SLOT(deleteLater()));
    connect(save, SIGNAL(finished()), this, SIGNAL(sProgramChanged()));//连接结束信号到节目列表项
    save->start();
    dlg->exec();
    //恢复沙漏前的光标形状
    //QApplication::restoreOverrideCursor();
#else
    pl->save();
#endif


}
void wEditProgram::Save()
{
    wPageList *pl = findChild<wPageList*>();
    //显示沙漏光标
    //    QApplication::setOverrideCursor(Qt::WaitCursor);
    auto save = QThread::create([pl](){
        pl->save();
        QThread::sleep(1);
    });
    connect(save, SIGNAL(finished()), save,   SLOT(deleteLater()));
    connect(save, SIGNAL(finished()), this, SIGNAL(sProgramChanged()));//连接结束信号到节目列表项
    save->start();



}
void wEditProgram::onSaveAs()
{
    Save();
    TipDialog *dlg2 = new TipDialog(this,ENUM_SAVEAS_DLG);
    connect(dlg2, SIGNAL(sigAcceptData(QString,QString)), this, SLOT(onReNameProgram(QString)));
    if(dlg2->exec() == QDialog::Accepted)
    {

    }
}
void wEditProgram::onReNameProgram(QString strName)
{
    m_strProgramItemPath=m_strSavePath + MACRO_FENGEFU + strName;

    wPageList *pl = findChild<wPageList*>();
    pl->m_strProgramItemPath=m_strProgramItemPath;
    LoEmptyDialog * dlgTip = new LoEmptyDialog(this);
    auto save = QThread::create([pl](){
        pl->saveAs();
        QThread::sleep(1);
    });
    dlgTip->lock(tr("Saving..."),tr("Success"),tr("Save failed"));
    connect(save, SIGNAL(finished()), dlgTip,    SLOT(unlock()));//显示正在保存提示对话框
    connect(save, SIGNAL(finished()), save,   SLOT(deleteLater()));
    connect(save, SIGNAL(finished()), this, SIGNAL(sProgramChanged()));//连接结束信号到节目列表项
    save->start();
    dlgTip->exec();
    close();



    //   wPageList *pl = findChild<wPageList*>();
    //  pl->m_strProgramItemPath=m_strProgramItemPath;
    m_title_bar->RenameTitle(strName);
    emit sProgramSaveAs(strName,QSize(m_width,m_height),m_remarks);

}

void wEditProgram::onSend()
{
    //if(IsChangedProgram())
    onSave();

    LoEmptyDialog * msgbox = new LoEmptyDialog(this);
    //转换节目
    QString m_strConverSaveTmpPath=LoAppConfig::getInstance()->NProgramsLocation();
    auto converter = new mConverter(m_name,m_strConverSaveTmpPath,"" ,this);
    converter->m_usbZipFlag=0;
    //转换结束，发送信号触发converter释放内存
    connect(converter, SIGNAL(finished()),                  converter, SLOT(deleteLater()));
    connect(converter, SIGNAL(finished()),                  msgbox, SLOT(unlock()));
    //链接转换进度信号到进度条槽函数
    connect(converter, SIGNAL(sProgress(QString,int,bool)), msgbox->m_pIndicator,    SLOT(onProgress(QString,int,bool)));
    //链接进度对话框启动信号到转换开始槽函数
    connect(msgbox,    SIGNAL(startUp()),                   converter, SLOT(start()));
    connect(converter, SIGNAL(sigConvertTimerOut()), msgbox,    SLOT(TimerOutUnlock()));//显示正在保存提示对话框
    msgbox->lock(tr("Convertering")+"...",tr("Converter Successed"),tr("Converter TimeOut"));
    msgbox->exec();

    SendProgramDialog *pDlg= new SendProgramDialog(this,m_name,m_strConverSaveTmpPath);
    pDlg->exec();

    //发送post命令，将任务发送到控制卡


    //控制卡主动向指定的连接上报进度


    //   QMessageBox::critical(this, tr("Waring"), tr("no finished send function !"));
}
void wEditProgram::onPreview(int iState)
{
   if(iState==0)
    {
        if(IsChangedProgram())
        {
            onSave();
        }
        else {

        }
        LoEmptyDialog * msgbox = new LoEmptyDialog(this);
        //转换节目
        QString m_strConverSaveTmpPath=LoAppConfig::getInstance()->NProgramsLocation();
        auto converter = new mConverter(m_name,m_strConverSaveTmpPath,"" ,this);
        converter->m_usbZipFlag=0;
        //转换结束，发送信号触发converter释放内存
        connect(converter, SIGNAL(finished()),                  converter, SLOT(deleteLater()));
        connect(converter, SIGNAL(finished()),                  msgbox, SLOT(unlock()));
        //   connect(converter, SIGNAL(finished()),                  this, SLOT(PreviewStart()));
        //链接转换进度信号到进度条槽函数
        connect(converter, SIGNAL(sProgress(QString,int,bool)), msgbox->m_pIndicator,    SLOT(onProgress(QString,int,bool)));
        //链接进度对话框启动信号到转换开始槽函数
        connect(msgbox,    SIGNAL(startUp()),                   converter, SLOT(start()));
        connect(converter, SIGNAL(sigConvertTimerOut()), msgbox,    SLOT(TimerOutUnlock()));//显示正在保存提示对话框
        msgbox->lock(tr("Generate preview data")+"...",tr("Ready"),tr("Generate TimeOut"));
        msgbox->exec();
        QString sWidth=QString::number(m_width);
        QString sHeight=QString::number(m_height);
        QString strAppPath=QApplication::applicationDirPath();
        strAppPath.replace(MACRO_DANYINFANXIEGAN, MACRO_DANYINXIEGAN);
        QString cmd=strAppPath+"/prog_player/bin/java.exe";
        QString strProgram=strAppPath+"/prog_player/prog-player.jar";
        QString strCommand="\""+cmd+"\" -jar \""+strProgram+"\"";

        QString strX=" -x 0";
        QString strY=" -y 0";
        QString strW=" -w "+sWidth;
        QString strH=" -h "+sHeight;
        QString strProg=" -prog \""+m_strProgramItemPath+"_tmp\"";

        if(m_po!=nullptr)
        {
            //m_po->start(strCommand+" -x 0 -y 0 -w 320 -h 240 -prog \""+m_strProgramItemPath+"_tmp\"");
            //m_po->start(cmd,argu);
             QString strAppPath=QApplication::applicationDirPath();
            strAppPath.replace(MACRO_DANYINFANXIEGAN, MACRO_DANYINXIEGAN);
            m_po->setWorkingDirectory(strAppPath+"/prog_player/bin");
            //QMessageBox::critical(this, tr("Waring"), strAppPath+"/bin");

            m_po->start(strCommand+strX+strY+strW+strH+strProg);
           // m_po->waitForStarted();
           // m_po->waitForFinished();
           // connect(m_po,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(StopPreview()));
            connect(m_po,static_cast<void(QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),[=](int exitCode,QProcess::ExitStatus exitStatus){emit sigProgPlayerQuit();});
           // QString getStr=QString(m_po->readAllStandardOutput());
           // QMessageBox::information(this,tr("Tip"),getStr);

        }
    }
    else {
       if(m_po!=nullptr)
       {
             m_po->close();

       }
       // QMessageBox::critical(this, tr("Waring"), "close");

    }



}
void wEditProgram::StopPreview()
{
    QMessageBox::information(this,tr("Tip"),"StopPreview");
}
void wEditProgram::UdpSendJson(QJsonObject json)
{
    QUdpSocket *tempUdpSocket= new QUdpSocket(this);
    if(!tempUdpSocket->bind(QHostAddress("127.0.0.1")))
    {
         QMessageBox::critical(this, tr("Waring"), "udp bind failedd");
        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);
    }
    else {

    }
    delete tempUdpSocket;

}

void wEditProgram::onSetting()
{
    wNewProgram *dlg = new wNewProgram(m_name, QSize(m_width, m_height), m_remarks, this, true);
    connect(dlg, SIGNAL(sigAcceptData(QString,QSize,QString)), this, SLOT(onEditHead(QString,QSize,QString)));
    dlg->exec();
}

void wEditProgram::onEditHead(QString name, QSize size, QString remarks)
{
    Q_UNUSED(name);
    m_width = size.width();
    m_height = size.height();
    m_remarks = remarks;
    emit sProgramChanged();

    wPageList     *pl = findChild<wPageList*>();
    wDrawingBoard *db = findChild<wDrawingBoard*>();
    db->setRes(m_width, m_height);
    pl->setRes(m_width, m_height);
}


void wEditProgram::readSettings()
{
    //return;
    LoAppConfig *cfg = LoAppConfig::getInstance();
    QSettings *settings = new QSettings(cfg->OrganizationName(), cfg->ApplicationName());
    QVariant iMaxFlag=settings->value("WindowMaximized");
    //QPoint pos = settings->value("pos1", QPoint(-1, 0)).toPoint();
    QSize size = settings->value("size", QSize(1024, 768)).toSize();
    if (iMaxFlag.toString() =="1")//是最大化状态
    {
        setWindowState(Qt::WindowMaximized);
    }
    else
    {
        resize(size);
        //if(pos.x() != -1)
        //     move(pos);
    }
    delete settings;
}

void wEditProgram::writeSettings()
{
    LoAppConfig *cfg = LoAppConfig::getInstance();
    QSettings *settings = new QSettings(cfg->OrganizationName(), cfg->ApplicationName());
    if (windowState() & Qt::WindowMaximized)//是最大化状态
    {
        settings->setValue("WindowMaximized", "1");
    }
    else {
        settings->setValue("pos1", this->pos());
        settings->setValue("size", QSize(this->width(), this->height()));
        settings->setValue("WindowMaximized", "0");

    }
    delete settings;
}

