/////////////////////////////////////////////////////////////
//                                                         //
// 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          //
//                                                         //
/////////////////////////////////////////////////////////////

#include <boost/version.hpp>
#include <iostream>
#include <sstream>
#include "InsertGenerator3DPy.h"

using namespace boost::python;

    using boost::python::arg;
    void exportAGenerator3D()
    {
      // Disable autogeneration of C++ signatures (Boost 1.34.0 and higher)
      // for Epydoc which stumbles over indentation in the automatically generated strings.
      boost::python::docstring_options no_autogen(true,false);

      class_<AGenerator3D, boost::noncopyable>("AGenerator3D", "Abstract base class for 3D InsertGenerators", no_init);
    }

    void exportInsertGenerator3D()
    {
      // Disable autogeneration of C++ signatures (Boost 1.34.0 and higher)
      // for Epydoc which stumbles over indentation in the automatically generated strings.
      boost::python::docstring_options no_autogen(true,false);

      class_<InsertGenerator3D, bases<AGenerator3D> >(
        "InsertGenerator3D",
        "A particle packing algorithm for filling L{AVolume3D} spaces.",
        init<>()
      )
      .def(init<const InsertGenerator3D &>())
      .def(
        init<double,double,int,int,double>(
          ( arg("minRadius"), arg("maxRadius"), arg("insertFails"), arg("maxIterations"), arg("tolerance") ),
          "Initialises a particle packer in preparation for filling an\n"
          "L{AVolume3D} with particles whose radii are in the specified range.\n"
          "The packing will terminate after the specified number of \n"
          "insertion failures. The iterative solver will compute only the\n"
          "specified maximum number of iterations. Particles are permitted \n"
          "to overlap by the specified tolerance.\n" 
          "@type minRadius: double\n"
          "@kwarg minRadius: the minimum radius of particles to pack\n"
          "@type maxRadius: double\n"
          "@kwarg maxRadius: the maximum radius of particles to pack\n"
          "@type insertFails: int\n"
          "@kwarg insertFails: the number of particle insertion failures before the packer terminates\n"
          "@type maxIterations: int\n"
          "@kwarg maxIterations: the maximum number of iterations of the solver\n"
          "@type tolerance: double\n"
          "@kwarg tolerance: the overlap tolerance permitted\n"
          "@rtype: void\n"
        )
      )
      .def(
	   init<double,double,int,int,double,bool>(
	   ( arg("minRadius"), arg("maxRadius"), arg("insertFails"), arg("maxIterations"), arg("tolerance"),arg("seed") ),
          "@type seed: bool\n"
          "@kwarg seed: randomize the random number generator if True (optional)\n"
        )
      )
      .def(
        "generatePacking",
        &InsertGenerator3D::generatePacking3,
        ( arg("volume"), arg("ntable"), arg("groupID")=0 ),
        "Generates a particle assembly to fill the specified volume.\n"
        "@type volume: L{AVolume3D}\n"
        "@kwarg volume: the volume to fill with particles\n"
        "@type ntable: L{MNTable3D}\n"
        "@kwarg ntable: the neighbours table that particles are inserted into\n"
        "@type groupID: int\n"
        "@kwarg groupID: the group ID assigned to particles (default: 0)\n"
        "@rtype: void\n" 
      )
      .def(
        "generatePacking",
        &InsertGenerator3D::generatePacking4,
        ( arg("volume"), arg("ntable"), arg("groupID")=0, arg("tag") ),
        "@type tag: int\n"
        "@kwarg tag: the tag assigned to the generated particles\n"
        " (optional (default: -1) if not followed by C{ShapeList})\n"
      )
      .def(
        "generatePacking",
        &InsertGenerator3D::generatePacking,
          ( arg("volume"), arg("ntable"), arg("groupID")=0 , arg("tag"), arg("shapeList") ),
          "@type shapeList: L{ShapeList}\n"  
          "@kwarg shapeList: the list of shapes to be inserted (optional)\n"
      )
      .def(
        "generatePackingMaxVolume",
        &InsertGenerator3D::generatePackingMaxVolume,
        ( arg("volume"), arg("ntable"), arg("groupID")=0, arg("tag"), arg("maxVolume") ),
  "Fills the specified L{AVolume3D} with particles until the accumulated particle volume exceeds the specified C{maxVolume}.\n"
        "@type maxVolume: float\n"
        "@kwarg maxVolume: the maximum cumulative volume of the inserted particles\n"
      )
      .def(
	   "setNextTag",
           &InsertGenerator3D::setNextTag,
	   ( arg("tag") ),
	   "Sets tag for the next particles generated\n"
	   "@type tag: int\n"
	   "@kwarg tag: tag to assign the next particles generated by the L{InsertGenerator3D}\n"
       )
      .def(
	"setOldSeeding",
	&InsertGenerator3D::setOldSeeding,
	( arg("old")),
	"Sets seeding behavior to older method.\n"
        "@type old: bool\n"  
        "@kwarg old: toggle between old and new seeding methods.\n"
      )
      .def(self_ns::str(self))
      ;
    }



