#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <float.h>
#include <time.h>

#include "cree_png.h"

#include "bufrlib.h"
#include "bufr_io.h"

radar_data_t b;

int subset_courant = 1;

static char * set_fuseau(char * nouveau)
{
  if (!nouveau) return nouveau;
  {
    char * ancien = getenv("TZ");
    if (ancien) ancien -= strlen("TZ=");
    putenv(nouveau);
    tzset();
    return ancien;
  }
}

int get_elt (dd *d, varfl val) 
{
  static int minute_reelle;
  int got_it = 1;
  if ((subset_courant == 1) && bufr_check_fxy (d, 0,5,33)) {
	b.img.psizex = val;
      }
      else if ((subset_courant == 1) && bufr_check_fxy (d, 0,6,33)) {
	b.img.psizey = val;
      }
      else if ((subset_courant == 1) && bufr_check_fxy (d, 0,30,21)) {
	b.img.ncols = val;
      }
      else if ((subset_courant == 1) && bufr_check_fxy (d, 0,30,22)) {
	b.img.nrows = val;
      }
      else if ((subset_courant == 1) && bufr_check_fxy (d, 0,4,5)) {
	minute_reelle = val;
      }
      else if ((subset_courant == 1) && bufr_check_fxy (d, 0,4,6)) {
	char * tz = set_fuseau("TZ=UTC");
	struct tm local;
	local.tm_year = b.meta.year - 1900;
	local.tm_mon = b.meta.month - 1;
	local.tm_mday = b.meta.day;
	local.tm_hour = b.meta.hour;
	local.tm_min = b.meta.min;
	local.tm_sec = b.meta.sec;
	local.tm_wday = 0;
	local.tm_yday = 0;    
	local.tm_isdst = 0;
	time_t nominal = mktime(&local);
	fprintf(stderr, "Heure nominale: %s", ctime(&nominal));
	local.tm_min = minute_reelle;
	local.tm_sec = val;
	time_t reel = mktime(&local);
	fprintf(stderr, "Heure réelle estimée: %s", ctime(&reel));
	if (reel > nominal + 1800) {
	  reel -= 3600;
	} else if (reel + 1800 < nominal) {
	  reel += 3600;
	}
	fprintf(stderr, "Heure réelle: %s", ctime(&reel));
	local = *gmtime(&reel);
	set_fuseau(tz);	
	b.meta.year = local.tm_year + 1900;
	b.meta.month = local.tm_mon + 1;
	b.meta.day = local.tm_mday;
	b.meta.hour = local.tm_hour;
	b.meta.min = local.tm_min;
	b.meta.sec = local.tm_sec;
      }
      else if ((subset_courant == 1) && bufr_check_fxy (d, 0,7,21)) {
	b.polar.elangle = val;
      }
      else if ((subset_courant == 1) && _replicating && bufr_check_fxy (d, 0, 21, 219)) { 
	static int n = 0;
	if (n == 0) {
	  fprintf(stderr, "Replication table de seuils de taille %d\n", _replicating);
	  assert(_replicating < 255);
	  b.img.scale.nvals = _replicating;
	  n = _replicating;
	}
	b.img.scale.vals[n-_replicating] = val;
	if (_replicating == 1) {
	  n = 0;
	}
      }
      else if (_replicating && bufr_check_fxy (d, 0, 30, 2)) { 
	static int n = 0;
	static int nrepet = 0;
	/* il y a un bug sur des '1 x 0' récursif, _replicating trop grand de 1 */
	if (_replicating == (b.img.ncols+1)) {
	  _replicating--;
	  if (n == 0) fprintf(stderr, "Replication d'une ligne de %d colonnes\n", b.img.ncols);
	}
	if ((n == 0) && (nrepet == 0)) {
	  assert(_replicating == b.img.ncols);
	  n = b.img.nrows*b.img.ncols;
	  nrepet = b.img.nrows;
	  b.img.data = calloc(n, sizeof(unsigned short));
	  assert(b.img.data);
	}
	b.img.data[n-(nrepet*b.img.ncols)+b.img.ncols-_replicating] = val;
	if (_replicating == 1) {
	  // fprintf(stderr, "Fin replication ligne\n");
	  nrepet--;
	  /* il y a un bug sur des '1 x 0' récursif, _replicating trop grand de 1 */
	  _replicating++;
	}
	if (nrepet == 0) {
	  fprintf(stderr, "Fin replication de %d lignes\n", b.img.nrows);
	  n = 0;
	}
      }
      else {
	got_it = 0;
      }
      return got_it;
}

int get_seq (dd * d, varfl *vv)
{
  int got_it = 1;
        /* WMO block and station number */
       if ((subset_courant == 1) && bufr_check_fxy (d, 3,1,1)) { 
	  int i = 0;
	  b.wmoblock = vv[i++];
	  b.wmostat = vv[i++];
       }
       else if ((subset_courant == 1) && bufr_check_fxy (d, 3,21,11)) { 
	  int i = 0;
	  b.img.type = vv[i++];
	  i++;
	  b.img.grid = vv[i++];
	  assert(b.img.grid == 0);
	} 
       else if ((subset_courant == 1) && bufr_check_fxy (d, 3,1,11)) { 
	  int i = 0;
	  b.meta.year = vv[i++];       /* Date */
	  b.meta.month = vv[i++];
	  b.meta.day = vv[i++];
	} 
	else if ((subset_courant == 1) && bufr_check_fxy (d, 3,1,13)) { 
	  int i = 0;
	  b.meta.hour = vv[i++];       /* Time */
	  b.meta.min = vv[i++];
	  b.meta.sec = vv[i++];
	  /* Véritables minutes/secondes par ailleurs */
	}
	else if ((subset_courant == 1) && bufr_check_fxy (d, 3,1,21)) { 
	  int i = 0;
	  b.meta.radar.lat = vv[i++];  /* Position */
	  b.meta.radar.lon = vv[i++];
	} else if ((subset_courant == 1) && bufr_check_fxy (d, 3,21,10)) { 
	  b.meta.radar_height = vv[1]+vv[2];
	}
	else {
	got_it = 0;
      }
      return got_it;
}

static void zoom(radar_data_t *b)
{
  int ncols = b->img.ncols, nrows = b->img.nrows;
  unsigned short *ptr = b->img.data;
  unsigned short *ptr2 = calloc(ncols*nrows/4, sizeof(unsigned short));
  int i, j;

  assert((ncols%4 == 0) && (nrows%4 == 0));
  for (i = ncols/4; i < 3*ncols/4; ++i) {
    for (j = nrows/4; j < 3*nrows/4; ++j) {
      ptr2[i - ncols/4  + (j - nrows/4)*ncols/2] = ptr[i + j*ncols]; 
    }
  }
  b->img.ncols /= 2;
  b->img.nrows /= 2;
  b->img.data = ptr2;
  free(ptr);
}

/*===========================================================================*/

int vraie_taille_palette = 80;
double seuils_france54[80] = {
  -100, -40, -9, -8, -7,
               -6,
               -5,
               -4,
               -3,
               -2,
               -1,
                0,
                1,
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9,
               10,
               11,
               12,
               13,
               14,
               15,
               16,
               17,
               18,
               19,
               20,
               21,
               22,
               23,
               24,
               25,
               26,
               27,
               28,
               29,
               30,
               31,
               32,
               33,
               34,
               35,
               36,
               37,
               38,
               39,
               40,
               41,
               42,
               43,
               44,
               45,
               46,
               47,
               48,
               49,
               50,
               51,
               52,
               53,
               54,
               55,
               56,
               57,
               58,
               59,
               60,
               61,
               62,
               63,
               64,
               65,
               66,
               67,
  68 };

  //  8, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 80 };
png_color palette[256] = {
{ 32, 36, 128 },
{ 32, 41, 129 },
{ 33, 47, 131 },
{ 33, 52, 132 },
{ 33, 57, 134 },
{ 34, 62, 135 },
{ 34, 68, 137 },
{ 35, 74, 138 },
{ 35, 79, 140 },
{ 35, 85, 141 },
{ 36, 91, 143 },
{ 36, 97, 144 },
{ 36, 103, 146 },
{ 37, 109, 147 },
{ 37, 116, 149 },
{ 38, 122, 150 },
{ 38, 129, 152 },
{ 38, 135, 153 },
{ 39, 142, 155 },
{ 39, 149, 156 },
{ 39, 156, 158 },
{ 40, 159, 156 },
{ 40, 161, 151 },
{ 41, 162, 147 },
{ 41, 164, 143 },
{ 41, 165, 138 },
{ 42, 167, 134 },
{ 42, 168, 129 },
{ 42, 170, 124 },
{ 43, 171, 119 },
{ 43, 173, 114 },
{ 44, 174, 109 },
{ 44, 176, 104 },
{ 44, 177, 98 },
{ 45, 179, 93 },
{ 45, 180, 87 },
{ 45, 182, 82 },
{ 46, 183, 76 },
{ 46, 185, 70 },
{ 47, 186, 64 },
{ 47, 188, 58 },
{ 47, 189, 52 },
{ 50, 191, 48 },
{ 57, 192, 48 },
{ 64, 194, 48 },
{ 72, 195, 49 },
{ 79, 197, 49 },
{ 87, 198, 50 },
{ 94, 200, 50 },
{ 102, 201, 50 },
{ 110, 203, 51 },
{ 118, 204, 51 },
{ 126, 206, 51 },
{ 134, 207, 52 },
{ 143, 209, 52 },
{ 151, 210, 53 },
{ 160, 212, 53 },
{ 168, 213, 53 },
{ 177, 215, 54 },
{ 186, 216, 54 },
{ 195, 218, 54 },
{ 204, 219, 55 },
{ 213, 221, 55 },
{ 222, 222, 56 },
{ 224, 216, 56 },
{ 225, 209, 56 },
{ 227, 203, 57 },
{ 228, 196, 57 },
{ 230, 189, 57 },
{ 231, 182, 58 },
{ 233, 175, 58 },
{ 234, 168, 59 },
{ 236, 161, 59 },
{ 237, 154, 59 },
{ 239, 146, 60 },
{ 240, 139, 60 },
{ 242, 131, 60 },
{ 243, 123, 61 },
{ 245, 116, 61 },
{ 246, 108, 62 },
{ 248, 100, 62 },
{ 249, 91, 62 },
{ 251, 83, 63 },
{ 252, 75, 63 },
{ 254, 66, 63 },
{ 254, 64, 64 } 
};

  /*                           {255, 255, 255}, /\* "White" *\/ */
  /* 			    {72,  61, 139},  /\* "DarkSlateBlue" *\/ */
  /* 			    {0, 0, 205},     /\* "MediumBlue" *\/ */
  /* 			    {30, 144, 255},  /\* "DodgerBlue" *\/ */
  /* 			    {173, 216, 230}, /\* "LightBlue" *\/ */
  /* 			    {85, 107,  47},  /\* "DarkOliveGreen" *\/ */
  /* 			    {60, 179, 113},  /\* "MediumSeaGreen" *\/ */
  /* 			    {127, 255, 212}, /\* "Aquamarine" *\/ */
  /* 			    {127, 255,   0}, /\* "Chartreuse" *\/ */
  /* 			    {255, 255,   0}, /\* "Yellow" *\/ */
  /* 			    {240, 230, 140}, /\* "khaki" *\/ */
  /* 			    {222, 184, 135}, /\* "burlywood" *\/ */
  /* 			    {255, 165,   0}, /\* "Orange" *\/ */
  /* 			    {160,  82,  45}, /\* "sienna" *\/ */
  /* 			    {255,   0,   0}  /\* "Red" *\/ */
  /* }; */

png_color no_value = {255, 192, 203}; /* Pink */

int kml = 0;

/*===========================================================================*/

static char *usage = "Usage: martinique [-k] [-t] [-d tabdir] input_file image_file_base\n";

int main (int argc, char** argv)

{
    char destfile[200], buffile[200];
    char *table_dir = NULL;
    sect_1_t s1;
    bufr_t bufr_msg;    /* structure holding encoded bufr message */

    /* initialize variables */

    memset (buffile, 0, sizeof (buffile));
    memset (&bufr_msg, 0, sizeof (bufr_t));
    memset (&s1, 0, sizeof (sect_1_t));

    /* check command line parameter */

    while (argc > 1 && *argv[1] == '-')
    {
        if (*(argv[1] + 1) == 'd')
        {
            if (argc < 2)
            {
                fprintf (stderr, "Missing parameter for -d\n\n%s", usage);
                exit (EXIT_FAILURE);
            }
            table_dir = argv[2];
            argc--;
            argv++;
        }
        else if (*(argv[1] + 1) == 'k')
        {
            kml = 1;
        }
        else if (*(argv[1] + 1) == 't')
        {
	  kml = 2;
        }
        else if (*(argv[1] + 1) != '\0')
        {
            fprintf (stderr, "Invalid parameter %s\n\n%s", argv[1], usage);
            exit (EXIT_FAILURE);
        } else {
	    strcpy (buffile, argv[1]);
	}
        argc--;
        argv++;
    }

    if ((kml == 2) && (argc == 2)) {
      strcpy (buffile, argv[1]);
      kml = 0;
      write_png(NULL, buffile);
      exit (EXIT_SUCCESS);
    }
 
    /* Get input- and output-filenames from the command-line */

    if (argc < 3 && strcmp(buffile,"-"))
    {
        fprintf (stderr, "%s", usage);
        exit (EXIT_FAILURE);
    }

    if (strcmp(buffile,"-")) {
      strcpy (buffile, argv[1]);
      strcpy (destfile, argv[2]);
    } else {
      strcpy (destfile, argv[1]);
    }

    /* read source-file. Therefore allocate memory to hold the complete
       BUFR-message */

    if (!bufr_read_file2 (&bufr_msg, buffile)) {
        bufr_free_data (&bufr_msg);
        exit (EXIT_FAILURE);
    }

    /* decode section 1 */

    if (!bufr_decode_sections01 (&s1, &bufr_msg)) {
        bufr_free_data (&bufr_msg);
        exit (EXIT_FAILURE);
    }

    /* Write section 1 to stderr */

    if (!bufr_header_to_file (&s1, NULL)) {
        bufr_free_data (&bufr_msg);
        exit (EXIT_FAILURE);
    }

    /* read descriptor tables */

    if (read_tables (table_dir, s1.vmtab, s1.vltab, s1.subcent, 
                     s1.gencent) < 0) {
        bufr_free_data (&bufr_msg);
        free_descs();
        exit (EXIT_FAILURE);
    }

    /* decode data descriptor- and data-section now */

    if (!bufr_to_data (destfile, &bufr_msg)) {
        fprintf (stderr, "unable to decode BUFR-message !\n");
        bufr_free_data (&bufr_msg);
        free_descs();
        exit (EXIT_FAILURE);
    }

    {
        int i;
        for (i = 0; i < 6; i++) {
            fprintf (stderr, "section %d length = %d\n", i, bufr_msg.secl[i]);
        }
    }

    zoom(&b);
    zoom(&b);
    write_png(&b, destfile);
    
    bufr_free_data (&bufr_msg);
    free_descs();
    exit (EXIT_SUCCESS);
}

/* end of file */

