//--------------------------------------------|
//                                            |
//  BlueCon v0.6 (15/12/2004)                 |
//                                            |
//  Chris Lindenmüller, Benjamin Mack         |
//  Thomas Müller, Boris Wüst                 |
//      HdM Stuttgart                         | 
//                                            |
//--------------------------------------------|

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

#include "blauzahn.h"
#include "bluecon.h"

//for global access to sock
int sock;
int doexit = 0;
unsigned long bufSize = 0;

//Bluetooth Socket parameter
struct sockaddr_rc laddr, raddr;
struct hci_dev_info di;

int userImput(){
 char prot;
 int choose;
 int data_size = DATA_SIZE_LENGTH;
 printf("\n\nMenue\n-----------------------------------------\n");
 printf("1) request a new picture\n2) send picture via email\n3) disconnect and exit\n\n");
 scanf("%i",&choose);
  
 switch(choose) {
  case 1: //request a new picture
   prot = CAM_PIC_REQ;
   sendProto(&prot);
   break;
   
  case 2: //send picture via email
   char email[50];
   printf("Please enter the reciepiant address;\n");
   //read address from console
   scanf("%s",email);
   //Length of address
   int addrSize;
   addrSize=strlen(email);
   char send[2+data_size+addrSize]; //makes send big enough for flags/size/data
   //control output
   printf("destination address: %s\n",email);
   printf("Size of address: %i\n",addrSize);
   printf("Size of send[]: %i\n",sizeof(send));
   
   //add flags for send byte
   send[0] = SEND_EMAIL;
   send[1] = DATA_SIZE;
   
   //Add data_size_length
   char formatstring[4];
   sprintf(formatstring,"%%%ii",data_size);
   char temp[data_size];
   sprintf(temp,formatstring,addrSize); //converts int addrSize to char[] with length of DATA_SIZE_LENGTH
   printf("temp: %s\n",temp);
   
   //combine the two array?s
   for (unsigned int i = 0; i < sizeof(temp); i++) {
    send[2+i] = temp[i]; //starts with third field of send
   }
   
   //add the email address
   for (int i = 0; i < addrSize; i++) {
    send[2+data_size+i] = email[i]; //starts with first field after dataSize
   }   
   
   //control output
   for (unsigned int i = 0; i < sizeof(send); i++) {
    printf("send_%i: %i : %c\n",i,send[i],send[i]);
   }
   
   //send it
   sendData(send,sizeof(send));
   userImput();
   
   break;

  case 3: //exit the programm
   printf("exiting...\n");
   doexit = 1;
   break;
   
  default: //to when nothing else to do
   printf("what?...\n");
   //userImput();
   break;
 }
 return 0;
}

//What to do
int examProto(char *buf){
 char prot;
 switch (*buf) {
  case SESSION_START:
   printf("SESSION_START empfangen\n");
   prot = SESSION_START_ACK;
   sendProto(&prot);
   break;
   
  case SESSION_START_ACK:
   printf("SESSION_START_ACK empfangen\n");
   //request picture
   prot = CAM_PIC_REQ;
   sendProto(&prot);
   break;
   
  case SESSION_END:
   printf("SESSION_END empfangen\n");
   //exit programm
   prot = SESSION_END_ACK;
   sendProto(&prot);
   doexit = 1;
   break;
   
  case SESSION_END_ACK:
   printf("SESSION_END_ACK empfangen\n");
   //exit programm
   doexit = 1;
   break;
  
  case DATA_SIZE:
   //set size of buffer
   printf("DATA_SIZE empfangen\n");
   int bytes;
   char buf[DATA_SIZE_LENGTH];
   //recieve size of buffer in DATA_SIZE_LENGTH Bytes
   bytes = recv(sock,buf,sizeof(buf),0);
   printf("%i Bytes an DATA_SIZE empfangen\n",bytes);
   
   //convert bytes to long
   unsigned long size;
   size = atol(buf);   

   printf("BufferSize: %li\n",size);
   bufSize = size;
   
   //recieve data
   if (recvData(size) < 0){
      return -1;
     }
     
     //what to do if pics is here
     userImput();
                  
   break;

  case SEND_EMAIL_SUCCESS:
   printf("SEND_EMAIL_SUCCESS empfangen\n");
   printf("\nPicture send via emial successful\n");
   //show again the user dialog
   userImput();
   break; 

  case SEND_EMAIL_FAIL:
   printf("SEND_EMAIL_FAIL empfangen\n");
   printf("\nPicture send via emial aborted\n");
   //show again the user dialog
   userImput();
   break; 

  case CAM_PIC_DATA:
   printf("CAM_PIC_DATA empfangen\n");

   break;
  
  default:
   printf("recieved unkown protocol header\n");
   break;
 } 
 
 return 0;
}


//recieves the header bytes
int recvProto(){
 printf("Waiting for Protocol Header\n");
 //Recive max of DATA_SIZE_LENGTH
 char buf;
 int bytes;
 //int bytes = 1;
 //while(bytes > 0){
 bytes = recv(sock,&buf,sizeof(buf),0);
    if(bytes > 0){
    printf("\n%i Byte(s) recieved.\nData: %i\n",bytes,buf);      
    //exam the header
    if (examProto(&buf)<0){
     return -1;
     }
   }
 //}
 return 0;
}


//recieves the data
int recvData(unsigned long size){
 char filename[50];
 printf("Enter filename of new picture:\n");
 scanf("%s",filename);
 
 printf("Waiting for Data..\n");
 char buf[size];
 int bytes;
 
 //Create a new File
 printf("create a new file...\n");
 FILE *datei_ptr;
 datei_ptr = fopen(filename,"wb");
 if(datei_ptr != NULL){
   printf("file opened...\n");
 } else {
  perror("Unable to open the file");
  return -1;
 }

 //Recieving data
 unsigned int sum = 0;
 while(sum < size){
  bytes = recv(sock,buf,sizeof(buf),0);
  fwrite(buf,1,bytes,datei_ptr);
  sum += bytes;
  printf("%i Byte(s) recieved\n",bytes);
 }
 printf("Sum of Bytes recieved: %i \n",sum);
 
 fclose(datei_ptr);
 printf("Data saved in file: %s\n",filename);
 return 0;
}

//sends Protokol Header
int sendProto(char *buf){
 int bytes;
   bytes = send(sock,buf,sizeof(*buf),0);
   if(bytes > 0){
   } else {
    perror("Could not send Bytes");
    return -1;
   } 
   return 0;
}

//Send Data
int sendData(char *buf,int length){
 int bytes;
   bytes = send(sock,buf,length,0);
   if(bytes > 0){
    printf("%i Byte(s) transmitted\n",bytes);
   } else {
    perror("Could not send Bytes");
    return -1;
   } 
   return 0;
}


//set the connection parameter
int setupConnection(){
 //set the connection parameter
 int hci_dev = 0;
 char addr[18] = "00:02:5B:01:00:3C";
 int channel; 
 hci_dev = 0;
 channel = 4;
 printf("dev:%i addr:%s channel:%i \n",hci_dev,addr,channel);
   
 //gather informations from hci_dev
 if(hci_devinfo(hci_dev, &di) < 0)
   {
     perror("HCI device info failed");
     return -1;
   }
  
 //set locale and remote address and typ
 laddr.rc_family = AF_BLUETOOTH;
 laddr.rc_bdaddr = di.bdaddr; //local address
 laddr.rc_channel = 0;
 
 raddr.rc_family = AF_BLUETOOTH;
 str2ba(addr,&raddr.rc_bdaddr); //Rrmote address
 raddr.rc_channel = htobs(channel);
 
 //create a new socket
 sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

 if(sock < 0)
   {
     perror("socket");
     return -1;
   }
  
 //bind this socket
 if(bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)) < 0)
   {
     perror("bind");
     return -1;;
   }
 
 return 0;
}


//connect the socket
int connect(){

 if(connect(sock, (struct sockaddr *)&raddr, sizeof(raddr)) < 0)
   {
     perror("connect");
     return -1;
   }
   printf("Connected.\n");
 
 return 0;
}

 

int main(int argc, char **argv) {

 //set up the conenction
 if(setupConnection() < 0){
  exit(1);
 }
 
 //connect the socket
 if(connect() < 0){
  exit(1);
 } 
   
   //waiting for first header
   while(!doexit){
  if(recvProto() < 0)
    {
       perror("recvData");
       exit(1);
    }    
   } 

   printf("Disconnected.\n");
  //close(sock);
  return 0;
}
