#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

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



#include "sessions_sdp.h"
#include "parser_sdp.h"

void
Panic(char *Filename, int Line)
{
   fprintf(stderr, "\n!! Panic in line %d of file %s\n", Line, Filename);
   perror("Unexpected library error");
   fprintf(stderr, "\n");
   abort();
}

#define PANIC (Panic(__FILE__, __LINE__))

/* Payload type map. */
static struct {
  char *enc;      /* encoding name */
  int  rate;      /* sampling rate for audio; clock rate for video */
  int  ch;        /* audio channels; 0 for video */
} pt_map[256];

static void
usage(void)
{
   fprintf(stderr, "Usage: wrtpLaunch -f file\n");
}

void
get_video_dest(struct session *sess, char *dest) {
   struct media *tmp;
   int found = 0;

   /* Insert media ports */
   tmp = sess->media;
 
   while((tmp != NULL) && !found)
   {
      if(strcmp(tmp->media, "video") == 0)
      {
         char port[10];
         strcat(dest, inet_ntoa(tmp->addr));
         strcat(dest, "/");
         sprintf(port, "%d", tmp->port);
         strcat(dest, port);
         strcat(dest, "/1");
         found = 1;
      }
      tmp = tmp->next;
   }
}

void
get_audio_dest(struct session *sess, char *dest) {
   struct media *tmp;
   int found = 0;

   /* Insert media ports */
   tmp = sess->media;
 
   while((tmp != NULL) && !found)
   {
      if(strcmp(tmp->media, "audio") == 0)
      {
         char port[10];
         strcat(dest, inet_ntoa(tmp->addr));
         strcat(dest, "/");
         sprintf(port, "%d", tmp->port);
         strcat(dest, port);
         strcat(dest, "/1");
         found = 1;
      }
      tmp = tmp->next;
   }
}

void
CheckChildren(void)
{
    int status;

    if(wait(&status) == -1)
    {
       fprintf(stderr, "Child no exists yet\n");
    }

    if((WIFEXITED(status) != 0) && (WEXITSTATUS(status) != 0))
    {
       fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(status));
    }

    if(WIFSIGNALED(status))
       fprintf(stderr, "Child died with signal %d\n", WTERMSIG(status));

    if(WIFSTOPPED(status))
       fprintf(stderr, "Child stopped by signal %d\n", WSTOPSIG(status));
}

void
CreateChildVic(struct session *sess)
{
    char dest[1024];

    memset(dest, 0, sizeof(dest));
    get_video_dest(sess, dest);
    switch(fork())
    {
       case -1:  PANIC;
                 break;
       case 0:

#ifdef DEBUG
                 printf("Creating Vic: vic -A rtp -C %s -s -P -f h261 -X geometry=250x250+302+0 %s\n", sess->sname, dest);
#endif /* DEBUG */
                 execlp("vic", "vic", "-A", "rtp" , "-C", sess->sname, "-s", "-P", "-f", "h261", "-X", "geometry=250x250+302+0", dest, NULL);
                 PANIC;
    }
}

void
CreateChildVat(struct session *sess)
{
    char dest[1024];

    memset(dest, 0, sizeof(dest));
    get_audio_dest(sess, dest);
    switch(fork())
    {
       case -1:  PANIC;
                 break;
       case 0:

#ifdef DEBUG
                 printf("Creating Vat: vat -r -C %s -X geometry=+0+0 %s\n", sess->sname, dest);
#endif /* DEBUG */

                 execlp("vat", "vat", "-r", "-C", sess->sname, "-X", "geometry=+0+0", dest, NULL);
                 PANIC;
    }
}

void
Create_Vic_Vat(struct session *sess)
{
   CreateChildVic(sess);
   CreateChildVat(sess);
   CheckChildren();
   CheckChildren();
}

void
main(int argc, char* argv[])
{
    extern char *optarg;
    extern int optopt;

    struct session *sess = NULL;

    int c, i;
    char *filename = NULL;

    FILE *file;

/*    char *session_description; */

    while ((c = getopt(argc, argv, "f:")) != EOF)
    {
       switch(c)
       {
          case 'f':  filename = optarg;
                     break;
          case ':':  // -c, -t, -a o -v without arguments parsed for ":"
                     fprintf(stderr, "Option -%c requires an argument\n", 
                                      (char)optopt);
                     usage();
                     exit(1);
          case '?':  // "Unrecognized option: -" optopt
                     usage();
                     exit(1);
          case 'h':
                     usage();
                     exit(1);

       }
    }
    if(filename == NULL)
    {
       usage();
       exit(1);
    }

   if ((file = fopen(filename, "r" )) == NULL )
   {
      fprintf(stderr, "\nFile %s specified could not be found\n", filename);
      exit(1);
   }
   
   if((sess = parse_SDP_file(file)) == NULL)
   {
       fclose(file);
       fprintf(stderr, "\nFile %s specified is not correctly parsed\n", filename);
       exit(1);
   }
  /*
   * Set up payload type map. We should be able to read this in
   * from a file.
   */
  for (i = 0; i < 256; i++) {
    pt_map[i].enc  = "????";
    pt_map[i].rate = 0;
    pt_map[i].ch   = 0;
  }
  pt_map[  0].enc = "pcmu"; pt_map[  0].rate =  8000; pt_map[  0].ch = 1;
  pt_map[  1].enc = "1016"; pt_map[  1].rate =  8000; pt_map[  1].ch = 1;
  pt_map[  2].enc = "g721"; pt_map[  2].rate =  8000; pt_map[  2].ch = 1;
  pt_map[  3].enc = "gsm "; pt_map[  3].rate =  8000; pt_map[  3].ch = 1;
  pt_map[  4].enc = "g723"; pt_map[  4].rate =  8000; pt_map[  4].ch = 1;
  pt_map[  5].enc = "idvi"; pt_map[  5].rate =  8000; pt_map[  5].ch = 1;
  pt_map[  6].enc = "idvi"; pt_map[  6].rate = 16000; pt_map[  6].ch = 1;
  pt_map[ 10].enc = "l16 "; pt_map[ 10].rate = 44100; pt_map[ 10].ch = 2;
  pt_map[ 11].enc = "l16 "; pt_map[ 11].rate = 44100; pt_map[ 11].ch = 1;
  pt_map[ 23].enc = "scr "; pt_map[ 23].rate = 65536; pt_map[ 23].ch = 0;
  pt_map[ 24].enc = "mpeg"; pt_map[ 24].rate = 65536; pt_map[ 24].ch = 0;
  pt_map[ 25].enc = "cellb"; pt_map[ 25].rate = 65536; pt_map[ 26].ch = 0;
  pt_map[ 26].enc = "jpeg"; pt_map[ 26].rate = 65536; pt_map[ 26].ch = 0;
  pt_map[ 27].enc = "cusm"; pt_map[ 27].rate = 65536; pt_map[ 27].ch = 0;
  pt_map[ 28].enc = "nv  "; pt_map[ 28].rate = 65536; pt_map[ 28].ch = 0;
  pt_map[ 29].enc = "picw"; pt_map[ 29].rate = 65536; pt_map[ 29].ch = 0;
  pt_map[ 30].enc = "cpv "; pt_map[ 30].rate = 65536; pt_map[ 30].ch = 0;
  pt_map[ 31].enc = "h261"; pt_map[ 31].rate = 65536; pt_map[ 31].ch = 0;
 

  Create_Vic_Vat(sess);

/*
   session_description = make_session_description(sess);
   printf("\n%s\n", session_description);
*/
}
