// Cutmesh - Copyright (C) 2010-2018 T. Mouton, E. Bechet 
//
// See the LICENSE file for license information and contributions.
// bugs and problems to <thibaud.mouton@gmail.com>.

#include "common.h"
#include <getopt.h>

void options::usage ( const char *program_name )
{
  printf ( "usage: %s [ options ] --basename <basename>\n", program_name );
  printf ( "  Cut a mesh according to levelsets.\n" );
  printf ( "[ --preset ] (type=INTEGER)\n" );
  printf ( "  0 : load a meshfile and a levelset file generated by cadlevelset. The topology is then generated according to initial Brep model. The output is a gmodel .msh file\n" );
  printf ( "  1 : load a gmodel file and a levelset file. Then recut the model. The topology is not cleaned. The output is a gmodel .msh file\n" );
  printf ( "  2 : load a gmodel file and a levelset file. Then recut the model. The topology is cleaned. The output is a gmodel .msh file\n" );
  printf ( "  3 : load a meshfile and a levelset file generated by cadlevelset. Then cut the model. The topology is not cleaned. The output is a gmodel .msh file\n" );
  printf ( "  4 : load a meshfile and a levelset file generated by cadlevelset. Then cut the model. The topology is cleaned. The output is a gmodel .msh file\n" );
#if defined(CUTMESH_ENABLE_IBREP)
  printf ( "  5 : load a iBrep file. Then cut the model. The topology is cleaned. The output is a gmodel .msh file\n" );
#endif
  printf ( "  6 : load a OpenCascade Model. Then build a mesh, compute the levelsets and cut the model. The topology is cleaned. The output is a gmodel .msh file\n" );
  printf ( "  7 : load a fiber surface file. Then build a mesh, compute the levelsets and cut the model. The topology is not cleaned. The output is a gmodel .msh file\n" );
  printf ( "  8 : load a gmodel file and a levelset file containing edges. Then recut the model. The topology is not cleaned. The output is a gmodel .msh file\n" );

  printf ( "[ --basename ] (type=STRING)\n" );
  printf ( "  The name of mesh and levelset files\n" );
  printf ( "[ --dotmin ] (type=DOUBLE)\n" );
  printf ( "  The minimal dotproduct above which two surfaces are considered parallel\n" );
  printf ( "[ --distmax ] (type=DOUBLE)\n" );
  printf ( "  The maximal distance below which two surfaces are considered to be coincident\n" );
  printf ( "[ --max-mesh-size ] (type=INTEGER)\n" );
  printf ( "  The number of octree elements in the largest side\n" );
  printf ( "[ --max-surface-sample ] (type=INTEGER)\n" );
  printf ( "  The number of sample points when generating a surface\n" );
  printf ( "[ --shrink-boundingbox ] (type=DOUBLE)\n" );
  printf ( "  The shrink factor of the bounding box enclosing the surfaces\n" );
  printf ( "[ --max-refine-level ] (type=INTEGER)\n" );
  printf ( "  The max number of refinement levels that will be applied on the initial mesh\n" );
  printf ( "[ --refinement-threshold ] (type=DOUBLE)\n" );
  printf ( "  Given an edge as the chord of a circle of curvature, this parameter is the max percentage of the chord allowed for the sagitta\n" );
  printf ( "[ --debug ] (type=FLAG)\n" );
  printf ( "  Output intermediate files\n" );
  printf ( "[ --version ]\n" );
  printf ( "  Output version information and exit.\n");
}

void options::presets ( int num )
{
  switch ( num )
  {
    case 0:
      /*
      * preset 0 : load a meshfile and a levelset file generated by cadlevelset. The topology is then generated according to initial Brep model.
      * The output is a gmodel .msh file
      */
      read_meshfile = 1;
      read_lsfile = 1;
      read_topo_file = 1;
      brep_topo = 1;
      only_valid_topo = 1;
      write_gmodel = 1;
      break;
    case 1:
      /*
       * preset 1 : load a gmodel file and a levelset file. Then recut the model. The topology is not cleaned. The output is a gmodel .msh file
       */
      load_gmodel_mesh = 1;
      read_lsfile = 1;
      auto_topo = 1;
      recut_enable = 1;
      write_gmodel = 1;
      break;
    case 2:
      /*
       * preset 2 : load a gmodel file and a levelset file. Then recut the model. The topology is cleaned. The output is a gmodel .msh file
       */
      load_gmodel_mesh = 1;
      read_lsfile = 1;
      only_valid_topo = 1;
      auto_topo = 1;
      recut_enable = 1;
      write_gmodel = 1;
      break;
    case 3:
      /*
       * preset 3 : load a meshfile and a levelset file generated by cadlevelset. Then cut the model. The topology is not cleaned. The output is a gmodel .msh file
       */
      read_meshfile = 1;
      read_lsfile = 1;
      auto_topo = 1;
      recut_enable = 0;
      write_gmodel = 1;
      break;
    case 4:
      /*
       * preset 4 : load a meshfile and a levelset file generated by cadlevelset. Then cut the model. The topology is cleaned. The output is a gmodel .msh file
       */
      read_meshfile = 1;
      read_lsfile = 1;
      only_valid_topo = 1;
      auto_topo = 1;
      write_gmodel = 1;
      break;
#if defined(CUTMESH_ENABLE_IBREP)
    case 5:
      /*
      * preset 5 : load a ibrep file. The topology is then generated according to initial iBrep model.
      * The output is a gmodel .msh file
      */
      load_ibrep = 1;
      brep_topo = 1;
      only_valid_topo = 1;
      write_gmodel = 1;
      break;
#endif
    case 6:
      /*
      * preset 6 : load a OpenCascade Model. Then build a mesh, compute the levelsets and cut the model. The topology is cleaned.
      * The output is a gmodel .msh file
      */
      load_gmodel_geometry = 1;
      generate_mesh = 1;
      brep_topo = 1;
      only_valid_topo = 1;
      write_gmodel = 1;
      break;
    case 7:
      /*
      * preset 7 : load a fiber surface file, then build the mesh and refine it according to the curvature. Then cut the model. The topology is not cleaned.
      * The output is a gmodel .msh file
      */
      read_fiber_surface = 1;
      generate_mesh = 1;
      refine_mesh_curvature = 1;
      auto_topo = 1;
      only_valid_topo = 1;
      write_gmodel = 1;
      break;
    case 8:
      /*
       * preset 8 : load a gmodel file and a levelset file containing edges. Then recut the model. The topology is not cleaned. The output is a gmodel .msh file
       */
      load_gmodel_mesh = 1;
      read_lsfile = 1;
      read_edges = 1;
      auto_topo = 1;
      recut_enable = 1;
      write_gmodel = 1;
      break;
    default:
      usage ( "cutmesh" );
      exit ( 0 );
  }
#if 0
  printf ( "####################\n" );
  printf ( "## preset summary ## \n" );
  printf ( "## load_gmodel_mesh --> %d\n", load_gmodel_mesh );
  printf ( "## read_meshfile --> %d\n", read_meshfile );
  printf ( "## read_lsfile --> %d\n", read_lsfile );
  printf ( "## brep_topo --> %d\n", brep_topo );
  printf ( "## only_valid_topo --> %d\n", only_valid_topo );
  printf ( "## auto_topo --> %d\n", auto_topo );
  printf ( "## recut_enable --> %d\n", recut_enable );
  printf ( "## write_gmodel --> %d\n", write_gmodel );
  printf ( "###################\n" );
#endif
}

void options::parse ( int argc, char **argv )
{
  int c;

//     while (1)
//     {
//         static struct option long_options[] =
//         {
// //             /* These options set a flag. */
//             {"debug",   no_argument,       &debug, 1},
//             /* These options don't set a flag.
//                We distinguish them by their indices. */
//             {"preset",     required_argument,       0, 'p'},
//             {"basename",  required_argument,       0, 'b'},
//             {"dotmin",     required_argument,       0, 's'},
//             {"distmin",  required_argument,       0, 'd'},
//             {"version",  no_argument,       0, 'v'},
//             {0, 0, 0, 0}
//         };
//         /* getopt_long stores the option index here. */
//         int option_index = 0;
//
//         c = getopt_long (argc, argv, "", long_options, &option_index);
//
//         /* Detect the end of the options. */
//         if (c == -1)
//             break;
//
//         switch (c)
//         {
//         case 0:
//             /* If this option set a flag, do nothing else now. */
//             if (long_options[option_index].flag != 0)
//                 break;
// //             printf ("option %s", long_options[option_index].name);
// //             if (optarg)
// //               printf (" with arg %s", optarg);
// //             printf ("\n");
// //             break;
// //             printf("--> %s\n", optarg);
//
//         case 'p':
//             presets(atoi(optarg));
//             break;
//         case 'b':
//             sprintf(basename, "%s", optarg);
// //             basename = optarg;
//             break;
//         case 's':
//             mesh_dotmin_merge_surface = atof(optarg);
//             break;
//         case 'd':
//             mesh_distmin_merge_surface = atof(optarg);
//             break;
//  case 'v':
//             printf("cutmesh current version --> %d.%d\n", major_version, minor_version);
//             exit(0);
//         default:
//             usage("cutmesh");
//             exit(0);
//         }
//     }
  while ( 1 )
  {
    static struct option long_options[] =
    {
      {"debug",                no_argument,       0, 0},
      {"preset",               required_argument, 0, 1},
      {"basename",             required_argument, 0, 2},
      {"dotmin",               required_argument, 0, 3},
      {"distmin",              required_argument, 0, 4},
      {"version",              no_argument,       0, 5},
      {"max-mesh-size",        required_argument, 0, 6},
      {"max-surface-sample",   required_argument, 0, 7},
      {"shrink-boundingbox",   required_argument, 0, 8},
      {"max-refine-level",     required_argument, 0, 9},
      {"refinement-threshold", required_argument, 0,10},
      {                     0,                 0, 0, 0}
    };
    /* getopt_long stores the option index here. */
    int option_index = 0;

    c = getopt_long ( argc, argv, "", long_options, &option_index );

    /* Detect the end of the options. */
    if ( c == -1 )
      break;

    switch ( c )
    {
      case 0:
        debug = 1;
        break;
      case 1:
        presets ( atoi ( optarg ) );
        break;
      case 2:
        sprintf ( basename, "%s", optarg );
        break;
      case 3:
        mesh_dotmin_merge_surface = atof ( optarg );
        break;
      case 4:
        mesh_distmin_merge_surface = atof ( optarg );
        break;
      case 5:
        printf ( "cutmesh current version --> %d.%d\n", major_version, minor_version );
        exit ( 0 );
      case 6:
        max_mesh_size = atoi ( optarg );
        break;
      case 7:
        max_surf_sample = atoi ( optarg );
        break;
      case 8:
        enlarge_mesh_factor = atof ( optarg );
        break;
      case 9:
        max_refinement_level = atoi ( optarg );
      case 10:
        refinement_error_threshold = atof ( optarg );

      default:
        usage ( "cutmesh" );
        exit ( 0 );
    }
  }

  if ( basename[0] == '\0' )
  {
    usage ( "cutmesh" );
    exit ( 0 );
  }
}
