//============================================================================
//
// This file is part of the 'reorientmeshfaces' project.
//
// This software is covered by the following BSD license, except for portions
// derived from other works which are covered by their respective licenses.
// For full licensing information including reproduction of these external
// licenses, see the file LICENSE.txt provided in the documentation.
//
// Copyright (c) 2015, Evangelos Kalogerakis, UMass Amherst
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holders nor the names of contributors
// to this software may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//============================================================================


#include "helper.h"
#include "Mesh.h"

int main(int argc, char *argv[]) {
#if defined(_MSC_VER) && defined(_DEBUG)
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

	srand( (unsigned)time( NULL ) );

	///////////////// INITIALIZATION /////////////////////
	MeshFeatureExporterOptions options;
  options.add_faces = false;
  options.subdivide_mesh = false;
  options.do_nothing = false;
	clock_t start = clock();	

	// initialize options
	strcpy(options.inputPath, "./");
  strcpy(options.outputExtension, "off");
	options.numPointSamples = POINT_SAMPLES;

	// rewrite options based on command options
  if (argc != 2 && argc != 3 && argc != 4 && argc != 5)
	{
    std::cout << "Usage: MeshReorient <execution_mode> input_path_or_file [output_path_or_file] [output_extension_for_conversion]" << std::endl;    
    std::cout << "execution mode: -n  (don't do any mesh processing, useful only for conversion)" << std::endl;
    std::cout << "execution mode: -pr  (re-orient mesh faces) [recommended option[" << std::endl;
    std::cout << "execution mode: -prn (re-orient mesh faces without creating any double-sided faces in dubious visibility cases)" << std::endl;
    std::cout << "execution mode: -prns (re-orient mesh faces, also use planar subdivision)" << std::endl;
    std::cout << "Example: MeshReorient -pr my_input_folder/ my_output_folder/  off" << std::endl;
    std::cout << "The input folder must have a 'meshlist.txt' file that includes all mesh filenames to be processed (each line has a filename)" << std::endl;
    std::cout << "see meshlist.txt for an example in the source code directory" << std::endl;
		return 0;
	}

  if (strcmp(argv[1], "-n") == 0)
  {
    options.do_nothing = true;
  }
	else if (strcmp(argv[1], "-pr") == 0)  // if visibility is dubious, this will create double-sided faces
	{
    options.add_faces = true;
	} 
  else if (strcmp(argv[1], "-prn") == 0)  // if visibility is dubious, this will avoid creating double-sided faces 
  {
    options.add_faces = false;
  }
  else if (strcmp(argv[1], "-prns") == 0)
  {
    options.add_faces = false;
    options.subdivide_mesh = true;
  }
	else
	{
    std::cout << "Usage: MeshReorient <execution_mode> input_path_or_file [output_path_or_file] [output_extension_for_conversion]" << std::endl;
    std::cout << "execution mode: -n  (don't do any mesh processing, useful only for conversion)" << std::endl;
    std::cout << "execution mode: -pr  (re-orient mesh faces) [recommended option[" << std::endl;
    std::cout << "execution mode: -prn (re-orient mesh faces without creating any double-sided faces in dubious visibility cases)" << std::endl;
    std::cout << "execution mode: -prns (re-orient mesh faces, also use planar subdivision)" << std::endl;
    std::cout << "Example: MeshReorient -pr my_input_folder/ my_output_folder/  off" << std::endl;
    std::cout << "The input folder must have a 'meshlist.txt' file that includes all mesh filenames to be processed (each line has a filename)" << std::endl;
    std::cout << "see meshlist.txt for an example in the source code directory" << std::endl;
    return 0;
	}

	if ( argc >= 3 )
	{
		strcpy(options.inputPath, argv[2]);
	}
  if (argc >= 4)
  {
    strcpy(options.outputPath, argv[3]);
  }
  else
  {
    strcpy(options.outputPath, options.inputPath);
  }
  if (argc == 5)
  {
    strcpy(options.outputExtension, argv[4]);
  }


  Mesh m(options.inputPath, options.add_faces, options.do_nothing);
  if (m.valid())
  {
    if (options.subdivide_mesh)
      while (m.mesh->faces.size() < 50000)
        subdiv(m.mesh, SUBDIV_PLANAR);
    mkdir("out");
    m.write("out/" + string(options.outputPath) );
    return 0;
  }
  else
  {
    strcat(options.inputPath, "/");
    strcat(options.outputPath, "/");
    if (argc < 4)
      strcat(options.outputPath, "out/");
    mkdir(options.outputPath);

    char meshFileListName[FILE_STRING_SIZE];
    strcpy(meshFileListName, options.inputPath);
    strcat(meshFileListName, MESHFILELIST);
    ifstream meshFileListFile(meshFileListName);

    if (!meshFileListFile.good())
    {
      std::cerr << "You specified paths as input/output. Input path (directory) should have a file " << meshFileListName << " listing all input meshes (one per line)" << std::endl;
      return -1;
    }

    while (meshFileListFile.good())
    {
      char inputFileName[FILE_STRING_SIZE];
      meshFileListFile.getline(inputFileName, FILE_STRING_SIZE);
      if (isemptychar(inputFileName) || !meshFileListFile.good())
        break;
      strcpy(options.currentObjFilename, options.inputPath);
      strcat(options.currentObjFilename, inputFileName);

      Mesh m(options.currentObjFilename, options.add_faces, options.do_nothing);
      if (options.subdivide_mesh)
        while (m.mesh->faces.size() < 50000)
          subdiv(m.mesh, SUBDIV_PLANAR);
      string output_filename = string(options.outputPath) + inputFileName;
      if (argc == 5)
      {
        output_filename[output_filename.length() - 1] = options.outputExtension[2];
        output_filename[output_filename.length() - 2] = options.outputExtension[1];
        output_filename[output_filename.length() - 3] = options.outputExtension[0];
      }

      m.write(output_filename);
    }
    meshFileListFile.close();

  }

 

}