/*=============================================================================
    Boost.Wave: A Standard compliant C++ preprocessor library
    http://www.boost.org/

    Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
    Software License, Version 1.0. (See accompanying file
    LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

// disable stupid compiler warnings
#include <boost/config/warning_disable.hpp>

// system headers
#include <string>
#include <iostream>
#include <vector>

// include boost
#include <boost/config.hpp>
#include <boost/wave.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

//  test application related headers
#include "cmd_line_utils.hpp"
#include "testwave_app.hpp"

namespace po = boost::program_options;
namespace fs = boost::filesystem;

///////////////////////////////////////////////////////////////////////////////
//
//  The debuglevel command line parameter is used to control the amount of text 
//  printed by the testwave application. 
//
//  level 0:    prints nothing except serious failures preventing the testwave
//              executable from running, the return value of the executable is 
//              equal to the number of failed tests
//  level 1:    prints a short summary only
//  level 2:    prints the names of the failed tests only
//  level 3:    prints the expected and real result for failed tests
//  level 4:    prints the outcome of every test
//  level 5:    prints the real result even for succeeded tests
//  level 6:    prints the real hooks information recorded, even for succeeded 
//              tests
//
//  level 9:    prints information about almost everything
//
//  The default debug level is 1.
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
int 
main(int argc, char *argv[])
{
    int error_count = 0;
    int config_file_error_count = 0;
    try {
    // analyze the command line options and arguments
        po::options_description desc_cmdline ("Options allowed on the command line");
        desc_cmdline.add_options()
            ("help,h", "print out program usage (this message)")
            ("version,v", "print the version number")
            ("copyright,c", "print out the copyright statement")
            ("config-file", po::value<std::vector<std::string> >()->composing(), 
                "specify a config file (alternatively: @arg)")
            ("hooks", po::value<bool>()->default_value(true), 
                "test preprocessing hooks")
            ("debug,d", po::value<int>(), "set the debug level (0...9)")
        ;

    // Hidden options, will be used in in config file analysis to allow to
    // recognize positional arguments, will not be shown to the user.
        po::options_description desc_hidden("Hidden options");
        desc_hidden.add_options()
            ("input", po::value<std::vector<std::string> >()->composing(), 
                "inputfile")
        ;        

    // this is the test application object
        po::variables_map vm;
        testwave_app app(vm);

    // all command line and config file options
        po::options_description cmdline_options;
        cmdline_options.add(desc_cmdline).add(app.common_options());

    // parse command line
        // (the (int) cast is to make the True64 compiler happy)
        using namespace boost::program_options::command_line_style;
        po::parsed_options opts(po::parse_command_line(argc, argv, 
            cmdline_options, (int)unix_style, cmd_line_utils::at_option_parser));
        
        po::store(opts, vm);
        po::notify(vm);

    // ... act as required 
        if (vm.count("help")) {
            po::options_description desc_help (
                "Usage: testwave [options] [@config-file(s)] file(s)");
            desc_help.add(desc_cmdline).add(app.common_options());
            std::cout << desc_help << std::endl;
            return 0;
        }
        
    // debug flag
        if (vm.count("debug")) {
            int debug_level = vm["debug"].as<int>();
            if (debug_level < 0 || debug_level > 9) {
                std::cerr 
                    << "testwave: please use an integer in the range [0..9] "
                    << "as the parameter to the debug option!" 
                    << std::endl;
            }
            else {
                app.set_debuglevel(debug_level);
            }
        }
        
        if (vm.count("version")) {
            return app.print_version();
        }

        if (vm.count("copyright")) {
            return app.print_copyright();
        }
        
    // If there is specified at least one config file, parse it and add the 
    // options to the main variables_map
    // Each of the config files is parsed into a separate variables_map to 
    // allow correct paths handling.
        int input_count = 0;
        if (vm.count("config-file")) {
            std::vector<std::string> const &cfg_files = 
                vm["config-file"].as<std::vector<std::string> >();

            if (9 == app.get_debuglevel()) {
                std::cerr << "found " << (unsigned)cfg_files.size() 
                          << " config-file arguments" << std::endl;
            }
            
            std::vector<std::string>::const_iterator end = cfg_files.end();
            for (std::vector<std::string>::const_iterator cit = cfg_files.begin(); 
                 cit != end; ++cit)
            {
                if (9 == app.get_debuglevel()) {
                    std::cerr << "reading config_file: " << *cit << std::endl;
                }
                
            // parse a single config file and store the results, config files
            // may only contain --input and positional arguments 
                po::variables_map cvm;
                if (!cmd_line_utils::read_config_file(app.get_debuglevel(), 
                    *cit, desc_hidden, cvm)) 
                {
                    if (9 == app.get_debuglevel()) {
                        std::cerr << "failed to read config_file: " << *cit 
                                  << std::endl;
                    }
                    ++config_file_error_count;
                }
                
                if (9 == app.get_debuglevel()) {
                    std::cerr << "succeeded to read config_file: " << *cit 
                              << std::endl;
                }
                
            // correct the paths parsed into this variables_map
                if (cvm.count("input")) {
                    std::vector<std::string> const &infiles = 
                        cvm["input"].as<std::vector<std::string> >();

                    if (9 == app.get_debuglevel()) {
                        std::cerr << "found " << (unsigned)infiles.size() 
                                  << " entries" << std::endl;
                    }

                    std::vector<std::string>::const_iterator iend = infiles.end();
                    for (std::vector<std::string>::const_iterator iit = infiles.begin(); 
                         iit != iend; ++iit)
                    {
                    // correct the file name (pre-pend the config file path)
                        fs::path cfgpath = fs::complete(
                            boost::wave::util::create_path(*cit), 
                            boost::wave::util::current_path());
                        fs::path filepath = 
                            boost::wave::util::branch_path(cfgpath) / 
                                boost::wave::util::create_path(*iit);

                        if (9 == app.get_debuglevel()) {
                            std::cerr << std::string(79, '-') << std::endl;
                            std::cerr << "executing test: " 
                                      << boost::wave::util::native_file_string(filepath)
                                      << std::endl;
                        }

                    // execute this unit test case
                        if (!app.test_a_file(
                              boost::wave::util::native_file_string(filepath))) 
                        {
                            if (9 == app.get_debuglevel()) {
                                std::cerr << "failed to execute test: " 
                                          << boost::wave::util::native_file_string(filepath)
                                          << std::endl;
                            }
                            ++error_count;
                        }
                        else if (9 == app.get_debuglevel()) {
                            std::cerr << "succeeded to execute test: " 
                                      << boost::wave::util::native_file_string(filepath)
                                      << std::endl;
                        }
                        ++input_count;

                        if (9 == app.get_debuglevel()) {
                            std::cerr << std::string(79, '-') << std::endl;
                        }
                    }
                }
                else if (9 == app.get_debuglevel()) {
                    std::cerr << "no entries found" << std::endl;
                }
            }
        }

    // extract the arguments from the parsed command line
        std::vector<po::option> arguments;
        std::remove_copy_if(opts.options.begin(), opts.options.end(), 
            std::back_inserter(arguments), cmd_line_utils::is_argument());

        if (9 == app.get_debuglevel()) {
            std::cerr << "found " << (unsigned)arguments.size() 
                      << " arguments" << std::endl;
        }
        
    // iterate over remaining arguments
        std::vector<po::option>::const_iterator arg_end = arguments.end();
        for (std::vector<po::option>::const_iterator arg = arguments.begin();
             arg != arg_end; ++arg)
        {
            fs::path filepath(boost::wave::util::create_path((*arg).value[0]));

            if (9 == app.get_debuglevel()) {
                std::cerr << std::string(79, '-') << std::endl;
                std::cerr << "executing test: " 
                          << boost::wave::util::native_file_string(filepath)
                          << std::endl;
            }

            if (!app.test_a_file(boost::wave::util::native_file_string(filepath))) 
            {
                if (9 == app.get_debuglevel()) {
                    std::cerr << "failed to execute test: " 
                              << boost::wave::util::native_file_string(filepath)
                              << std::endl;
                }
                ++error_count;
            }
            else if (9 == app.get_debuglevel()) {
                std::cerr << "succeeded to execute test: " 
                          << boost::wave::util::native_file_string(filepath)
                          << std::endl;
            }

            if (9 == app.get_debuglevel()) {
                std::cerr << std::string(79, '-') << std::endl;
            }
            ++input_count;
        }

    // print a message if no input is given
        if (0 == input_count) {
            std::cerr 
                << "testwave: no input file specified, " 
                << "try --help to get a hint." 
                << std::endl;
            return (std::numeric_limits<int>::max)() - 3;
        }
        else if (app.get_debuglevel() > 0) {
            std::cout 
                << "testwave: " << input_count-error_count 
                << " of " << input_count << " test(s) succeeded";
            if (0 != error_count) {
                std::cout 
                    << " (" << error_count << " test(s) failed)";
            }
            std::cout << "." << std::endl;
        }
    }
    catch (std::exception const& e) {
        std::cerr << "testwave: exception caught: " << e.what() << std::endl;
        return (std::numeric_limits<int>::max)() - 1;
    }
    catch (...) {
        std::cerr << "testwave: unexpected exception caught." << std::endl;
        return (std::numeric_limits<int>::max)() - 2;
    }

    return error_count + config_file_error_count;
}
