#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include "netiscommander.h"

#define SOH 0x01
#define EOT 0x04
static int fds;

char pos_main;
char pos_contr;

char command[1024];
#define send_command(message, descr) { const char * __msg = message; \
write(descr, __msg, strlen(__msg)); }

int main(int argc, char *argv[])
{
  puts("Hello");
  ConfigCom();
  //getchar();
  //printf("hello\n");
  char * sresult;
/*  int strlength;
  // Proverka dali e pusnata razwojnata sistema
  SendCommand("H 0200 020F");
  sresult = Response(fds) ;//+1 ;            // skip begining tag
  *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
  //printf("sresult=\"%s\" length=%d\n", sresult, strlen(sresult));
  strlength= strlen(sresult);
  send_command("1", fds);
  sresult = Response(fds) ;//+1 ;            // skip begining tag
  *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
  //printf("sresult=\"%s\" length=%d\n", sresult, strlen(sresult));
  send_command("1", fds);
  if(strlength!=52)
  {*/
  puts("Please reset system");
  // Wait for initial message
  sresult = Response(fds) ;//+1 ;            // skip begining tag
  *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
  //printf("sresult=\"%s\" length=%d\n", sresult, strlen(sresult));
  puts(sresult);
  send_command("1", fds);
  sresult = Response(fds) ;//+1 ;            // skip begining tag
  *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
  //printf("sresult=\"%s\" length=%d\n", sresult, strlen(sresult));
  printf("%s", sresult);
  send_command("1", fds);
  //}
  do
  {
    gets(command);
    switch(command[0])    
    {
      case 'l': case 'L': Load(); break;
      case 'h': case 'H': HPrint(); break;
      case 'a': case 'A': AMovedt(); break;
      case 'i': case 'I': InitMem(); break;
      case 'c': case 'C': Compar(); break;
      case 'v': case 'V': VBreak(); break;
      case 'd': case 'D': DelBreak(); break;
      case 'g': case 'G': GoTo(); break;
      case 'r': case 'R': Regs(); break;
      default: printf("Error in command\n");
    }
    //printf("%s", sresult);
    //send_command("1", fds);
  }while((command[0]!='q') && (command[0]!='Q'));
}

void ConfigCom()
{
  fds = open("/dev/ttyS0", O_RDWR | O_NOCTTY); //com1 port
  //printf ("fds = %d\n", fds);
  if (fds < 0)
  {
    puts( strerror(errno) );
  }
  tcflush(fds, TCIFLUSH); // flush the input buffer
  termios tio; // the terminal settings
  memset(&tio, 0, sizeof(termios));
  tio.c_cflag = B2400 // Set 2400 baud rate
    | CS8    // 8 bits data word
    | CLOCAL // Ignore hardware handshake
    | CREAD; // Enable receiving
  tio.c_iflag = IGNPAR; // Ignored input parity control
  tio.c_cc[VTIME] = 50; // Set Message timeout 10s
  tio.c_cc[VMIN]  = 0;  // No blocking operation
  tcsetattr(fds, TCSANOW, &tio);
  //printf("End of ConfigCom\n");
  pos_main='A';
  pos_contr='C';
}

char * Response(int descr)
{
  //static int count = 0;
  //printf("count=%d\n", count++);
  bool startFind = false;
  static char m_response[1024];
  static char response[1024];
  for(int i=0; i<1024; i++)
  {
    m_response[i]='\0';
    response[i]='\0';
  }
  m_response[0] = '\0';
  int curpos = 0;
  char character;
  int res;
  int integer;
  int start=0;
  char MainAddress, RemoteAddress, Color;
  char CHKSUM=0;
  unsigned char length, length_count=100;
  int len,iptr=0;
  unsigned char buf;
  struct timeval tp;
  double startsecs,secs;
  gettimeofday(&tp,NULL);
  startsecs = tp.tv_sec + tp.tv_usec / 1000000.0;

  //GET RESPONCE
  int counter=0;
  for (;;)
  {
    res = read(descr, &character, 1);
    if (res < 1) break;
    //printf("%u ", character);
    if (character == 1)
    {
      startFind = true;
      //puts("startFind");
    }
    if (startFind)
    {
      counter++;
    }
    if (startFind && length_count!=2)
    {
      CHKSUM += character;
    }
    //printf("counter=%d\n", counter);
    if (counter==5)
    {
      length=character;
      //printf("length=%d\n", length);
      length_count=character;
      //printf("length_count=%d\n", length_count);
      length_count+=3;
    }
    if (startFind)
    {
      length_count--;
      //puts("startFind");
    }
    //printf("length_count=%d\n", length_count);
    if(length_count==1)  
      if (CHKSUM != character)
      { //printf("CHKSUM=%d\ncharacter=%d\n", CHKSUM, character);
        return &response[1023]; // return NULL string
	}
    curpos++;
    sprintf(m_response, "%c", character);
    integer=int(character);
    strncat(response, m_response, 1);
   // puts("Point 1");
   bool tmp;
   if (startFind)
     tmp=curpos == 1023 || character == EOF || !length_count;
   else
     tmp=curpos == 1023 || character == EOF;
    if(tmp)	
      break;
    gettimeofday(&tp,NULL);
    secs = tp.tv_sec + tp.tv_usec / 1000000.0;
    //puts("Point 2");
    if (secs-startsecs > /*timeout*/30.0)
      break;
  }
  //printf("\nresponse=%s\n", response);
  response[curpos-1] = '\0';
  while(response[start]!=0x01);
  {
    start++;
    if (start==1023)
      return &response[1023]; // return NULL string    
  }
  //printf("start=%d\n", start);
  MainAddress = response[start];
  if(MainAddress != pos_main)
    return &response[1023]; // return NULL string
  //puts("point 1");
  RemoteAddress = response[start+1];
  if (length>150)
  {
    puts("Length is too high");
    return &response[1023]; // return NULL string
  }
/*  for(unsigned int index=0; index<length+5; index++)
  {
     CHKSUM += response[start-1+int(index)];
  }*/
  //printf("CHKSUM=%d\nresponse[start+4+int(length)]=%d\n", CHKSUM, response[start+4+int(length)]);
  //if (CHKSUM != response[start+4+int(length)])
    //return &response[1023]; // return NULL string
  //puts("point 2");
  //response[start+int(length)+5]='\0';
  start+=4;
  return &response[start];
/*  
  static char m_response[1024];
  static char response[1024];
  //printf("char * Response(int descr)\n");
  for(int i=0; i<1024; i++)
  {
    m_response[i]='\0';
    response[i]='\0';
  }
  //if (m_response[0]) return m_response;
  m_response[0] = '\0';
  int curpos = 0;
  char character;
  int res;
  int integer;
  int start=0;
  char MainAddress, RemoteAddress, Color;
  unsigned int length;
  //tcflush(fds, TCIFLUSH); // flush the input buffer
  //GET RESPONCE
  do
  {
    res = read(descr, &character, 1);
    if (res < 1) break;
    curpos++;
    sprintf(m_response, "%c", character);
    integer=int(character);
    strncat(response, m_response, 1);
    //printf("%c %c %d\n", character, response[curpos-1], integer);
  } while (curpos < 1023 && character != 10 && character != EOF && character != EOT);
  m_response[curpos] = '\0';
  while(response[start]!=0x01);
  {
    integer=int(response[start]);
    start++;
    //printf("start=%5d char=%d\n", integer);
  }
  //printf("start=%d\n", start);
  MainAddress = response[start];
  RemoteAddress = response[start+1];
  //printf("MainAddress=%c\nRemoteAddress=%c\n", MainAddress, RemoteAddress);
  length = unsigned(response[start+3]);
  //printf("length=%u\n", length);
  char sum = 0;
  for(unsigned int index=0; index<length+5; index++)
  {
     //sum += response[start-1+int(index)];
  }
  //printf("sum=%d\n", int(sum));
  response[start+int(length)+5]='\0';
  start+=4;
  //tcflush(fds, TCIFLUSH); // flush the input buffer
  return &response[start];*/
}

void SendCommand(char * command)
{
  char message[1024];
  unsigned char LENGTH;
  char CHKSUM=0;
  LENGTH = char(strlen(command));
  CHKSUM += SOH;
  CHKSUM += pos_main;
  CHKSUM += pos_contr;
  CHKSUM += 'A';
  CHKSUM += LENGTH;
  for(unsigned index=0; index<strlen(command); index++)
    CHKSUM += command[index];
  sprintf(message,"%c%c%cA%c%s%c%c", SOH, pos_contr, pos_main, strlen(command), command, CHKSUM, EOT );
  //sprintf(message,"%c%c%cA%c%s%c%c", 1,pos_contr, pos_main, strlen(command), command, 22, 4 );
  for(unsigned int i=0; i< LENGTH+7; i++)
  {
    //printf("%c %u\n", message[i], unsigned (message[i]));
  }
  //printf("CHKSUM=%d\n", int(CHKSUM));
  send_command(message,fds);
}

bool SyntaxOK(char * mask, bool strict)
{
  // L - any letter or symbol
  // H - only HEX digit
  // ' ' - 0nly space
  bool SyntOK = true; // be optimistic
  if ( (strlen(command)!=strlen(mask)) && strict)
  {
    SyntOK = false;
    return (SyntOK);
  }
  
  if ((strlen(command)>strlen(mask)) && strict)
  {
    SyntOK = false;
    return (SyntOK);
  }
  int index;
  if(strict)
  for(index=0; index<strlen(mask); index++)
  {
    switch (mask[index])
    {
      case 'L': break;
      case 'H': if(SyntOK) SyntOK=IsHEX(command[index]); break;
      case ' ': if(SyntOK) SyntOK=(command[index]==' '); break;
    }
  }
  else
  for(index=0; index<strlen(command); index++)
  {
    switch (mask[index])
    {
      case 'L': break;
      case 'H': if(SyntOK) SyntOK=IsHEX(command[index]); break;
      case ' ': if(SyntOK) SyntOK=(command[index]==' '); break;
    }
  }

  return (SyntOK);
}
bool IsHEX(char character)
{
  return((character>='0'&&character<='9')||(character>='a'&&character<='f')||(character>='A'&&character<='F'));
}

void DefineSectors(unsigned int old_start_address, unsigned int old_end_address, unsigned int * new_start_address, unsigned int * new_end_address, unsigned int segments_length, int * count_segments)
{
  int count=0;
  (*count_segments)=0;
  unsigned int var_start_address = old_start_address;
  //printf("DefineSectors\n");
  do
  {
    new_start_address[count]=var_start_address;
    new_end_address[count]= new_start_address[count] | segments_length;
    var_start_address=new_end_address[count]+1;
    count++;
    (*count_segments)++;    
    //getchar();
  }while(new_end_address[count-1]<old_end_address);
}

void HPrint()
{
  char * mask ="L HHHH HHHH";
  unsigned int bega, enda, length=0xF;
  unsigned int new_bega[4096];
  unsigned int new_enda[4096];
  char buf;
  int count, index;
  char com;
  char *sresult;
  if (SyntaxOK(mask, true))
  {
    //printf("Syntax is OK\n");
    sscanf(command, "%c %4X %4X", &buf, &bega, &enda);
    //printf("bega=%u enda=%u\n", bega, enda);
    DefineSectors(bega, enda, new_bega, new_enda, 0xF, &count);
    //printf("count=%d\n", count);
    for(index=0; index<count; index++)
    {
      if (new_bega[index]<0x10)
      sprintf(command, "h 000%1X 000%1X", new_bega[index], new_enda[index]);
      else if (new_bega[index]<0x100)
           sprintf(command, "h 00%2X 00%2X", new_bega[index], new_enda[index]);
           else if (new_bega[index]<0x1000)
                sprintf(command, "h 0%3X 0%3X", new_bega[index], new_enda[index]);
                else sprintf(command, "h %4X %4X", new_bega[index], new_enda[index]);
      //puts(command);
      //printf("index=%d\n", index);
      SendCommand(command);
      sresult = Response(fds);// +1 ;            // skip begining tag
      *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
      printf("%s\n", sresult);
      send_command("1", fds);
      sresult = Response(fds);// +1 ;            // skip begining tag
      *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
      if(index==count-1)
        printf("%s", sresult);
      send_command("1", fds);
      //if
    }
  }
  else
    printf("Syntax is NOT OK\n");
}

void Load()
{
  char * mask ="L HHHH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH";
  unsigned int bega, enda, length=0xF;
  unsigned int new_bega[500];
  unsigned int new_enda[500];
  char *sresult;  
  if (SyntaxOK(mask, false))
  {
      SendCommand(command);
      sresult = Response(fds);// +1 ;            // skip begining tag
      *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
      printf("%s", sresult);
      send_command("1", fds);
  }
  else
    printf("Syntax is NOT OK\n");
}

void AMovedt()
{
  char * mask ="L HHHH HHHH HHHH";
  char *sresult;  
  if (SyntaxOK(mask, true))
  {
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);
  }
  else
    printf("Syntax is NOT OK\n");
}
void InitMem()
{
  char * mask ="L HHHH HHHH HH";
  char *sresult;  
  if (SyntaxOK(mask, true))
  {
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);
  }
  else
    printf("Syntax is NOT OK\n");
}
void Compar()
{
  char * mask ="L HHHH HHHH HHHH";
  char *sresult;  
  if (SyntaxOK(mask, true))
  {
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s\n", sresult);
    send_command("1", fds);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);
  }
  else
    printf("Syntax is NOT OK\n");
}
void VBreak()
{
  char * mask1 ="L HHHH";
  char * mask2 ="L";
  char * sresult;  
  if (SyntaxOK(mask1, true))
  {
    //puts("Now is rinning VBreak L HHHH");
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);
  }
  else  if (SyntaxOK(mask2, true))
        {
          //puts("Now is rinning VBreak L bla bla");
          SendCommand(command);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s", sresult);
          send_command("1", fds);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s", sresult);
          send_command("1", fds);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s\n", sresult);
          send_command("1", fds);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s", sresult);
          send_command("1", fds);
        }
        else
          printf("Syntax is NOT OK\n");


}
void DelBreak()
{
  char * mask1 ="L HHHH";
  char * mask2 ="L";
  char * sresult;  
  if (SyntaxOK(mask1, true))
  {
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);

  }
  else  if (SyntaxOK(mask2, true))
        {
          SendCommand(command);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s", sresult);
          send_command("1", fds);
        }
        else
          printf("Syntax is NOT OK\n");

}
void GoTo()
{
  char * mask ="L HHHH";
  char * sresult;  
  if (SyntaxOK(mask, true))
  {
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s\n", sresult);
    send_command("1", fds);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);
  }
  else
    printf("Syntax is NOT OK\n");

}
void Regs()
{
  char * mask1 ="L LH HHHH";
  char * mask2 ="L";
  char * sresult;  
  if (SyntaxOK(mask1, true))
  {
    SendCommand(command);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s\n", sresult);
    send_command("1", fds);
    sresult = Response(fds);// +1 ;            // skip begining tag
    *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
    printf("%s", sresult);
    send_command("1", fds);

  }
  else  if (SyntaxOK(mask2, true))
        {
          SendCommand(command);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s\n", sresult);
          send_command("1", fds);
          sresult = Response(fds);// +1 ;            // skip begining tag
          *(short *)(sresult + strlen(sresult) - 1) = 0; // skip ending tag and the CR (it was -2 not -1)
          printf("%s", sresult);
          send_command("1", fds);
        }
        else
          printf("Syntax is NOT OK\n");

}
