text: #include <QApplication>
  #include <QClipboard>
  
  #include "controller.h"
  #include "controlmsg.h"
  #include "inputconvertgame.h"
  #include "receiver.h"
  #include "videosocket.h"
  
  Controller::Controller(QString gameScript, QObject *parent) : QObject(parent)
  {
      m_receiver = new Receiver(this);
      Q_ASSERT(m_receiver);
  
      updateScript(gameScript);
  }
  
  Controller::~Controller() {}
  
  void Controller::setControlSocket(QTcpSocket *controlSocket)
  {
      if (m_controlSocket || !controlSocket) {
          return;
      }
      m_controlSocket = controlSocket;
      m_receiver->setControlSocket(controlSocket);
  }
  
  void Controller::postControlMsg(ControlMsg *controlMsg)
  {
      if (controlMsg) {
          QCoreApplication::postEvent(this, controlMsg);
      }
  }
  
  void Controller::test(QRect rc)
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_TOUCH);
      controlMsg->setInjectTouchMsgData(static_cast<quint64>(POINTER_ID_MOUSE), AMOTION_EVENT_ACTION_DOWN, AMOTION_EVENT_BUTTON_PRIMARY, rc, 1.0f);
      postControlMsg(controlMsg);
  }
  
  void Controller::updateScript(QString gameScript)
  {
      if (m_inputConvert) {
          delete m_inputConvert;
      }
      if (!gameScript.isEmpty()) {
          InputConvertGame *convertgame = new InputConvertGame(this);
          convertgame->loadKeyMap(gameScript);
          m_inputConvert = convertgame;
      } else {
          m_inputConvert = new InputConvertNormal(this);
      }
      Q_ASSERT(m_inputConvert);
      connect(m_inputConvert, &InputConvertBase::grabCursor, this, &Controller::grabCursor);
  }
  
  void Controller::onPostBackOrScreenOn()
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_BACK_OR_SCREEN_ON);
      if (!controlMsg) {
          return;
      }
      postControlMsg(controlMsg);
  }
  
  void Controller::onPostGoHome()
  {
      postKeyCodeClick(AKEYCODE_HOME);
  }
  
  void Controller::onPostGoMenu()
  {
      postKeyCodeClick(AKEYCODE_MENU);
  }
  
  void Controller::onPostGoBack()
  {
      postKeyCodeClick(AKEYCODE_BACK);
  }
  
  void Controller::onPostAppSwitch()
  {
      postKeyCodeClick(AKEYCODE_APP_SWITCH);
  }
  
  void Controller::onPostPower()
  {
      postKeyCodeClick(AKEYCODE_POWER);
  }
  
  void Controller::onPostVolumeUp()
  {
      postKeyCodeClick(AKEYCODE_VOLUME_UP);
  }
  
  void Controller::onPostVolumeDown()
  {
      postKeyCodeClick(AKEYCODE_VOLUME_DOWN);
  }
  
  void Controller::onExpandNotificationPanel()
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_EXPAND_NOTIFICATION_PANEL);
      if (!controlMsg) {
          return;
      }
      postControlMsg(controlMsg);
  }
  
  void Controller::onCollapseNotificationPanel()
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_COLLAPSE_NOTIFICATION_PANEL);
      if (!controlMsg) {
          return;
      }
      postControlMsg(controlMsg);
  }
  
  void Controller::onRequestDeviceClipboard()
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_GET_CLIPBOARD);
      if (!controlMsg) {
          return;
      }
      postControlMsg(controlMsg);
  }
  
  void Controller::onSetDeviceClipboard()
  {
      QClipboard *board = QApplication::clipboard();
      QString text = board->text();
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_SET_CLIPBOARD);
      if (!controlMsg) {
          return;
      }
      controlMsg->setSetClipboardMsgData(text, true);
      postControlMsg(controlMsg);
  }
  
  void Controller::onClipboardPaste()
  {
      QClipboard *board = QApplication::clipboard();
      QString text = board->text();
      onPostTextInput(text);
  }
  
  void Controller::onPostTextInput(QString &text)
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_TEXT);
      if (!controlMsg) {
          return;
      }
      controlMsg->setInjectTextMsgData(text);
      postControlMsg(controlMsg);
  }
  
  void Controller::onSetScreenPowerMode(ControlMsg::ScreenPowerMode mode)
  {
      ControlMsg *controlMsg = new ControlMsg(ControlMsg::CMT_SET_SCREEN_POWER_MODE);
      if (!controlMsg) {
          return;
      }
      controlMsg->setSetScreenPowerModeData(mode);
      postControlMsg(controlMsg);
  }
  
  void Controller::onMouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize)
  {
      if (m_inputConvert) {
          m_inputConvert->mouseEvent(from, frameSize, showSize);
      }
  }
  
  void Controller::onWheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize)
  {
      if (m_inputConvert) {
          m_inputConvert->wheelEvent(from, frameSize, showSize);
      }
  }
  
  void Controller::onKeyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize)
  {
      if (m_inputConvert) {
          m_inputConvert->keyEvent(from, frameSize, showSize);
      }
  }
  
  bool Controller::event(QEvent *event)
  {
      if (event && static_cast<ControlMsg::Type>(event->type()) == ControlMsg::Control) {
          ControlMsg *controlMsg = dynamic_cast<ControlMsg *>(event);
          if (controlMsg) {
              sendControl(controlMsg->serializeData());
          }
          return true;
      }
      return QObject::event(event);
  }
  
  bool Controller::sendControl(const QByteArray &buffer)
  {
      if (buffer.isEmpty()) {
          return false;
      }
      qint32 len = 0;
      if (m_controlSocket) {
          len = static_cast<qint32>(m_controlSocket->write(buffer.data(), buffer.length()));
      }
      return len == buffer.length() ? true : false;
  }
  
  void Controller::postKeyCodeClick(AndroidKeycode keycode)
  {
      ControlMsg *controlEventDown = new ControlMsg(ControlMsg::CMT_INJECT_KEYCODE);
      if (!controlEventDown) {
          return;
      }
      controlEventDown->setInjectKeycodeMsgData(AKEY_EVENT_ACTION_DOWN, keycode, AMETA_NONE);
      postControlMsg(controlEventDown);
  
      ControlMsg *controlEventUp = new ControlMsg(ControlMsg::CMT_INJECT_KEYCODE);
      if (!controlEventUp) {
          return;
      }
      controlEventUp->setInjectKeycodeMsgData(AKEY_EVENT_ACTION_UP, keycode, AMETA_NONE);
      postControlMsg(controlEventUp);
  }
  