/*
 * (C) Copyright 2013 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation
 * nor does it submit to any jurisdiction.
 */

#include "Logging.h"

#include <iostream>

#include "eckit/log/Channel.h"

#include "atlas/library/Library.h"
#include "atlas/parallel/omp/omp.h"

//-----------------------------------------------------------------------------------------------------------

namespace atlas {
namespace runtime {
namespace trace {

//-----------------------------------------------------------------------------------------------------------

bool Control::enabled() {
    return atlas_omp_get_thread_num() == 0;
}

class LoggingState {
private:
    std::ostream* channel_;

    LoggingState() { channel_ = &atlas::Library::instance().traceChannel(); }

public:
    static eckit::Channel& empty_channel() {
        static eckit::Channel channel;
        return channel;
    }

    static LoggingState& instance() {
        static LoggingState channel;
        return channel;
    }

    operator std::ostream&() { return *channel_; }
    operator std::ostream*() { return channel_; }

    void set( std::ostream& channel ) { channel_ = &channel; }
    void set( bool state ) {
        if ( state == false ) {
            channel_ = &empty_channel();
        }
    }
};

//-----------------------------------------------------------------------------------------------------------

Logging::Logging( bool state ) : previous_state_( LoggingState::instance() ) {
    LoggingState::instance().set( state );
}

Logging::Logging( std::ostream& channel ) : previous_state_( LoggingState::instance() ) {
    LoggingState::instance().set( channel );
}

Logging::~Logging() {
    LoggingState::instance().set( *previous_state_ );
}

std::ostream& Logging::channel() {
    return LoggingState::instance();
}

bool Logging::enabled() {
    return LoggingState::instance();
}

void Logging::start( const std::string& title ) {
    if ( enabled() ) {
        channel() << title << " ..." << std::endl;
    }
}

void Logging::stop( const std::string& title, double seconds ) {
    if ( enabled() ) {
        channel() << title << " ... done : " << seconds << "s" << std::endl;
    }
}
//-----------------------------------------------------------------------------------------------------------

std::ostream& NoLogging::channel() {
    return LoggingState::empty_channel();
}

//-----------------------------------------------------------------------------------------------------------

void LoggingResult::stop( const std::string& title, double seconds ) {
    if ( enabled() ) {
        channel() << title << " : " << seconds << "s" << std::endl;
    }
}

//-----------------------------------------------------------------------------------------------------------

}  // namespace trace
}  // namespace runtime
}  // namespace atlas
