//***************************************************************************
// Group VDR/GraphTFT
// File comthread.cc
// Date 28.10.06 - Jörg Wendel
// This code is distributed under the terms and conditions of the
// GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
//--------------------------------------------------------------------------
// Class ComThread
//***************************************************************************

#include <arpa/inet.h>

#include <QImage>

#include "graphtft.hpp"

//***************************************************************************
// Object
//***************************************************************************

ComThread::ComThread()
   : QThread()
{
   line = new TcpChannel();

   bufferSize = maxBuffer;

   buffer = new char[bufferSize+1];
   header = new TcpChannel::Header;

   timeout = 5;
   port = -1;
   *host = 0;
   client = 0;
}

ComThread::~ComThread()
{
   if (line->isConnected())
   {
      tell(eloAlways, "Logout from server, closing tcp connection");
      line->write(cGraphTftComService::cmdLogout);
      line->close();
   }

   delete line;
   delete header;
   delete[] buffer;
}

//***************************************************************************
// Run
//***************************************************************************

void ComThread::run()
{
   int status;

   running = true;

   while (running)
   {
      if (!line->isConnected())
      {
         tell(eloAlways, "Trying connecting to '%s' at port (%d)", host, port);

         if (line->open(host, port) == 0)
            tell(eloAlways, "Connection to '%s' established", host);
         else
            tell(eloAlways, "Connecting to '%s' failed", host);
      }

      while (line->isConnected() && running)
      {
         if ((status = line->look(1)) != 0)
         {
            if (status != TcpChannel::wrnNoEventPending)
            {
               tell(eloAlways, "Error: Communication problems, closing line! status was (%d)", 
                    status);
               line->close();

               break;
            }
            
            continue;
         }
         
         if ((status = read()) != 0)
         {
            line->close();
            tell(eloAlways, "Error: Communication problems, closing line! status was (%d)", 
                 status);
         }
      }

      if (!running) break;

      tell(eloAlways, "Retrying in %ld seconds", timeout);

      for (int i = 0; i < timeout && running; i++)
         sleep(1);
   }
}

//***************************************************************************
// Transmit events
//***************************************************************************

int ComThread::mouseEvent(int x, int y, int button, int flag)
{
   GraphTftTouchEvent m;

   m.x = x;
   m.y = y;
   m.button = button;
   m.flag = flag;
   line->write(cGraphTftComService::cmdMouseEvent, (char*)&m, sizeof(GraphTftTouchEvent));

   return 0;
}

//***************************************************************************
// ...
//***************************************************************************

int ComThread::keyEvent(int key, int flag)
{
   GraphTftTouchEvent m;

   m.x = 0;
   m.y = 0;
   m.button = key;
   m.flag = flag | efKeyboard;
   line->write(cGraphTftComService::cmdMouseEvent, (char*)&m, sizeof(GraphTftTouchEvent));

   return 0;
}

//***************************************************************************
// Read
//***************************************************************************

int ComThread::read()
{
   int status;
   TcpChannel::Header tmp;

   // es stehen Daten an, erst einmal den Header abholen ..

   if ((status = line->read((char*)&tmp, sizeof(TcpChannel::Header))) == 0)
   {
      header->command = ntohl(tmp.command);
      header->size = ntohl(tmp.size);

      switch (header->command)
      {
         case cGraphTftComService::cmdWelcome:
         {
            tell(eloAlways, "Got welcome");

            break;
         }

         case cGraphTftComService::cmdLogout:
         {
            tell(eloAlways, "Got logout from client, closing line");
            line->close();

            break;
         }

         case cGraphTftComService::cmdData:
         {
            tell(eloDebug, "Debug: Received %d bytes", header->size);
            
            status = line->read(buffer, header->size);
            
            if (status == 0 && client) 
               client->updateImage((uchar*)buffer, header->size);
            
            break;
         }

         case cGraphTftComService::cmdMouseEvent:
         {
            GraphTftTouchEvent ev;

            status = line->read((char*)&ev, header->size);
            tell(eloAlways, "Got mouse event, button (%d) at (%d/%d)", ev.button, ev.x, ev.y); 

            break;
         }

         default:
         {
            tell(eloAlways, "Got unexpected protocol (%d), aborting", header->command); 
            status = -1;

            break;
         }
      }
   }   

   return status;
}
