#include <iostream>
#include <fstream>

#include <TestReporterStdout.h>
#include <XMLTestReporter.h>

using namespace std;
using namespace UnitTest;
using boost::shared_ptr;
namespace po = boost::program_options;

static bool ConvertString( const std::wstring& input, shared_ptr<char>& output )
{
    output = shared_ptr<char>( new char[ input.size() * 3 + 1 ] );
    size_t len = 0;
    errno_t rv = wcstombs_s( &len, output.get(), input.size() * 3 + 1, input.c_str(), input.size() + 1 );
    return 0 == rv;
}

int _tmain( int argc, TCHAR** argv )
{
    ::setlocale(LC_ALL, "korean");

    wstring out;
    boost::shared_ptr<char>    suitename;
    boost::shared_ptr<char>    testname;

    try
    {
        po::options_description desc("Allowed options" );
        po::positional_options_description p;
        p.add("suite", -1);

        desc.add_options()
            ("help",                                     "produce help message")
            ("output,o", po::wvalue<wstring>(&out),      "test-report output path")
            ("suite,s",      po::wvalue<wstring>(),          "test-suite to run")
            ("testcase,t",   po::wvalue<wstring>(),          "test-case to run")
            ;

        po::variables_map vm;
        po::store(
                po::wcommand_line_parser( argc, argv ).options( desc ).positional(p).run(),
                vm
                );
        po::notify(vm);

        if (vm.count("help"))
        {
            cout << desc << endl;
            return 1;
        }

        if( vm.count("suite") )       ConvertString( vm["suite"].as<wstring>(), suitename );
        if( vm.count("testcase") )    ConvertString( vm["testcase"].as<wstring>(), testname );          
    }
    catch( std::exception& e )
    {
        cout << "Error: " << e.what() << endl;
        return 1;
    }
    catch( ... )
    {
        cout << "Error: Unknown error" << endl;
        return 1;
    }  

    boost::shared_ptr<UnitTest::TestReporter> tr;
    boost::shared_ptr<ofstream> os;

    if( out.size() < 5 || out.substr( out.size() - 4, wstring::npos ) != _T(".xml") )
    {
        tr = boost::shared_ptr<UnitTest::TestReporter>( new UnitTest::TestReporterStdout() );
    }
    else
    {
        os = boost::shared_ptr<ofstream>( new ofstream( out.c_str(), ios_base::trunc ) );
        tr = boost::shared_ptr<UnitTest::TestReporter>( new UnitTest::XmlTestReporter( *os.get() ) );
    }

    return UnitTest::RunAllTests( *tr.get(), UnitTest::Test::GetTestList(), suitename.get(), testname.get() );
}