#include <iostream>
#include <vector>
#include <string>
#include <exception>

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>

int main(int c, char**v)
{
  try {
    namespace po = boost::program_options;

    int debug;

    po::options_description desc("Options");
    desc.add_options()
      ("output,o", "output flag [required]")
      ("quote,q", "quote flag")
      ("debug,d", po::value< int >(&debug)->default_value(0), "debug level [0|1|2]")
      ;
    po::options_description hidden("hidden optionis");
    hidden.add_options()
      ("input", po::value< std::vector< std::string > >(), "input file [at least one required]")
      ;

    po::positional_options_description positional;
    positional.add("input", -1);

    po::options_description visible("Allowed Options");
    visible.add(desc);

    po::options_description full("Full Options");
    full.add(desc).add(hidden);

    po::variables_map vm;
    po::store(po::command_line_parser(c, v).options(full).positional(positional).run(), vm);
    po::notify(vm);    

    bool error=false;
    if ( !vm.count("output") ) {
      std::cerr << "*** you must specify -o option\n\n";
      error = true;
    }
    if ( !vm.count("input") ) {
      std::cerr << "*** you must specify at least 1 input parameter\n\n";
      error = true;
    }
    if ( debug < 0 || debug > 2 ) {
      std::cerr << "*** debug level must be 0, 1 or 2\n\n";
      error = true;
    }
    
    if ( error ) {
      std::cerr << visible << "\n";
      return 1;
    }

    bool output = vm.count("output");
    bool quote  = vm.count("quote");

    if ( output ) {
      std::cout << "[オプション情報]\n";
      std::cout << "o(output) : " << (output ? "ON" : "OFF") << "\n";
      std::cout << "q(quote)  : " << (quote  ? "ON" : "OFF") << "\n";
      std::cout << "d(debug)  : " << debug << "\n\n";

      std::cout << "[パラメタ情報]\n";
      const std::vector<std::string>& input = vm["input"].as< std::vector<std::string> >();
      std::cout << "指定数 : " << input.size() << "\n";
      for ( int i = 0; i < input.size(); ++i )
        std::cout << i+1 << " : " << (quote?"\"":"") << input[i] << (quote?"\"":"") << "\n";
    }

    return 0;
  } catch (const std::exception& e) {
    std::cerr << e.what() << "\n";
    return -1;
  }
}
