/** \file
 *
 *  Contains the LogQueue class implementation.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#include "LogQueue.h"


/// Static singleton retrival function
LogQueue& LogQueue::Instance()
{
//    MutexLocker obtain_lock( m_s );
    static LogQueue lqInstance_g;
    return lqInstance_g;
}


// Constructor
LogQueue::LogQueue()
//: whichQueue_( FIRST_QUEUE )//,
//loggerWaitMutex_(),
//loggerThreadCondition_( loggerWaitMutex_ ),
//loggerRunMutex_()
{}

// Destructor
LogQueue::~LogQueue()
{
    // If the LogQueue is being deleted, should release any memeory it might hold.
    //std::cout << "At destruction, LogQueues have length (read,write) " << queue_[theReadQueue()].size() << "," << queue_[theWriteQueue()].size() << endl;

    //clear( FIRST_QUEUE, true );
    //clear( SECOND_QUEUE, true );
    clear( true );
}

//== Accessor functions ==

/// Push into queue.
LogEntry *LogQueue::push( LogEntry *entry )
{
    //printf("LogQueue(%08X) push...\n", (unsigned int)&getLoggerWaitMutex());
    //printf("In LogQueue::push, locking\n");fflush(stdout);
    //MutexLocker obtain_lock( m_s );
    //wakeLogger();
    //queue_[ theWriteQueue()].push( entry );
    queue_.push( entry );
    //printf("LogQueue(%08X) pushed, read/write size is now %d/%d\n", (unsigned int)&getLoggerWaitMutex(), readQueueSize(), writeQueueSize());
    //printf("In LogQueue::push, done\n");fflush(stdout);
    return entry;
}

/// Sends a wake signal to the logger
//void LogQueue::wakeLogger()
//{
//    //loggerWaitMutex_.lock();
//    //loggerThreadCondition_.signal();
//    //loggerWaitMutex_.unlock();
//}

/// Examine queue, but do not pop element
LogEntry *LogQueue::peek( void )
{
    return queue_.peek();
}

/// Pop out of queue
LogEntry *LogQueue::pop( void )
{
    /// The STL makes a non-empty queue a precondition for running front()
    ///     How should this code react if called on empty queue?

    /// Design for just one reader, not Mutexed.

    //LogEntry * entry = queue_[ theReadQueue()].front();
    //queue_[ theReadQueue()].pop();

    //return entry;
    return queue_.pop();
}

/// Clear the read queue
//void LogQueue::clearReadQueue( bool andDelete )
//{
//    clear( theReadQueue(), andDelete );
//};

/// Clear either queue
//void LogQueue::clear( LogQueue::QueueSelect queueSelect, bool andDelete )
void LogQueue::clear( bool andDelete )
{
    //printf("In LogQueue::clear, locking\n");fflush(stdout);
    //MutexLocker obtain_lock( m_s );
    LogEntry *entry = NULL;
    //while ( !queue_[ queueSelect ].empty() )
    while( !queue_.isEmpty() )
    {
        //entry = queue_[ queueSelect ].front();
        entry = queue_.pop();
        if( andDelete == true )
        {
            delete entry;
        }
        //queue_[ queueSelect ].pop();
    }
    //printf("In LogQueue::clear, done\n");fflush(stdout);
}

/// Is read queue empty?
bool LogQueue::isEmpty( void )
{
    //return queue_[ theReadQueue()].empty();
    return queue_.isEmpty();
}

/// Swap the two queues
//void LogQueue::swap( void )
//{
//    //printf("In LogQueue::swap, locking\n");fflush(stdout);
//    MutexLocker obtain_lock( m_s );
//
//    if ( whichQueue_ == FIRST_QUEUE )
//    {
//        whichQueue_ = SECOND_QUEUE;
//    }
//    else
//    {
//        whichQueue_ = FIRST_QUEUE;
//    }
//    //printf("In LogQueue::swap, done\n");fflush(stdout);
//}

/// Just define not the current queue
//LogQueue::QueueSelect LogQueue::theReadQueue( void )
//{
//    if ( whichQueue_ == FIRST_QUEUE )
//    {
//        return SECOND_QUEUE;
//    }
//    else
//    {
//        return FIRST_QUEUE;
//    }
//}

void LogQueue::FlushQueues( bool andDelete )
{
    LogQueue::Instance().clear( andDelete );
}
