/////////////////////////////////////////////////////////////
//                                                         //
// Copyright (c) 2007-2014 by The University of Queensland //
// Centre for Geoscience Computing                         //
// http://earth.uq.edu.au/centre-geoscience-computing      //
//                                                         //
// Primary Business: Brisbane, Queensland, Australia       //
// Licensed under the Open Software License version 3.0    //
// http://www.opensource.org/licenses/osl-3.0.php          //
//                                                         //
/////////////////////////////////////////////////////////////

/*!
  \file main.cc
  $Revision:$
  $Date:$
*/

#include "geometry/Sphere.h"
#include "geometry/Line2D.h"
#include "geometry/LineSegment2D.h"
#include "util/vector3.h"
#include "MNTable2D.h"
#include "MNTable3D.h"
#include "InsertGenerator2D.h"
#include "InsertGenerator3D.h"
#include "HexAggregateInsertGenerator2D.h"
#include "BoxWithLines2D.h"
#include "BoxWithPlanes3D.h"

// --- IO includes ---
#include <iostream>

using std::cout;
using std::cout;
using std::endl;

// -- System includes --
#include <cstdlib>
#include <sys/time.h>
using std::atoi;
using std::atof;

int main(int argc, char** argv)
{
  int ret=0;
  double size=atof(argv[1]);
  int ntry=atoi(argv[2]);
  double rmin=atof(argv[3]);
  int outputstyle=atoi(argv[4]);
  int dim=atoi(argv[5]);
  double vol;

  // seed RNG
  struct timeval tv;
  gettimeofday(&tv,NULL);
  int random_seed=tv.tv_usec;
  srand(random_seed);

  if(dim==2){
    double ratio=atof(argv[6]);
    double xsize=ratio*size;
    double ysize=size;
    MNTable2D T(Vector3(0.0,0.0,0.0),Vector3(xsize,ysize,0.0),2.5,1);
    Vector3 min=Vector3(0.0,0.0,0.0); 
    Vector3 max=Vector3(xsize,ysize,0.0);
    
    MNTable2D::SetOutputStyle(outputstyle);

    InsertGenerator2D *G=new InsertGenerator2D(rmin,1.0,ntry,10000,1e-7);
    BoxWithLines2D Box(Vector3(0.0,0.0,0.0),Vector3(xsize,ysize,0.0));
    Line2D bottom_line(Vector3(xsize,0.0,0.0),min);
    Line2D top_line(max,Vector3(0.0,ysize,0.0));
    Line2D left_line(Vector3(xsize,0.0,0.0),max);
    Line2D right_line(min,Vector3(0.0,ysize,0.0));

    Box.addLine(top_line);
    Box.addLine(bottom_line);
    Box.addLine(left_line);
    Box.addLine(right_line);

    G->generatePacking(&Box,&T,0,0);
    //T.generateBonds(0,1e-5,0);

    LineSegment2D bottom_left(Vector3(xsize/2,0.0,0.0),min);
    LineSegment2D bottom_right(Vector3(xsize,0.0,0.0),Vector3(xsize/2,0.0,0.0));

    T.tagParticlesAlongLine(left_line,0.5,4,4,0);
    T.tagParticlesAlongLine(right_line,0.5,8,8,0);
    T.tagParticlesAlongLine(bottom_left,0.5,8,8,0);
    T.tagParticlesAlongLine(bottom_right,0.5,4,4,0);

    vol=xsize*ysize;
    double poros=(vol-T.getSumVolume(0))/vol;
    cout << "Porosity:  " << poros << endl;

    cout << T << endl;
    
    delete G;
  } else if(dim==3){ // 3D block 1x2x1
    double rmax=atof(argv[6]);
    Vector3 min=Vector3(0.0,0.0,0.0); 
    Vector3 max=Vector3(size,2.0*size,size);
    MNTable3D T(min,max,2.5*rmax,1);
    MNTable3D::SetOutputStyle(outputstyle);
    InsertGenerator3D G(rmin,rmax,ntry,1000,1e-6);
    BoxWithPlanes3D Box(min,max);
    Box.addPlane(Plane(min,Vector3(1.0,0.0,0.0)));
    Box.addPlane(Plane(min,Vector3(0.0,1.0,0.0)));
    Box.addPlane(Plane(min,Vector3(0.0,0.0,1.0)));
    Box.addPlane(Plane(max,Vector3(-1.0,0.0,0.0)));
    Box.addPlane(Plane(max,Vector3(0.0,-1.0,0.0)));
    Box.addPlane(Plane(max,Vector3(0.0,0.0,-1.0)));
    G.generatePacking(&Box,&T,0);
    T.generateBonds(0,1e-5,0);

    double vol=2.0*size*size*size;
    double poros=(vol-T.getSumVolume(0))/vol;
    cout << "Porosity:  " << poros << endl;
    
    cout << T << endl;
  }
  return ret;
}
