#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <rfb/rfbclient.h>

#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <termios.h> /* POSIX terminal control definitions */

static struct termios gOriginalTTYAttrs;

static int OpenSerialPort()
{
    int        fileDescriptor = -1;
    struct termios  options;
    
    // Open the serial port read/write, with no controlling terminal, and don't wait for a connection.
    // The O_NONBLOCK flag also causes subsequent I/O on the device to be non-blocking.
    // See open(2) ("man 2 open") for details.
    
    fileDescriptor = open("/dev/tty.iap", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fileDescriptor == -1)
    {
        printf("Error opening serial port %s - %s(%d).\n",
               "/dev/tty.iap", strerror(errno), errno);
        goto error;
    }
    
    // Get the current options and save them so we can restore the default settings later.
    if (tcgetattr(fileDescriptor, &gOriginalTTYAttrs) == -1)
    {
        printf("Error getting tty attributes %s - %s(%d).\n",
            "/dev/tty.iap", strerror(errno), errno);
        goto error;
    }

    // The serial port attributes such as timeouts and baud rate are set by modifying the termios
    // structure and then calling tcsetattr() to cause the changes to take effect. Note that the
    // changes will not become effective without the tcsetattr() call.
    // See tcsetattr(4) ("man 4 tcsetattr") for details.
    
    options = gOriginalTTYAttrs;
    
    // Print the current input and output baud rates.
    // See tcsetattr(4) ("man 4 tcsetattr") for details.
    
    printf("Current input baud rate is %d\n", (int) cfgetispeed(&options));
    printf("Current output baud rate is %d\n", (int) cfgetospeed(&options));
    
    // Set raw input (non-canonical) mode, with reads blocking until either a single character 
    // has been received or a one second timeout expires.
    // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") for details.
    
    cfmakeraw(&options);
    options.c_cc[VMIN] = 1;
    options.c_cc[VTIME] = 10;
        
    // The baud rate, word length, and handshake options can be set as follows:
    
    cfsetspeed(&options, B19200);    // Set 19200 baud    
    options.c_cflag |= (CS8);  // RTS flow control of input
      
    
    printf("Input baud rate changed to %d\n", (int) cfgetispeed(&options));
    printf("Output baud rate changed to %d\n", (int) cfgetospeed(&options));
    
    // Cause the new options to take effect immediately.
    if (tcsetattr(fileDescriptor, TCSANOW, &options) == -1)
    {
        printf("Error setting tty attributes %s - %s(%d).\n",
            "/dev/tty.iap", strerror(errno), errno);
        goto error;
    }    
    // Success
    return fileDescriptor;
    
    // Failure "/dev/tty.iap"
error:
    if (fileDescriptor != -1)
    {
        close(fileDescriptor);
    }
    return -1;
}

static int converter(int huns, int tens, int ones)
{
    if (huns)
        huns =(huns - 48)*100;

    if (tens)
        tens =(tens - 48)*10;
        
    if (ones)
        ones = ones -48;
    return huns+tens+ones;
}

int
main(int argc, char **argv)
{
        unsigned int c;
    int fd;
    char buf[10];
    int x;
    int y;
    
    rfbClient* client = rfbGetClient(8,1,2);
        time_t t=time(NULL);

        if (!rfbInitClient(client,&argc,argv))
                return 1;

#if 0
        sleep(5);
        printf("Sending key events now !\n");
#endif

        
        SendPointerEvent(client, 50, 50, 0 | 1);
        SendPointerEvent(client, 50, 50, 1);

        sleep(1);

        SendPointerEvent(client, 150, 150, 0 | 1);
        SendPointerEvent(client, 150, 150, 1);

#if 0
        printf("Keycode: %d\n", XK_A);

        SendKeyEvent(client, XK_A, TRUE);
        SendKeyEvent(client, XK_A, FALSE);

        SendKeyEvent(client, XK_B, TRUE);
        SendKeyEvent(client, XK_B, FALSE);

        SendKeyEvent(client, XK_C, TRUE);
        SendKeyEvent(client, XK_C, FALSE);
#endif

    fd=OpenSerialPort();
    if(fd>-1)
    {
           while ( 1==1)
           {
               c=-1;
              read(fd,&c,1);
              if (c != -1)
              {      
                   c = c+256;
                   if (c == 13)
                   {
                       c=-1;
                       read(fd,&c,1);
                       c = c+256;
                       if (c == 10)
                       {   
                           c=-1;
                           read(fd,&c,1);
                           c = c+256;
                           if (c == 13)
                           {
                               rfbClientLog("Sending New Line"); 
                                  SendKeyEvent(client, c, TRUE);
                                  SendKeyEvent(client, c, FALSE);
                                  c = 10;
                                  SendKeyEvent(client, c, TRUE);
                                  SendKeyEvent(client, c, FALSE);
                              }         
                       } 
                   }
                   else
                   {   
                       if (c == 42)
                       {
                           c=-1;
                           read(fd,&c,1);
                           c = c+256;
                           if (c == 42)
                           {
                               memset(buf, 0, 10);
                               read(fd,buf,7);
                               rfbClientLog("Got  %d - %d - %d,  %d - %d - %d,  %d\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
                               x = converter(buf[0], buf[1], buf[2]);
                               y = converter(buf[3], buf[4], buf[5]);
                               
                               if (buf[6])
                               buf[6] = buf[6] - 48;
                               
                               rfbClientLog("Converted to  X = %d  Y = %d  , %d\n", x, y,buf[6]);
                               SendPointerEvent(client,x, y, buf[6]);
                               //uint8_t buttonMask;     bits 0-7 are buttons 1-8, 0=up, 1=down
                        }                      
                       }   
                       else
                       {
                          SendKeyEvent(client, c, TRUE);
                          SendKeyEvent(client, c, FALSE);
                          rfbClientLog("Sending Key %d\n",c);
                          }
                      }
                  }
           }
    }

        /* TODO: better wait for update completion */
        while (time(NULL)-t<5) {
                static int i=0;
                fprintf(stderr,"\r%d",i++);
                if(WaitForMessage(client,50)<0)
                        break;
                if(!HandleRFBServerMessage(client))
                        break;
        }

        rfbClientCleanup(client);

        return 0;
}

