#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "inputfile.h"
#include "manglefn.h"
#include "rwbinpoly.h"

typedef struct
{
  int np, pixel, id;
  long double weight;
} polygon_header;

/* global pixelization variables */
extern int res_max;
extern char scheme;
extern int pixelized;
extern int snapped;
extern int balkanized;

/* initial angular tolerance within which to merge multiple intersections */
extern long double mtol;

/* suppress error messages from garea */
extern int verb;


int process_next_entry_binary(format *fmt, inputfile *thisfile, polygon **poly)
{
  format in_fmt;
  int ird;
  char *line_rest, *word;
  polygon_header ph;

  if (fmt->id == 0)
    {
      int npolyw, this_pixel, this_snapped, this_balkanized, res_max_temp;
      char scheme_temp;

      // No header has been read. Read it.

      fmt->id = 1;

      fread(&npolyw, sizeof(int), 1, thisfile->file);
      fread(&this_pixel, sizeof(int), 1, thisfile->file);
      fread(&res_max_temp, sizeof(int), 1, thisfile->file);
      fread(&scheme_temp, sizeof(char), 1, thisfile->file);
      fread(&this_snapped, sizeof(int), 1, thisfile->file);
      fread(&this_balkanized, sizeof(int), 1, thisfile->file);

      if (this_pixel) 
       {
         if (pixelized > 0) {
           if(scheme_temp!=scheme || res_max!=res_max_temp){
              fprintf(stderr, " Pixelization %d%c incompatible with pixelization %d%c of previous file.  Pixelize files to be combined later using the same resolution and scheme.\n", res_max_temp, scheme_temp,res_max,scheme);
              return(-1);
           }
           if(res_max==-1 || res_max_temp==-1){
              fprintf(stderr, " Files pixelized adaptively cannot be combined later.  To use the adaptive pixelization feature, combine files before pixelization.\n");
              return(-1);
           }
         } else {
           res_max = res_max_temp;
           scheme = scheme_temp;
         }
         fprintf(stderr, "input is pixelized (%d,%c)\n", res_max_temp, scheme_temp);
         pixelized++;
       }
      if (this_snapped)
       {
        fprintf(stderr, "input snapped\n");
        snapped++;
       }
      if (this_balkanized)
       {
        fprintf(stderr, "input balkanized\n");
        balkanized++;
       }
      if (pixelized > 0)
        {
        }

      fmt->nweights = npolyw;

    }

  *poly = 0;

  /* store original contents of fmt */
  copy_format(fmt, &in_fmt);

  if (feof(thisfile->file))
    return 0;

  if (fread(&ph, sizeof(polygon_header), 1, thisfile->file) == 0)
    return 0;

  if (feof(thisfile->file))
    return 0;

  *poly = new_poly(ph.np);

  (*poly)->np = ph.np;
  (*poly)->pixel = ph.pixel;
  (*poly)->id = ph.id;
  (*poly)->weight = ph.weight;
  if (fread((*poly)->rp, sizeof(vec), ph.np, thisfile->file) != ph.np)
    return -1;

  if (fread((*poly)->cm, sizeof(long double), ph.np, thisfile->file) != ph.np)
    return -1;

  return 1;
}

int wr_bin_poly(char *filename, format *fmt, int npolys, polygon *polys[/*npolys*/], int npolyw)
{
    int ier, ip, ipoly, nbadarea, npoly;
    long double area, tol;
    FILE *file;
    polygon_header ph;

    /* open filename for writing */
    if (!filename || strcmp(filename, "-") == 0) {
      file = stdout;
    } else {
      file = fopen(filename, "w");
      if (!file) {
        fprintf(stderr, "wr_poly: cannot open %s for writing\n", filename);
        return(-1);
      }
    }


    fwrite(&npolyw, sizeof(int), 1, file);
    fwrite(&pixelized, sizeof(int), 1, file);
    fwrite(&res_max, sizeof(int), 1, file);
    fwrite(&scheme, sizeof(char), 1, file);
    fwrite(&snapped, sizeof(int), 1, file);
    fwrite(&balkanized, sizeof(int), 1, file);

    npoly = 0;
    nbadarea = 0;

    for (ipoly = 0; ipoly < npolys; ipoly++)
      {

        if (!polys[ipoly])
          continue;

        /* area of polygon */
        tol = mtol;
        ier = garea(polys[ipoly], &tol, verb, &area);
        if (ier == -1) return(-1);
        if (ier) {
          fprintf(stderr, "wr_poly: area of polygon %d is incorrect\n", polys[ipoly]->id);
          nbadarea++;
        }


        ph.np = polys[ipoly]->np;
        ph.id = polys[ipoly]->id;
        ph.pixel = polys[ipoly]->pixel;
        ph.weight = polys[ipoly]->weight;
        fwrite(&ph, sizeof(ph), 1, file);
        fwrite(polys[ipoly]->rp, sizeof(vec), ph.np, file);
        fwrite(polys[ipoly]->cm, sizeof(long double), ph.np, file);
      }
    npoly = npolys;

  /* warn about polygons with incorrect area */
  if (nbadarea > 0) {
    msg("%d polygons have incorrect area, but kept\n", nbadarea);
  }

  /* advise */
  msg("%d polygons written to %s\n",
    npoly, (file == stdout)? "output": filename);

  /* close file */
  if (file != stdout) fclose(file);

  return(npoly);
}
