#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include "typedef.h"
#include "interf_enc.h"
#include "interf_dec.h"

#define AMR_MAGIC_NUMBER "#!AMR\n"

static const short modeConv[]={
   475, 515, 59, 67, 74, 795, 102, 122};

static void Usage(char* argv[])
{
   fprintf (stderr,
      "Usage of %s:\n\n"
      "[-dtx] mode speech_file encoded_decoded_file \n\n"
      "or \n\n"
      "[-dtx] -modefile=mode_file speech_file bitstream_file \n\n\n"
      "mode = MR475, MR515, MR59, MR67, MR74, MR795, MR102, MR122 \n\n\n",
      argv[0]);
}
void Copyright(void){
fprintf (stderr,
"===================================================================\n"
" 3GPP AMR Floating-point Speech Encoder                            \n"
"===================================================================\n"
);
}

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

   /* file strucrures */
   FILE * file_speech = NULL;	//input file
   FILE * file_mode = NULL;	//mode file
   FILE * file_enc_dec = NULL;	//output file
   FILE * file_encoded = NULL;	//temp file

   /* input speech vector */
   short speech[160];

   /* counters */
   int byte_counter, frames = 0, bytes = 0;

   /* pointer to encoder state structure */
   int *enstate;
   int *destate;
   
   int read_size;

   /* requested mode */
   enum Mode req_mode = MR122;
   int dtx = 0;

   /* temporary variables */
   char mode_string[9];
   long mode_tmp;

   /* bitstream filetype */
   unsigned char serial_data[32];
   enum Mode dec_mode;
   short block_size[16]={ 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };

   /* Process command line options */

   if ((argc == 5) || (argc == 4)){
      file_enc_dec = fopen(argv[argc - 1], "wb");
      if (file_enc_dec == NULL){
         Usage(argv);
         return 1;
      }
      file_speech = fopen(argv[argc - 2], "rb");
      if (file_speech == NULL){
         fclose(file_enc_dec);
         Usage(argv);
         return 1;
      }
      if (strncmp(argv[argc - 3], "-modefile=", 10) == 0){
         file_mode = fopen(&argv[argc - 3][10], "rt");
         if (file_mode == NULL){
            Usage(argv);
            fclose(file_speech);
            fclose(file_enc_dec);
            return 1;
         }
      }
      else {
         mode_tmp = strtol(&argv[argc - 3][2], NULL, 0);
         for (req_mode = 0; req_mode < 8; req_mode++){
            if (mode_tmp == modeConv[req_mode])
               break;
         }
         if (req_mode == 8){
            Usage(argv);
            fclose(file_speech);
            fclose(file_enc_dec);
            if (file_mode != NULL)
               fclose(file_mode);
            return 1;
         }
      }
      if (argc == 5){
         if ((strcmp(argv[1], "-dtx") != 0)){
            Usage(argv);
            fclose(file_speech);
            fclose(file_enc_dec);
            if (file_mode != NULL){
               fclose(file_mode);
            }
            return 1;
         }
         else {
            dtx = 1;
         }
      }
   }
   else {
      Usage(argv);
      return 1;
   }


   enstate = Encoder_Interface_init(dtx);

   Copyright();
   fprintf( stderr, "%s\n", "Code compiled with VAD option: VAD1");

   file_encoded = fopen("temp.cod", "wb");
   if (file_encoded == NULL){
   	Usage(argv);
   	return 1;
   }

   /* read file */
   while (fread( speech, sizeof (Word16), 160, file_speech ) > 0)
   {
      /* read mode */
      if (file_mode != NULL){
         req_mode = 8;
         if (fscanf(file_mode, "%9s\n", mode_string) != EOF) {
            mode_tmp = strtol(&mode_string[2], NULL, 0);
            for (req_mode = 0; req_mode < 8; req_mode++){
               if (mode_tmp == modeConv[req_mode]){
                  break;
               }
            }
         }
         if (req_mode == 8){
            break;
         }
      }

      frames ++;

      /* call encoder */
      byte_counter = Encoder_Interface_Encode(enstate, req_mode, speech, serial_data, 0);

      bytes += byte_counter;
      fwrite(serial_data, sizeof (UWord8), byte_counter, file_encoded );
      fflush(file_encoded);
   }
   Encoder_Interface_exit(enstate);

   fprintf ( stderr, "\n%s%i%s%i%s\n", "Frame structure AMR MIME file storage format: ", frames, " frames, ", bytes, " bytes.");

   fclose(file_speech);
   fclose(file_encoded);
   if (file_mode != NULL)
      fclose(file_mode);
      
   /*****************************************************************************************************************************/      
   file_encoded = fopen("temp.cod", "rb");
   if (file_encoded == NULL){
		fprintf ( stderr, "file_encoded read error!!!\n");
         return 1;
   }
   /* init decoder */
   destate = Decoder_Interface_init();      

   frames = 0;

   /* find mode, read file */
   while (fread(serial_data, sizeof (unsigned char), 1, file_encoded ) > 0)
   {
      dec_mode = (serial_data[0] >> 3) & 0x000F;
	  read_size = block_size[dec_mode];

      fread(&serial_data[1], sizeof (char), read_size, file_encoded );

      frames ++;

      /* call decoder */
      Decoder_Interface_Decode(destate, serial_data, speech, 0);

      fwrite( speech, sizeof (short), 160, file_enc_dec );
   }

   Decoder_Interface_exit(destate);      

   fclose(file_enc_dec);
   fclose(file_encoded);      

   return 0;
}
