#include "gddcdlg.h"
#include "ui_gddcdlg.h"
#include <QDateTime>
#include <QDir>
#include <QNetworkInterface>
#include <QTabBar>
#include <QTabWidget>
#include <iostream>
#include <windows.h>
#include <wtsapi32.h>

#pragma comment(lib, "Wtsapi32.lib")
using namespace std;
DWORD GetmPid(LPCWSTR ProcessName) {
  PWTS_PROCESS_INFOW wts;
  DWORD Count;
  DWORD i = 0;

  BOOL result =
      WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &wts, &Count);
  if (result == 0) {
    cout << "WTSEnumerateProcessesW Error" << endl;

    return 1;
  }
  cout << "WTSEnumerateProcessesW Success" << endl;
  for (i; i < Count; i++) {
    if (lstrcmpiW(wts[i].pProcessName, ProcessName) == 0) {
      DWORD pid = wts[i].ProcessId;
      cout << "find pid:" << pid << endl;

      return pid;
      break;
    }
  }

  WTSFreeMemory(wts);
}

#define CONFIG_PATH "config.ini"
#define CMDPAGEHIGHT 210
#define STATEPAGEWIDTH 250

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

  initWindow();
  initParam();
  initSignalSlot();
}

GDDCdlg::~GDDCdlg() {
  // 停止所有通信
  stopPushURL();
  stopConnectURL1();
  stopConnectURL2();
  stopConnectSerialCtrl();
  stopConnectUDPCtrl();
  stopConnectTCPCtrl();

  delete m_DlgGDDCSet;
  delete m_GDDCCmdDlg;
  delete m_GDDCStateDlg;
  delete ui;
}

// 初始化window
void GDDCdlg::initWindow() {
  QPalette palette;
  // 设置主窗口背景颜色
  palette.setColor(QPalette::Window, QColor(50, 50, 50));
  this->setPalette(palette);
  // 嵌入到主窗口
  setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
  hide();

  m_DlgGDDCSet = new GDDCSet(this);
  m_DlgGDDCSet->setWindowFlags(Qt::Dialog);
  m_DlgGDDCSet->setWindowModality(Qt::WindowModal); // 设置为模态对话框
  m_GDDCCmdDlg = new GDDCCmdDlg(this);
  m_GDDCStateDlg = new GDDCStateInfo(this);
  ui->pushButShowStatePage->setIcon(QIcon(":/res/right.png"));
  ui->pushButShowCmdPage->setIcon(QIcon(":/res/down.png"));

  ui->WgtffmpegVideo->setVedioSaveFileDirPath("./Video");
}

// 初始化参数
void GDDCdlg::initParam() {
  pointSelectionTracking = false;
  Is_openVideo = false;
  isCmdPageShow = true;
  isStatePageShow = true;
  detectionAreaSetting = false;
  connectFlag.resize(12, false);
}

// 初始化信号与槽
void GDDCdlg::initSignalSlot() {
  /*******有四种方式*******/
  // 方式一
  connect(ui->pushButtonSet, SIGNAL(clicked()), this,
          SLOT(pushButtonSet_clicked()));
  // 方式二
  // connect(ui->pushButtonSet,&QPushButton::clicked,this,&::GDDCdlg::pushButtonSet_clicked);
  // 方式三
  // connect(ui->pushButtonSet,
  // QOverload<bool>::of(&QPushButton::clicked),this,&::GDDCdlg::pushButtonSet_clicked);
  // 方式四
  // connect(ui->pushButtonSet,&QPushButton::clicked,[=](bool
  // check){pushButtonSet_clicked();});
  connect(ui->pushButShowCmdPage, SIGNAL(clicked()), this,
          SLOT(pushButShowCmdPage_clicked())); // 控制页面隐藏显示按钮
  connect(ui->pushButShowStatePage, SIGNAL(clicked()), this,
          SLOT(pushButShowStatePage_clicked())); // 状态页面隐藏显示按钮
  connect(m_DlgGDDCSet, SIGNAL(SignalStartConnect(int)), this,
          SLOT(startConnect(int))); // 开始连接
  connect(m_DlgGDDCSet, SIGNAL(SignalStopConnect(int)), this,
          SLOT(stopConnect(int))); // 停止连接
}

// 槽函数开始连接
void GDDCdlg::startConnect(int type) {
  switch (type) {
  case 1: // 播放视频1
    stopConnectURL2();
    startConnectURL1();
    break;
  case 2: // 播放视频2
    stopConnectURL1();
    startConnectURL2();
    break;
  case 3: // 串口控制
    startConnectSerialCtrl();
    break;
  case 4: // UDP控制
    stopConnectTCPCtrl();
    startConnectUDPCtrl();
    break;
  case 5: // TCP控制
    stopConnectUDPCtrl();
    startConnectTCPCtrl();
    break;
  case 6: // 视频(1)推流
    startPushURL();
    break;
  default:
    break;
  }
}

// 槽函数停止连接
void GDDCdlg::stopConnect(int type) {
  switch (type) {
  case 1:
    stopConnectURL1();
    break;
  case 2:
    stopConnectURL2();
    break;
  case 3:
    stopConnectSerialCtrl();
    break;
  case 4:
    stopConnectUDPCtrl();
    break;
  case 5:
    stopConnectTCPCtrl();
    break;
  case 6:
    stopPushURL();
    break;
  default:
    break;
  }
}
// bool GDDCdlg::eventFilter(QObject *watched, QEvent *event)
// {
//     qDebug() << this->geometry().x();
//     qDebug() << this->geometry().y();

//     QPoint sPoint2=QCursor::pos();
//     qDebug()<<"相对于屏幕坐标2:"<<"("<<sPoint2.rx()<<","<<sPoint2.ry()<<")";

//     QPoint windowPoint=this->mapFromGlobal(sPoint2);
//     qDebug()<<"相对于窗口坐标:"<<"("<<windowPoint.rx()<<","<<windowPoint.ry()<<")";

//     return true;

// }
// 鼠标左键
void GDDCdlg::mousePressEvent(QMouseEvent *event) {
  // 如果鼠标左键按下
  if (event->type() == QEvent::MouseButtonPress) {
    // AI检测区域设置
    if (m_GDDCCmdDlg->detectionAreaSetting == true) {
      QPointF sPoint1 = event->globalPosition();
      sPoint1 = QCursor::pos();
      QPointF widgetPoint = ui->WgtffmpegVideo->mapFromGlobal(sPoint1);
      double a = ui->WgtffmpegVideo->width();
      double b = ui->WgtffmpegVideo->height();
      double dir = 1920 / a * widgetPoint.rx() - 960;
      double pitch = -(1080 / b * widgetPoint.ry() - 540);
      m_GDDCCmdDlg->setAIDetcLineEditText(QString::number((int)dir),
                                          QString::number((int)pitch));
    }
    // 目标跟踪
    if (m_GDDCCmdDlg->pointSelectionTracking == true) {
      QPointF sPoint1 = event->globalPosition();
      QPointF widgetPoint = ui->WgtffmpegVideo->mapFromGlobal(sPoint1);
      double a = ui->WgtffmpegVideo->width();
      double b = ui->WgtffmpegVideo->height();
      double dir = 1920 / a * widgetPoint.rx() - 960;
      double pitch = -(1080 / b * widgetPoint.ry() - 540);
      std::byte buffer[10];
      buffer[0] = (std::byte)0x3A;
      buffer[1] = (std::byte)(dir);
      buffer[2] = (std::byte)((int)dir >> 8);
      buffer[3] = (std::byte)pitch;
      buffer[4] = (std::byte)((int)pitch >> 8);
      buffer[5] = (std::byte)0x00;
      buffer[6] = (std::byte)0x00;
      buffer[7] = (std::byte)0x00;
      buffer[8] = (std::byte)0x00;
      buffer[9] = (std::byte)0x00;

      // 发送5次
      m_GDDCCmdDlg->sendCurDate(buffer, 3);
    }
  }
}
// 鼠标移动
void GDDCdlg::mouseMoveEvent(QMouseEvent *event) {
  if (m_GDDCCmdDlg->detectionAreaSetting == true) {
    // qDebug() << this->geometry().x();
    // qDebug() << this->geometry().y();
    QPointF sPoint1 = event->globalPosition();
    // qDebug()<<"相对于屏幕坐标1:"<<"("<<sPoint1.rx()<<","<<sPoint1.ry()<<")";

    QPointF sPoint2 = QCursor::pos();
    // qDebug()<<"相对于屏幕坐标2:"<<"("<<sPoint2.rx()<<","<<sPoint2.ry()<<")";

    QPointF windowPoint = this->mapFromGlobal(sPoint2);
    // qDebug()<<"相对于窗口坐标:"<<"("<<windowPoint.rx()<<","<<windowPoint.ry()<<")";

    QPointF widgetPoint = ui->WgtffmpegVideo->mapFromGlobal(sPoint1);
    // qDebug()<<"相对于控件坐标:"<<"("<<widgetPoint.rx()<<","<<widgetPoint.ry()<<")";

    // 更新LineEdit信息
    double a = ui->WgtffmpegVideo->width();
    double b = ui->WgtffmpegVideo->height();
    double dir = 1920 / a * widgetPoint.rx() - 960;
    double pitch = -(1080 / b * widgetPoint.ry() - 540);
    m_GDDCCmdDlg->setAIDetcLineEditText(QString::number((int)dir),
                                        QString::number((int)pitch));
  }
}
// 区域重绘
void GDDCdlg::resizeEvent(QResizeEvent *event) {
  resizeUI(); // 重新设置布局
}
// 重新设置布局
void GDDCdlg::resizeUI() {
  /* -------------->x
   * | (0,0)
   * |
   * |
   * |
   * |
   * ↓ y
   */
  double GDDCPageHeight = (double)(this->height());
  double GDDCPageWidth = (double)(this->width());
  // qDebug()<<"宽度,高度:"<<GDDCPageHeight<<GDDCPageWidth;

  /******控制区位置和大小设置*****/
  double cmdAreaHeight;
  double cmdAreaWidth;
  if (isStatePageShow) {
    cmdAreaWidth = GDDCPageWidth - STATEPAGEWIDTH;
  } else {
    cmdAreaWidth = GDDCPageWidth;
  }
  if (isCmdPageShow) {
    cmdAreaHeight = CMDPAGEHIGHT;
  } else {
    cmdAreaHeight = 0;
  }
  m_GDDCCmdDlg->setGeometry(0, GDDCPageHeight - cmdAreaHeight,
                            (int)cmdAreaWidth, (int)cmdAreaHeight);
  m_GDDCCmdDlg->setTabWidgetGeometry(0, 0, cmdAreaWidth, cmdAreaHeight);

  /*********状态区位置和大小设置***********/
  double stateAreaHeight = GDDCPageHeight;
  double stateAreaWidth;
  if (isStatePageShow) {
    stateAreaWidth = STATEPAGEWIDTH;
  } else {
    stateAreaWidth = 0;
  }
  m_GDDCStateDlg->setGeometry(GDDCPageWidth - stateAreaWidth, 0, stateAreaWidth,
                              stateAreaHeight);
  m_GDDCStateDlg->setTableViewGeometry(0, 0, stateAreaWidth, stateAreaHeight);

  /*******视频区位置和大小设置********/
  double VideoAreaHeight = GDDCPageHeight - cmdAreaHeight; // 视频区高度
  double VideoAreaWidth = GDDCPageWidth - stateAreaWidth;  // 视频区宽度
  // //高度值相对比较大
  // if(VideoAreaHeight*16>VideoAreaWidth*9)
  // {
  //     double setVideoAreaWidth = VideoAreaWidth;//等于吊舱页面宽度-状态区高度
  //     double setVideoAreaHeight = VideoAreaWidth*9/16;
  //     ui->WgtffmpegVideo->setGeometry(0,0.5*(VideoAreaHeight-setVideoAreaHeight),(int)setVideoAreaWidth,(int)setVideoAreaHeight);
  // }
  // //宽度值相对比较大
  // else
  // {
  //     double setVideoAreaHeight =
  //     VideoAreaHeight;//等于吊舱页面高度-控制区高度 double setVideoAreaWidth
  //     = VideoAreaHeight*16/9;
  //     ui->WgtffmpegVideo->setGeometry(0.5*(VideoAreaWidth-setVideoAreaWidth),0,(int)setVideoAreaWidth,(int)setVideoAreaHeight);
  // }
  ui->WgtffmpegVideo->setGeometry(20, 20, (int)VideoAreaWidth,
                                  (int)VideoAreaHeight);

  /**************设置按钮****************/
  ui->pushButtonSet->setGeometry(GDDCPageWidth - stateAreaWidth - 45, 0, 40,
                                 40);

  /**********控制页显示隐藏按钮********/
  ui->pushButShowCmdPage->setGeometry(
      cmdAreaWidth * 0.5, GDDCPageHeight - cmdAreaHeight - 15, 50, 15);
  ui->pushButShowCmdPage->raise();

  /**********状态页显示隐藏按钮********/
  ui->pushButShowStatePage->setGeometry(GDDCPageWidth - stateAreaWidth - 15,
                                        (stateAreaHeight - cmdAreaHeight) * 0.5,
                                        15, 50);
  ui->pushButShowStatePage->raise();
}

void GDDCdlg::setGlobalSetMap(
    std::unordered_map<QString, settingStruct> &gSetMap) {
  if (m_DlgGDDCSet) {
    m_DlgGDDCSet->initPullURL(gSetMap["光电吊舱"].net.remoteIp);
  }
}

// 定时器处理
void GDDCdlg::GDDCControlTimeOut() {
  if (m_GDDCCmdDlg->sendTimes > 0) { // 优先发送次数指令
    m_GDDCCmdDlg->sendTimes -= 1;

    // UDP控制
    if (connectFlag[3]) {
      udpSocket->writeDatagram(m_GDDCCmdDlg->m_DCcmdBuffer,
                               m_DlgGDDCSet->m_myPairNetwork.getRemoteAddr(),
                               m_DlgGDDCSet->m_myPairNetwork.getRemotePort());
    }
    // TCP控制

    // 串口控制

    if (m_GDDCCmdDlg->sendTimes == 0) {
      m_GDDCCmdDlg->clearTJDCCmdBuffer();
    }
  } else { // 发送常发帧或长按指令
    m_GDDCCmdDlg->UpdateDataTJDC();
    // UDP控制
    if (connectFlag[3]) {
      udpSocket->writeDatagram(m_GDDCCmdDlg->m_DCcmdBuffer,
                               m_DlgGDDCSet->m_myPairNetwork.getRemoteAddr(),
                               m_DlgGDDCSet->m_myPairNetwork.getRemotePort());
    }

    // TCP控制

    // 串口控制
  }
}

// 播放视频1
void GDDCdlg::startConnectURL1() {
  if (!connectFlag[0]) {
    connectFlag[0] = true;
    ffmpegvideoDlg *videoDlg = ui->WgtffmpegVideo;
    // 开始拉流
    videoDlg->m_flowType = m_DlgGDDCSet->m_FlowType;
    videoDlg->setStreamIP(m_DlgGDDCSet->m_playURL1);
    videoDlg->setPlayVideo(true);
    // ui->WgtffmpegVideo->play(m_DlgGDDCSet->m_playURL1);
  }
}

// 关闭视频1
void GDDCdlg::stopConnectURL1() {
  if (connectFlag[0]) {
    connectFlag[0] = false;
    // Is_openVideo = false;
    // ui->WgtffmpegVideo->m_PlayStatus = Is_openVideo;
    ui->WgtffmpegVideo->setPlayVideo(false);
    // ui->WgtffmpegVideo->stop();
  }
}

// 播放视频2
void GDDCdlg::startConnectURL2() {
  if (!connectFlag[1]) {
    connectFlag[1] = true;
  }
}

// 关闭视频2
void GDDCdlg::stopConnectURL2() {
  if (connectFlag[1]) {
    connectFlag[1] = false;
  }
}

void GDDCdlg::startConnectSerialCtrl() {
  if (!connectFlag[2]) {
    connectFlag[2] = true;
  }
}

void GDDCdlg::stopConnectSerialCtrl() {
  if (connectFlag[2]) {
    connectFlag[2] = false;
  }
}

// 开始UDP控制通信
void GDDCdlg::startConnectUDPCtrl() {
  if (!connectFlag[3]) {
    /*启动定时器*/
    GDDCControlTimer = new QTimer();
    GDDCControlTimer->setInterval(100);
    connect(GDDCControlTimer, &QTimer::timeout, this,
            [=]() { GDDCControlTimeOut(); });
    GDDCControlTimer->start();

    // 创建udp socket对象
    udpSocket = new QUdpSocket(this);
    /*接收*/
    // QList<QHostAddress> ipAddressesList =
    // QNetworkInterface::allAddresses();//获取本机ip
    udpSocket->bind(m_DlgGDDCSet->m_myPairNetwork.getLocalPort());
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(UDPMessageReceive()));
    connectFlag[3] = true;
  }
}

// 停止UDP控制通信
void GDDCdlg::stopConnectUDPCtrl() {
  if (connectFlag[3]) {
    // 关闭定时器
    GDDCControlTimer->stop();
    delete GDDCControlTimer;
    udpSocket->abort(); // 关闭套接字,并丢缓冲区中的所有待处理数据
    delete udpSocket;
    connectFlag[3] = false;
  }
}

// 开始TCP控制通信
void GDDCdlg::startConnectTCPCtrl() {
  if (!connectFlag[4]) {
    connectFlag[4] = true;
  }
}

// 停止TCP控制通信
void GDDCdlg::stopConnectTCPCtrl() {
  if (connectFlag[4]) {
    connectFlag[4] = false;
  }
}

// 开始视频推流
void GDDCdlg::startPushURL() {
  if (!connectFlag[5]) {

    // //方式1:命令行推流
    // process = new QProcess();
    // connect(process, &QProcess::readyReadStandardOutput, this, [=]() mutable
    // {
    //   QString Output = process->readAllStandardOutput();
    //   qDebug() << "Output:" << Output;
    // });
    // connect(process, &QProcess::readyReadStandardError, this, [=]() mutable {
    //   QString Error = process->readAllStandardError();
    //   qDebug() << "Error Output:" << Error;
    // });

    // // process->start("cmd",QStringList()<<"/c"<<"ffmpeg -i
    // // rtmp://liteavapp.qcloud.com/live/liteavdemoplayerstreamid -c copy -f
    // flv
    // // rtmp://182.92.130.23/app/test");

    // QStringList m_cmd;
    // QString str;
    // // str = "ffmpeg -i " + m_DlgGDDCSet->m_playURL1 + " -c copy -f flv " +
    // //       m_DlgGDDCSet->m_pushURL;
    // str = "ffmpeg -rtsp_transport tcp -i " + m_DlgGDDCSet->m_playURL1 + "
    // -c:v libx264 -c:a copy -f flv " +
    //       m_DlgGDDCSet->m_pushURL;
    // m_cmd << "/c" << str;
    // process->start("cmd", m_cmd);

    // //方式2:代码推流
    // if(!connectFlag[0])
    // {
    //     QMessageBox::information(NULL, tr("提示"), "请先开始连接",
    //     QMessageBox::Ok); m_DlgGDDCSet->setPushStreamText("推送"); return;
    // }
    ffmpegvideoDlg *videoDlg = ui->WgtffmpegVideo;
    videoDlg->setStreamIP(m_DlgGDDCSet->m_playURL1);
    videoDlg->setPushStreamIP(m_DlgGDDCSet->m_pushURL);
    videoDlg->setPushStream(true);
    m_DlgGDDCSet->setPushStreamText("停止推送");

    connectFlag[5] = true;
  }
}

// 停止视频推流
void GDDCdlg::stopPushURL() {
  if (connectFlag[5]) {

    // //方式1:命令行推流
    // if (process != nullptr) {
    //   process->terminate();
    //   process->close();
    //   process->kill();
    //   // 检查进程退出状态
    //   if (process->exitStatus() == QProcess::CrashExit) {
    //     qDebug() << "Process crashed";
    //   } else {
    //     qDebug() << "Process exited normally";
    //   }
    //   delete process;

    //   // 推流进程未自动关闭,手动关闭
    //   int pids = GetmPid(L"ffmpeg.exe");
    //   qDebug() << "ffmpeg.exe进程的pid为:" << pids;
    //   if (pids != 0) {
    //     QStringList m_cmd;
    //     m_cmd << "/c" << "taskkill /pid " << QString::number(pids) << " -f";
    //     QProcess::startDetached("cmd", m_cmd);
    //   }
    // }

    // 方式2:代码推流
    // ui->WgtffmpegVideo->setPushStreamIP("");
    ui->WgtffmpegVideo->setPushStream(false);
    m_DlgGDDCSet->setPushStreamText("推送");

    connectFlag[5] = false;
  }
}

// 设置页面弹出
void GDDCdlg::pushButtonSet_clicked() {
  m_DlgGDDCSet->show();
  m_DlgGDDCSet->activateWindow(); // 置为顶层
}

// udp数据接收
void GDDCdlg::UDPMessageReceive() {
  QByteArray data;
  data.resize(udpSocket->pendingDatagramSize());
  QHostAddress addr;
  quint16 port;
  udpSocket->readDatagram(data.data(), data.size(), &addr, &port);

  // 吊舱状态数据更新
  m_GDDCStateDlg->UDPMessageReceive(data, data.size());
}
// 控制页面隐藏与显示
void GDDCdlg::pushButShowCmdPage_clicked() {
  if (isCmdPageShow) {
    m_GDDCCmdDlg->setVisible(false);
    isCmdPageShow = false;
    resizeUI();
    ui->pushButShowCmdPage->setIcon(QIcon(":/res/up.png"));
    // ui->pushButton->setGeometry(this->width()/2,this->height()-50,50,50);
  } else {
    m_GDDCCmdDlg->setVisible(true);
    isCmdPageShow = true;
    resizeUI();
    ui->pushButShowCmdPage->setIcon(QIcon(":/res/down.png"));
    // ui->pushButton->setGeometry(this->width()/2,ui->tabWidget->height(),50,50);
  }
}
// 状态页面隐藏与显示
void GDDCdlg::pushButShowStatePage_clicked() {
  if (isStatePageShow) {
    m_GDDCStateDlg->setVisible(false);
    isStatePageShow = false;
    resizeUI();
    ui->pushButShowStatePage->setIcon(QIcon(":/res/left.png"));
  } else {
    m_GDDCStateDlg->setVisible(true);
    isStatePageShow = true;
    resizeUI();
    ui->pushButShowStatePage->setIcon(QIcon(":/res/right.png"));
    // ui->pushButton->setGeometry(this->width()/2,ui->tabWidget->height(),50,50);
  }
}