#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <set>
#include "phIO.h"
#include "posixio.h"
#include "phio_posix.h"

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  int commrank,commsize;
  MPI_Comm_rank(MPI_COMM_WORLD,&commrank);
  MPI_Comm_size(MPI_COMM_WORLD,&commsize);
  if( argc != 4 ) {
    if( !commrank )
      fprintf(stderr, "Usage: %s <geombc posix file> <verbosity=0|1|2> <rankoffset>\n",argv[0]);
    MPI_Finalize();
    return 1;
  }
  const char* filename = argv[1];
  const int verbosity = atoi(argv[2]);
  const int rankoffset = atoi(argv[3]);
  const char* phrase = "ilwork";
  const char* type = "integer";
  const char* iotype = "binary";
  int* ilwork = NULL;
  int len = 0;
  int one = 2;


  int phastarank = commrank+1+rankoffset;

  char geomfilename[4096];
  sprintf(geomfilename, "%s/geombc.dat.%d",filename,phastarank);

  phio_fp file;
  posixio_setup(&(file), 'r');
  posix_openfile_single(geomfilename, file);
  phio_readheader(file, phrase, &len, &one, type, iotype);
  ilwork = (int*) malloc(len*sizeof(int));
  phio_readdatablock(file, phrase, ilwork, &len, type, iotype);
  phio_closefile(file);

  // Initialization 
  int itkbeg = 0;
  int m = 0;
  int idl = 0;
  std::set<int> neighbors;

  // Compute summary info first such as number of communication tasks, neighboring parts, onwer parts, etc
  int numtask = ilwork[0];
  int numowner = 0;
  for(int itask=0;itask<numtask;itask++) {
    int iacc   = ilwork [itkbeg + 2];
    int iother = ilwork [itkbeg + 3];
    int numseg = ilwork [itkbeg + 4];
    if(iacc == 1) numowner++;
    neighbors.insert(iother);
    itkbeg = itkbeg + 4 + 2*numseg;
  }
  if( !commrank )
      printf("rank peers tasks owned notowned\n");
  MPI_Barrier(MPI_COMM_WORLD);
  for(int i=0; i<commsize; i++) {
    if( i == commrank )
      printf("%d %d %d %d %d\n",
          phastarank,neighbors.size(),numtask,numowner,numtask-numowner);
    MPI_Barrier(MPI_COMM_WORLD);
  }

  if( verbosity > 0 ) {
    // Print now communication info
    printf("\n");
    printf("Communication info for this part:\n");
    itkbeg = 0;
    for(int itask=0;itask<numtask;itask++) {
      int itag   = ilwork [itkbeg + 1];
      int iacc   = ilwork [itkbeg + 2];
      int iother = ilwork [itkbeg + 3];
      int numseg = ilwork [itkbeg + 4];
      int isgbeg = ilwork [itkbeg + 5];

      // Toal number of nodes involved in this communication (lfront), including all segments
      int lfront = 0;
      for(int is=1;is<=numseg;is++) {
        int lenseg = ilwork [itkbeg + 4 + 2*is];
        lfront = lfront + lenseg;
      }
      printf("Communication %d:\ttag %d\townership %d\trank %d\tnumseg %d\tnumvtx %d\n",itask,itag,iacc,iother,numseg,lfront);
      itkbeg = itkbeg + 4 + 2*numseg;
    }
    printf("\n");
  }

  // Print now the raw ilwork array
  if( verbosity > 1 ) {
    printf("ilwork array:\n");
    for(int i=0;i<len;i++) {
      printf("%d\n",ilwork[i]);
    }
  }

  free(ilwork);

  MPI_Finalize();
  return 0;
}
