#ifndef COVERAGE_TEST_OBSERVER_INCLUDED
#define COVERAGE_TEST_OBSERVER_INCLUDED

#include <boost/test/framework.hpp>
#include <boost/test/tree/observer.hpp>
#include <boost/test/included/unit_test.hpp>

#ifdef __COVERAGESCANNER__

class BoostTestObserver
    : public boost::unit_test_framework::test_observer
{
public:
    BoostTestObserver(const char* moduleName)
        : test_observer()
        , m_testSuiteName(moduleName)
        , m_isAnyTestcaseOpen(false)
    {}

    ~BoostTestObserver()
    {
        if (m_isAnyTestcaseOpen)
            close_current_testcase();
    }

///////////////////////////////////////////////////////////////////////////////
// test suite related events:


    virtual int priority()
    {
        return 1;
    }

    virtual void test_finish()
    {
        if (m_isAnyTestcaseOpen) {
            close_current_testcase();
        }
    }

    virtual void test_aborted()
    {
        if (m_isAnyTestcaseOpen) {
            close_current_testcase();
        }
    }

    const char* get_testsuite_name()
    {
        return m_testSuiteName.data();
    }

    // called in the very beginning of the test suite:
    virtual void test_start(
        boost::unit_test_framework::counter_t  NumberOfTestCases)
    {
        m_currentTestNumber = -1;
        m_numberOfTestCases = NumberOfTestCases;
        __coveragescanner_install(m_testSuiteName.c_str());
    }


///////////////////////////////////////////////////////////////////////////////
// test case related events:


    // called before each testcase's start   
    virtual void test_unit_start(
        boost::unit_test_framework::test_unit const &unit)
    {
        // skip any calls which may being triggered by the 'TestWrap' fixture
        if(unit.full_name().find('/') == -1) {
            return;
        }

        if (++m_currentTestNumber)
            close_current_testcase();

        m_currentCaseHasFailed = false;
        __coveragescanner_clear();
        m_currentTestName.assign( unit.full_name().c_str());
        __coveragescanner_testname(m_currentTestName.c_str());
        m_isAnyTestcaseOpen = true;
    }

    // should be called after each testcase has finished... 
    // but which definitveley, for unknown reason is NOT
    virtual void test_unit_finish(
        boost::unit_test_framework::test_unit const &unit,
        unsigned number)
    {
        close_current_testcase();
    }

    // workaround for missing 'test_unit_finish' event being not triggered:
    void close_current_testcase()
    {
        if (m_isAnyTestcaseOpen) {
            __coveragescanner_teststate(m_currentCaseHasFailed
                                       ? "FAILED"
                                       : "PASSED");
            __coveragescanner_save();
            m_currentTestName.append("_invalid");
            m_isAnyTestcaseOpen = false;
        }
    }

    // called once on each FAILED or PASSED result
    virtual void assertion_result(boost::unit_test::assertion_result result)
    {
        if (result == boost::unit_test::AR_FAILED)
            m_currentCaseHasFailed = true;
    }

protected// Depricated boost event:
    virtual void assertion_result(bool result)
    {
        if (!result) m_currentCaseHasFailed = true;
    }

///////////////////////////////////////////////////////////////////////////////
//  member variables:


    std::string m_testSuiteName;
    std::string m_currentTestName;
    int         m_currentTestNumber;
    int         m_numberOfTestCases;
    bool        m_verboseLogging;
    bool        m_currentCaseHasFailed;
    bool        m_isAnyTestcaseOpen;
};

//////////////////
// boost fixture:
// will be called in the very beginning and in the end of executing test
///////////////////////////////////////////////////////////////////////////////


struct TestWrap
{
    BoostTestObserver observer;

    TestWrap()
    : BoostTestObserver(
        boost::unit_test::framework::master_test_suite().argv[0])
    {
        boost::unit_test::framework::register_observer(observer);
    }

   ~TestWrap()
    {
        observer.close_current_testcase();
        boost::unit_test::framework::deregister_observer(observer);
    }
};

///////////////////////////////////////////////////////////////////////////////

BOOST_GLOBAL_FIXTURE(TestWrap);

  #endif
#endif