#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QWidget>
#include <QByteArray>
#include <QDateTime>

enum ShellViewFlags{
    ShellViewFlags_Login    =   0x0001,
    ShellViewFlags_Preview  =   0x0002,
    ShellViewFlags_SaveMp4  =   0x0004,
    ShellViewFlags_SaveStream  =   0x0008,
};

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow){
    ui->setupUi(this);

    m_flags=0;
    m_device = new Device(this);
    connect(m_device, &Device::frameRecved, this, &MainWindow::device_frameRecved);
    connect(m_device, &Device::gpioInputChanged, this, &MainWindow::device_gpioInputChanged);

    //0
    deviceCanvas = new DeviceCanvas(this);

    //1
    btnUrl = new QPushButton("Url",this);
    connect(btnUrl, &QPushButton::clicked, this, &MainWindow::btnUrl_clicked);
    txtUrl = new QLineEdit(this);

    //2
    btnLogin = new QPushButton("Login",this);
    connect(btnLogin, &QPushButton::clicked, this, &MainWindow::btnLogin_clicked);

    btnPlayVideo = new QPushButton("PlayVideo",this);
    connect(btnPlayVideo, &QPushButton::clicked, this, &MainWindow::btnPlayVideo_clicked);

    btnPlayTemp = new QPushButton("PlayTemp",this);
    connect(btnPlayTemp, &QPushButton::clicked, this, &MainWindow::btnPlayTemp_clicked);

    btnStop = new QPushButton("Stop",this);
    connect(btnStop, &QPushButton::clicked, this, &MainWindow::btnStop_clicked);

    //3
    btnSaveJpg = new QPushButton("SaveJpg",this);
    connect(btnSaveJpg, &QPushButton::clicked, this, &MainWindow::btnSaveJpg_clicked);

    btnSaveMp4 = new QPushButton("SaveMp4",this);
    connect(btnSaveMp4, &QPushButton::clicked, this, &MainWindow::btnSaveMp4_clicked);

    btnSaveStream = new QPushButton("SaveStream",this);
    connect(btnSaveStream, &QPushButton::clicked, this, &MainWindow::btnSaveStream_clicked);

    cmbTest = new QComboBox(this);
    cmbTest->addItem("Set Measure");
    cmbTest->addItem("Clear Measure");
    cmbTest->addItem("Manual FFC");

    btnTest = new QPushButton("Test",this);
    connect(btnTest, &QPushButton::clicked, this, &MainWindow::btnTest_clicked);

    //5
    txtEcho = new QTextEdit(this);

    //
    initUI();
}
MainWindow::~MainWindow(){
    delete ui;
}

void xSetGeometry(QWidget* widget,  double x, double y, double width, double height){
    int dx = width / 6;
    int dy = height / 8;
    widget->setGeometry(x + dx, y + dy, width - 2 * dx, height - 2 * dy);
}

void MainWindow::resizeEvent(QResizeEvent *event){
    initUI();
}

void MainWindow::initUI(){
    double width=this->width();
    double height=this->height();

    //
    double xarr[] = { 1, 1, 1, 1, 1 };
    double yarr[] = { 12, 1, 1, 1, 2 };
    double dx = width / 5.0;
    double dy = height / 17.0;

    //00
    double x, y;
    x = 0; y = 0; height = dy * yarr[0];
    deviceCanvas->setGeometry(x, y, width, height);

    //10,11
    y += height; width = dx * xarr[0]; height = dy * yarr[1];
    xSetGeometry(btnUrl, x, y, width, height);

    x += width; width =dx * (xarr[1] + xarr[2] + xarr[3] + xarr[4]);
    txtUrl->setGeometry(x, y, width, height);

    //20,
    x = 0; y += height; width = dx * xarr[0]; height = dy * yarr[2];
    xSetGeometry(btnLogin, x, y, width, height);

    x += width; width = dx * xarr[1];
    xSetGeometry(btnPlayVideo, x, y, width, height);

    x += width; width = dx * xarr[2];
    xSetGeometry(btnPlayTemp, x, y, width, height);

    x += width; width = dx * xarr[3];
    xSetGeometry(btnStop, x, y, width, height);

    //30
    x = 0; y += height; width = dx * xarr[0]; height =dy * yarr[3];
    xSetGeometry(btnSaveJpg, x, y, width, height);

    x += width; width = dx * xarr[1];
    xSetGeometry(btnSaveMp4, x, y, width, height);

    x += width; width = dx * xarr[2];
    xSetGeometry(btnSaveStream, x, y, width, height);

    x += width; width = dx * xarr[3];
    xSetGeometry(cmbTest, x, y, width, height);

    x += width; width = dx * xarr[4];
    xSetGeometry(btnTest, x, y, width, height);

    //40
    x = 0; y += height; width = dx*5; height = dy * yarr[4];
    txtEcho->setGeometry(x, y, width, height);
}

/*********************************************************************
 *
 *
 *
 *
 * ******************************************************************/
void MainWindow::device_frameRecved(int errorCode, DataFrame* dataFrame){
    if(0==errorCode){
        deviceCanvas->xUpdateData(dataFrame);
    }else{
        txtEcho->setText(QString::asprintf("errorCode %d\n", errorCode));
    }
}

void MainWindow::device_gpioInputChanged(int oldValue, int newValue){
     txtEcho->insertPlainText(QString::asprintf("gpioInputChanged, %d -> %d\n", oldValue,newValue));
}

/*********************************************************************
 *
 *
 * discover
 *
 * ******************************************************************/
void MainWindow::btnUrl_clicked(){
    DiscoverCameraResp2 *dcrs =  Yoseen_DiscoverCameras(xxxdiscoverflags_broadcast);

    //
    QString info;
    if (dcrs == nullptr) {
        info = "discover no cameras";
    }
    else {
        info = "discover cameras:";
        DiscoverCameraResp2* pdcr=dcrs;
        char tmpStr[32];
        while(pdcr) {
            u32 ip = pdcr->CameraIp;
            u8* p = (u8*)&ip;
            sprintf(tmpStr,"%d.%d.%d.%d; ", *(p+3), *(p+2), *(p+1), *p);
            info.append(tmpStr);
            pdcr = pdcr->pNext;
        }
    }
    txtEcho->setText(info);

    //
    Yoseen_DiscoverCamerasFree(&dcrs);
}

/*********************************************************************
 *
 *
 * login, preview
 *
 * ******************************************************************/
void MainWindow::btnLogin_clicked(){
    int ret;
    QString info;
    if(0==(m_flags&ShellViewFlags_Login)) {
        QString str = txtUrl->text();
        QByteArray ba = str.toLocal8Bit();
        char* ip = ba.data();
        ret = m_device->login(ip);
        info = "login, ret " + QString::number(ret);
        if(0==ret)
        {
            m_flags=ShellViewFlags_Login;
            btnLogin->setText("Logout");
        };

    }else{
        m_device->logout();
        btnLogin->setText("Login");
        m_flags=0;
        info = "logout, ret " + QString::number(ret);
    }

    txtEcho->setText(info);
}

void MainWindow::btnPlayVideo_clicked(){
    if( 0==(m_flags&ShellViewFlags_Login))return;

    int ret;
    ret= m_device->startPreivew(xxxdatatype_video);
    if(0==ret)
    {
        int w = m_device->getVideoWidth();
        int h = m_device->getVideoHeight();
        deviceCanvas->xBeginUpdate(w, h);
        m_flags|=ShellViewFlags_Preview;
    }

    //
    QString info = "startPreivew, video, ret " + QString::number(ret);
    txtEcho->setText(info);
}

void MainWindow::btnPlayTemp_clicked(){
    if( 0==(m_flags&ShellViewFlags_Login))return;

    int ret;
    ret= m_device->startPreivew(xxxdatatype_temp);
    if(0==ret){
        int w = m_device->getTempWidth();
        int h = m_device->getTempHeight();
        deviceCanvas->xBeginUpdate(w, h);
        m_flags|=ShellViewFlags_Preview;
    }

    //
    QString info = "startPreivew, temp, ret " + QString::number(ret);
    txtEcho->setText(info);
}

void MainWindow::btnStop_clicked(){
    if( 0==(m_flags&ShellViewFlags_Preview))return;
    deviceCanvas->xEndUpdate();
    m_device->stopPreview();
    m_flags&=(~ShellViewFlags_Preview);

    //
    QString info = "stopPreview";
    txtEcho->setText(info);
}

/*********************************************************************
 *
 *
 * save
 *
 * ******************************************************************/
QString getFilename(QString suffix){
    QDateTime dt =QDateTime::currentDateTime();
    QString fn = dt.toString("yyyyMMdd_hhmmss") + suffix;
    return fn;
}

void MainWindow::btnSaveJpg_clicked(){
    if( 0==(m_flags&ShellViewFlags_Login))return;
    QString fn=getFilename(".jpg");
    QByteArray ba=fn.toLocal8Bit();
    int ret = m_device->saveJpg(ba.data());
    if(0==ret){
        txtEcho->setText("save, "+fn);
    }
}

void MainWindow::btnSaveMp4_clicked(){
    int ret;
    if(0==(m_flags&ShellViewFlags_SaveMp4)) {
        //
        QString fn=getFilename(".mp4");
        QByteArray ba=fn.toLocal8Bit();
        ret = m_device->beginSave(ba.data(), xxxmediafile_mp4);
        if(0==ret){
            m_flags|=ShellViewFlags_SaveMp4;
            btnSaveMp4->setText("EndSaveMp4");
            txtEcho->setText("save, "+fn);
        }
    }else{
        m_device->endSave(xxxmediafile_mp4);
        m_flags&=(~ShellViewFlags_SaveMp4);
        btnSaveMp4->setText("SaveMp4");
    }
}

void MainWindow::btnSaveStream_clicked(){
    int ret;
    if(0==(m_flags&ShellViewFlags_SaveStream)) {
        //
        QString fn=getFilename(".stream");
        QByteArray ba=fn.toLocal8Bit();
        ret = m_device->beginSave(ba.data(), xxxmediafile_stream);
        if(0==ret){
            m_flags|=ShellViewFlags_SaveStream;
            btnSaveStream->setText("EndSaveStream");
            txtEcho->setText("save, "+fn);
        }
    }else{
        m_device->endSave(xxxmediafile_stream);
        m_flags&=(~ShellViewFlags_SaveStream);
        btnSaveStream->setText("SaveStream");
    }
}

/*********************************************************************
 *
 * test
 *
 *
 * ******************************************************************/
#include <YoseenSDK/YoseenAlg_Mea.h>
void test_SetMeasure(int userHandle, int width, int height){
    int ret;

    //make template
    MeasureTemplate measureTemplate = {};
    MeasureTemplateHead* mth = &measureTemplate.Head;
    mth->Width = width;
    mth->Height = height;

    //
    xxxshield* shd = &measureTemplate.ShieldArray[0];
    u16* xydata = shd->xydata;
    xydata[0] = width / 8; xydata[1] = height / 8;
    xydata[2] = width * 2 / 8; xydata[3] = height / 8;
    xydata[4] = width * 2 / 8; xydata[5] = height * 2 / 8;
    xydata[6] = width / 8; xydata[7] = height * 2 / 8;
    mth->ShieldFlags = 0x01;

    //
    xxxmeasure* mea = &measureTemplate.GMO;
    mea->measureflags = xxxmeasureflags_track_max | xxxmeasureflags_plot_max;

    mea = &measureTemplate.LMOArray[0];
    xydata = mea->xydata;
    mea->measureflags = xxxmeasureflags_track_max |xxxmeasureflags_plot_max;
    mea->emmi = 97;
    mea->measuretype = xxxmeasuretype_polygon;

    mea->points = 4;
    xydata[0] = width *3/ 8; xydata[1] = height *4/ 8;
    xydata[2] = width * 5 / 8; xydata[3] = height *4/ 8;
    xydata[4] = width * 5 / 8; xydata[5] = height * 7 / 8;
    xydata[6] = width *3/ 8; xydata[7] = height * 7 / 8;
    mth->LMOFlags = 0x01;

    //upload template
    ret = Yoseen_UploadMem(userHandle, xxxcameramem_measure, &measureTemplate, sizeof(MeasureTemplate));
}

void test_ClearMeasure(int userHandle, int width, int height){
    int ret;

    //make template
    MeasureTemplate measureTemplate = {};
    MeasureTemplateHead* mth = &measureTemplate.Head;
    mth->Width = width;
    mth->Height = height;

    //upload template
    ret = Yoseen_UploadMem(userHandle, xxxcameramem_measure, &measureTemplate, sizeof(MeasureTemplate));
}

void test_ManualFFC(int userHandle){
    Ctl ctl={};
    ctl.Type=CtlType_ManualFFC;
    int ret;
    ret=Yoseen_SendControl(userHandle, &ctl);
}

void MainWindow::btnTest_clicked(){
    if( 0==(m_flags&ShellViewFlags_Login))return;

    int userHandle=m_device->getUserHandle();
    int tempWidth=m_device->getTempWidth();
    int tempHeight=m_device->getTempHeight();

    int ret;
    switch(cmbTest->currentIndex()){
    case 0:
        test_SetMeasure(userHandle, tempWidth,tempHeight);
        break;
    case 1:
        test_ClearMeasure(userHandle, tempWidth,tempHeight);
        break;
    case 2:
        test_ManualFFC(userHandle);
        break;
    default:
        break;
    }

}


