#include "webbyphone.h"

int modem_fd;
extern URL *current;
extern char filename[256];
extern char *history_list[HISTORY];
extern int historylist_counter;
extern int mode;
extern char *prefix[2];

int readline(int fd, char *buf, int bytes)
{
  int done = 0;
  int n = 0, i = 0;
  char buffer[256];
  char c;

  while((i = read(fd, &c, 1)) > 0){
    switch(c){
    case '\r': 
      i = read(fd, &c, 1);
      if(n > 0)
	done = 1;
      break;
    default:
      buffer[n++] = c;      
    }
    if(done == 1)
      break;
    if(strstr(buffer, "OK")!= 0)
      break;
  }
  
  buffer[n] = '\0';
  strcpy(buf, buffer);

  return n;
}

int array[2][10][5] = 
{ 
  {
    {'0', -1,  -1,  -1,  -1},
    {'1', -1,  -1,  -1,  -1},
    {'2', 'a', 'b', 'c', -1},
    {'3', 'd', 'e', 'f', -1},
    {'4', 'g', 'h', 'i', -1},
    {'5', 'j', 'k', 'l', -1},
    {'6', 'm', 'n', 'o', -1},
    {'7', 'p', 'q', 'r', 's'},
    {'8', 't', 'u', 'v', -1},
    {'9', 'w', 'x', 'y', 'z'},
  },
  {
    {'0', -1,  -1,  -1,  -1},
    {'1', -1,  -1,  -1,  -1},
    {'2', 'A', 'B', 'C', -1},
    {'3', 'D', 'E', 'F', -1},
    {'4', 'G', 'H', 'I', -1},
    {'5', 'J', 'K', 'L', -1},
    {'6', 'M', 'N', 'O', -1},
    {'7', 'P', 'Q', 'R', 'S'},
    {'8', 'T', 'U', 'V', -1},
    {'9', 'W', 'X', 'Y', 'Z'},
  }
};

void read_num(int fd, int *number)
{
  int done = 0;
  int n = 0, i = 0;
  char buffer[256];
  char c;

  while((i = read(fd, &c, 1)) > 0){

    switch(c){
    case '#':
      {
	done = 1;
	break;
      }

    case '0': case '1': case '2': case '3': case '4': case '5': case '6':
    case '7': case '8': case '9':
      fprintf(stderr, "%c", c);
      buffer[n++] = c;
      break;

    default:
      fprintf(stderr, "ignoring %c\n", c);
    }

    if(done == 1)
      break;
  }
  
  buffer[n] = '\0';
  *number = atoi(buffer);
}

void play_char(char *charname)
{
  char filename[100];
  strcpy(filename, "charset/");
  strcat(filename, charname);
  play_file(filename);
}

int read_web_address(int fd, char *buffer, int bytes)
{
  int done = 0;
  int n = 0, i = 0;
  char c, c2, c3, c4;
  int history_flag = 0;
  int flag = 0;

  n = strlen(buffer);

  if(n)
    history_flag = 1;

  while((i = read(fd, &c, 1)) > 0){
    if(flag == 0){
      kill_sound();
      flag = 1;
    }
    
    switch(c){
    case '*':
      {
	if((i = read(fd, &c2, 1)) < 0)
	  break;
	switch(c2){
	case '0': 
	  {
	    buffer[n++] = '*';
	    play_char("star");
	    fprintf(stderr, "%c", buffer[n-1]);
	  }
	break;
	case '1': 
	  {
	    buffer[n++] = '.';
	    play_char("dot");
	    fprintf(stderr, "%c", buffer[n-1]);
	  }
	break;
	case '2':
	  {
	    buffer[n++] = '/';
	    play_char("slash");
	    fprintf(stderr, "%c", buffer[n-1]);	    
	  }
	break;
	case '3':
	  {
	    buffer[n++] = '~';
	    play_char("tilde");
	    fprintf(stderr, "%c", buffer[n-1]);	    
	  
	  }
	break;
	case '4':
	  {
	    buffer[n++] = ':';
	    play_char("colon");
	    fprintf(stderr, "%c", buffer[n-1]);	    
	  
	  }
	break;
	case '5':
	  {
	    if(n > 0){
	      buffer[n--] = 0;
	    }
	    play_char("ERASE");
	    fprintf(stderr, "ERASE", buffer[n-1]);	    
	  }
	break;
	default:
	  play_sound("ignore");
	  fprintf(stderr, "ignoring %c %c\n", c, c2);
	}
      }
    break;

    case '#':
      {
	if((i = read(fd, &c2, 1)) < 0)
	  break;
	switch(c2){
	case '0': 
	  {
	    buffer[n++] = '#';
	    play_char("pound");
	    fprintf(stderr, "%c", buffer[n-1]);	    	    
	    break;
	  }
	case '#': 
	  {
	    done = 1;
	    play_char("done");
	    sleep(1);
	    break;
	  }
	case '*':
	  {

	    if(history_flag){
	      play_char("CANCEL");
	      return -2;
	    }
	    else{
	      play_sound("ignore");
	      fprintf(stderr, "ignoring %c %c\n", c, c2);
	    }
	  }
	default:
	  {
	    play_sound("ignore");
	    fprintf(stderr, "ignoring %c %c\n", c, c2);
	  }
	}
	break;
      }

    case '0': case '1': case '2': case '3': case '4': case '5': case '6':
    case '7': case '8': case '9':
      {
	if((i = read(fd, &c2, 1)) < 0)
	  break;

	if((i = read(fd, &c3, 1)) < 0 ||  ! (c3 <= '1' && c3 >= '0') ){

	  if(c == '9' && c2 == '9' && c3 == '9'){
	    fprintf(stderr, "www");
	    buffer[n++] = 'w';
	    buffer[n++] = 'w';
	    buffer[n++] = 'w';
	    play_char("www");	    
	  }else if(c == '3' && c2 == '6' && c3 == '6'){
	    fprintf(stderr, "com");
	    buffer[n++] = 'c';
	    buffer[n++] = 'o';
	    buffer[n++] = 'm';
	    play_char("com");	    
	  }else if(c == '4' && c2 == '6' && c3 == '8'){
	    fprintf(stderr, "gov");
	    buffer[n++] = 'g';
	    buffer[n++] = 'o';
	    buffer[n++] = 'v';
	    play_char("gov");	    
	  }else if(c == '3' && c2 == '3' && c3 == '8'){
	    fprintf(stderr, "edu");
	    buffer[n++] = 'e';
	    buffer[n++] = 'd';
	    buffer[n++] = 'u';
	    play_char("edu");	    
	  }else if(c == '3' && c2 == '8' && c3 == '7'){
	    fprintf(stderr, "ftp");
	    buffer[n++] = 'f';
	    buffer[n++] = 't';
	    buffer[n++] = 'p';
	    play_char("ftp");	    
	  }else if(c == '6' && c2 == '4' && c3 == '5'){
	    fprintf(stderr, "mil");
	    buffer[n++] = 'm';
	    buffer[n++] = 'i';
	    buffer[n++] = 'l';
	    play_char("mil");
	  }else{
	    fprintf(stderr, "ignoring %c %c %c\n", c, c2, c3);	  
	    play_sound("ignore");
	  }
	  break;

	}else{
	  switch(c2){
	  case '0': case '1': case '2': case '3': case '4':
	    
	    if((c4 = array[c3-'0'][c-'0'][c2-'0']) == -1){
	      fprintf(stderr, "ignoring %c %c %c\n", c, c2, c3);
	      play_sound("ignore");
	    }else{
	      char string[2];
	      buffer[n++] = c4;
	      string[0] = c4;
	      string[1] = 0;
	      play_char(string);
	      fprintf(stderr, "%c", buffer[n-1]);
	    }
	    break;
	  default:
	    fprintf(stderr, "ignoring %c %c %c\n", c, c2, c3);
	    play_sound("ignore");
	  }
	  break;
	}
      }
    default:
      fprintf(stderr, "ignoring %c\n", c);
      play_sound("ignore");
    }

    if(done == 1)
      break;
  }
  
  buffer[n] = '\0';

  return n;
}

int read_commands(int fd, char *buf, int bytes)
{
  int n = 0, i;
  char buffer[256];
  char c;

  while((i = read(fd, &c, 1)) > 0){

    switch(c){
    case '\r': case '\n':
      break;
    default:
      fprintf(stderr, "%c", c);      
      buffer[n++] = c;
    }

    if(n > 0)
      break;
  }
  
  buffer[n] = '\0';
  strcpy(buf, buffer);

  return n;
}

int writen(int fd, char *buf, int bytes)
{
  int i = 0;
  int n = 0;
  while(bytes - n){
    i = write(fd, &buf[n], 1);
    if(i < 1)
      perror("write error"), exit(1);
    n++;
  }
  return bytes;
}

void open_modem()
{
  struct termios modemio_s;
  int i;

  modem_fd = open("/dev/term/a", O_RDWR | O_NONBLOCK);

  if(modem_fd < 0){
    perror("open modem");
    exit(1);
  }

  if(tcgetattr(modem_fd, &modemio_s))
    perror("tcgetattr error"), exit(1);

  modemio_s.c_cflag = CS8 | CREAD | HUPCL; /*  CS7 | PARENB | CREAD | CLOCAL | HUPCL; **/
  modemio_s.c_oflag = IGNBRK | IGNPAR; 
  modemio_s.c_iflag = IGNBRK | IGNPAR;
  modemio_s.c_lflag = 0;
  modemio_s.c_cc[VMIN] = 1;
  modemio_s.c_cc[VTIME] = 0;

  cfsetospeed(&modemio_s, B1200);
  cfsetispeed(&modemio_s, B1200);


  tcsetattr(modem_fd, TCSANOW, &modemio_s);

  /** blocking mode **/
  if((i = fcntl(modem_fd, F_GETFL, 0)) < 0)
    perror("fcntl error"), exit(1);

  i ^= O_NONBLOCK;
  
  if((i = fcntl(modem_fd, F_SETFL, i)) < 0)
    perror("fcntl error"), exit(1);  
}

void  configure_modem()
{
  int i;
  char buf[200];

  strcpy(buf, "at*r2\n");
  i = writen(modem_fd, buf, strlen(buf));
  i = readline(modem_fd, buf, 200);
  if(strstr(buf, "OK") == 0){
    fprintf(stderr, "cannot enable audio input\n");
    exit(1);
  }else{
    fprintf(stderr, "audio input enabled\n");    
  }
}

void process_commands()
{
  char command[200];
  char url[200];
  int i;
  NODE *list = (NODE*)malloc(sizeof(NODE));
  NODE *traverse = list;
  NODE *back;
  traverse->back = NULL;
  traverse->next = NULL;
  traverse->url = NULL;
  current = NULL;

  for(i = 0; i < 10 ; i ++){
    history_list[i] = NULL;
    historylist_counter = 0;
  }

  thr_setconcurrency(10);

  mode = 0;

  play_sound("welcome");

  while(1){
    read_commands(modem_fd, command, 200);

    if(strcmp(command, "1") == 0 || strcmp(command, "2") == 0){
      int linkNum = -1;

      kill_sound();      

      if(strcmp(command, "1") == 0){
	char file1[] = "enteringURL";
	char file2[] = "enteringFTP";
	char buffer[256];
	if(mode == 0)
	  play_sound(file1);
	else
	  play_sound(file2);
	bzero(buffer, 256);
	read_web_address(modem_fd, buffer, 200);      
	kill_sound();      
	play_url(buffer);
	strcpy(url, prefix[mode]);
	strcat(url, buffer);
	sleep(3);	
      }else{
	char file[] = "enteringLinkNum";
	kill_sound();      
	if(current == NULL){
	  char file1[] = "pagenotloaded";
	  play_sound(file1);
	  continue;
	}else{
	  play_sound(file);
	  read_num(modem_fd, &linkNum);
	  kill_sound();      
	}
      }

      if( ((strcmp(command, "2") == 0) && (current!= NULL && (linkNum > current->numLinks || linkNum < 0))) ){
	char file[] = "wronglinknum";
	play_sound(file);
      }else{
	if(traverse->url == NULL){
	  traverse->url = new_url();
	  current = traverse->url;
	  insert_historylist(url);
	  goto_page(url);
	}else{
	  back = traverse;
	  if(traverse->next)
	    free_node(traverse->next);
	  traverse->next = (NODE*)malloc(sizeof(NODE));
	  traverse = traverse->next;
	  back->next = traverse;
	  traverse->back = back;
	  traverse->next = NULL;
	  
	  traverse->url = new_url();
	  current = traverse->url;
	  if(strcmp(command, "1") == 0){
	    insert_historylist(url);
	    goto_page(url);
	  }else{
	    insert_historylist(url);
	    goto_page(back->url->linkNames[linkNum]);
	  }
	}
      }

    }else if(strcmp(command, "3") == 0){
      kill_sound();      
      if(traverse->back){
	char string[] = "Going back to ";
	traverse = traverse->back;
	current = traverse->url;
	fprintf(stderr, "going back\n");
	play_page_url(current, current->url, string, 0);
      }else{
	char file[] = "cannotgoback";
	play_sound(file);
	fprintf(stderr, "cannot go back anymore\n");
      }

    }else if(strcmp(command, "4") == 0){
      kill_sound();      
      if(traverse->next){
	char string[] = "Going forward to ";
	traverse = traverse->next;
	current = traverse->url;
	fprintf(stderr, "going forward\n");
	play_page_url(current, current->url, string, 0);
      }else{
	char file[] = "cannotgoforward";
	play_sound(file);
	fprintf(stderr, "cannot go forward anymore\n");
      }

    }else if(strcmp(command, "5") == 0){
      kill_sound();      
      fprintf(stderr, "playing page again\n");
      if(current){
	if(current->text == NULL){
	  if(strstr(current->filename, ".au") != NULL){
	    play_song(current->filename);
	  }else{
	    char file[] = "emptypage";
	    fprintf(stderr, "empty page\n");
	    play_sound(file);
	  }
	}else{
	  play_file(current->filename);
	}
      }
      else{
	char file[] = "pagenotloaded";
	play_sound(file);
      }

    }else if(strcmp(command, "6") == 0){
      int linkNum = -1;
      char file[] = "wronglinknum";
      kill_sound();      
      if(current){
	char string[] = " The current page is  ";
	char file[] = "enteringLinkNum";
	play_page_url(current, current->url, string, 1);
	if(current->text != NULL){
	  sleep(1);
	  play_sound(file);
	  read_num(modem_fd, &linkNum);
	  if(linkNum > current->numLinks || linkNum < 0){
	    play_sound(file);
	  }else{
	    char string[256];
	    sprintf(string, "The %dth link of the page is ", linkNum);
	    play_page_url(current, current->linkNames[linkNum], string, 0);
	  }
	}
      }else{
	char file[] = "pagenotloaded";
	play_sound(file);
      }

    }else if(strcmp(command, "7") == 0){

      char file[] = "historylist";
      int linkNum = -1;
      fprintf(stderr, "use history list\n");
      kill_sound();      

      if(historylist_counter){
	play_history_summary();
	sleep(2);
	play_sound(file);
	
	read_num(modem_fd, &linkNum);
	kill_sound();
	if(linkNum >= 0 && linkNum < historylist_counter){
	  char file[] = "usehistory";
	  char buffer[256], url[256];
	  bzero(buffer, 256);
	  play_url(history_list[linkNum]);
	  sleep(3);
	  play_sound(file);
	  sleep(3);
	  bzero(buffer, 256);

	  strcpy(buffer, history_list[linkNum]);

	  if(read_web_address(modem_fd, buffer, 200) > 0){
	    strcpy(url, buffer);
	    play_url(buffer);
	    sleep(3);
	    fprintf(stderr, "%s.\n", url);
	    back = traverse;
	    if(traverse->next)
	      free_node(traverse->next);
	    traverse->next = (NODE*)malloc(sizeof(NODE));
	    traverse = traverse->next;
	    back->next = traverse;
	    traverse->back = back;
	    traverse->next = NULL;
	    
	    traverse->url = new_url();
	    current = traverse->url;
	    insert_historylist(url);
	    goto_page(url);
	  }

	}else{
	  char file[] = "wronghistorylinknum";
	  play_sound(file);
	}
      }else{
	char file[] = "emptyhistorylist";
	play_sound(file);
	sleep(2);
      }

    }else if(strcmp(command, "8") == 0){
      char command[256];
      kill_sound();      
      fprintf(stderr, "stop playing\n");

    }else if(strcmp(command, "9") == 0){
      char file[] = "welcome";
      kill_sound();      
      fprintf(stderr, "play help\n");
      play_sound(file);

    }else if(strcmp(command, "0") == 0){
      char file1[] = "http_to_ftp";
      char file2[] = "ftp_to_http";
      kill_sound();
      if(mode == 1){
	mode = 0;
	play_sound(file2);
      }else{
	mode = 1;
	play_sound(file1);
      }
    }else{
      kill_sound();      
      fprintf(stderr, "your command is not understood\n");
      play_sound("wrongcommand");
    }
  }
}

void read_func()
{
  char buf[200];
  int i;
  
  /*  configure_modem();*/

  while(1){
    i = readline(modem_fd, buf, 200);

    fprintf(stderr, ".%s.\n", buf);

    if(strstr(buf, "RING") != 0){

      strcpy(buf, "ata\n");
      i = writen(modem_fd, buf, strlen(buf));

      i = readline(modem_fd, buf, 200);
      fprintf(stderr, ".%s.\n", buf);      

      if(strstr(buf, "ANSWERED") == 0){
	fprintf(stderr, "cannot answer phone call! exiting...\n");
	exit(1);
      }else{
	configure_modem();
	process_commands();
      }

      strcpy(buf, "ath\n");
      i = writen(modem_fd, buf, strlen(buf));
    }
  }
}

void main()
{
  thread_t tid1;

  open_modem();

  thr_create(NULL, NULL, read_func, NULL, 0, &tid1);
  while (thr_join(NULL, NULL, NULL) == 0)  sleep(1);

  close(modem_fd);
}



