#ifdef _MSC_VER
# pragma warning( disable : 4786 )
#endif

#if defined(__unix__) || defined(__linux__)
# include <unistd.h>
#else
  extern "C" int getopt (int argc, char *const *argv, const char *shortopts);
# include "getopt.h"
#endif

#include <akaxiso/akaxiso.h>
#include <akaxiso/schema/schema_xiso.h>
#include <akaxiso/schema/schema.h>

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>

#include "osixaka.h"


void usage() {

  std::cout << "osixaka (" << PACKAGE << "-" << VERSION << ")" << std::endl
	    << " XMLSchema compiler for akaxiso2." << std::endl
	    << " usage  osixaka2 [-p] [-d] [-v] [-h] [-o output directory] [Schema files...]" 
	    << std::endl
	    << "  -p: just parse XMLSchema document." << std::endl
	    << "  -d: dump parsed document." << std::endl
	    << "  -v: verbose mode." << std::endl
	    << "  -h: show this message." << std::endl
	    << "  -o: specify output directory to write generated files." << std::endl;
}


int main(int argc, char* argv[]){

  aka::initialize();
  osixaka::initialize();

  std::ostream &logstm = std::cout;
  std::string outputdir = "./";
  bool parse_only = false;
  bool do_dump = false;
  bool verbose = false;

  char c;
  while ((c = getopt(argc, argv, "pdvo:h")) != -1) {
    switch (c) {
    case 'o': {
      outputdir = optarg;
      if (outputdir.at(outputdir.size()) != '/')
	outputdir += "/";
      break;
    }
    case 'p': {
      do_dump = true;
      parse_only = true;
      break;
    }
    case 'd': {
      do_dump = true;
      break;
    }
    case 'v': {
      verbose = true;
      break;
    }
    case 'h' :{
      usage();
      exit(0);
    }
    default: {
      logstm << "Unknown option." << std::endl;
      exit(1);
    }
    }
  }

  if (optind == argc) {
    logstm << "No document for generation." << std::endl;
    usage();
    exit(1);
  }

  osixaka osx(std::cerr, do_dump, verbose);
  for (int docindex = optind; docindex < argc; ++docindex) {

    if (osx.parse(argv[docindex]) != 0) {
      logstm << "Faild to parse document, " << argv[docindex] << std::endl;
      exit(1);
    }
    if (parse_only)
      continue;

    if (osx.process() != 0) {
      logstm << "Failed to process document, " << argv[docindex] << std::endl;
      exit(1);
    }
  }

  if (parse_only)
    exit(0);

  try {
    osx.akaxisonize();
    osx.generate(outputdir);
  }
  catch (const std::exception &e) {
    logstm << e.what() << std::endl
	   << "Error found.  Generation aborted." << std::endl;
    exit(1);
  }

  logstm << "Generation completed." << std::endl;
    
  // Uninitializers.
  aka::uninitialize();
  return 0;
}
