/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



// Base header file.  Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>



#include "Logger.hpp"


#include <ctime>

#include <iostream>
#include <iomanip>


using xalanc::XalanDOMString;




Logger::Logger(StreamType&  stream) :
    m_stream(stream)
{
    logText[eMessage] = "Message";
    logText[eWarning] = "Warning";
    logText[eError] = "Error";
}



Logger::StreamType&
Logger::message()
{
    return log(eMessage);
}



Logger::StreamType& 
Logger::warning()
{
    return log(eWarning);
}



Logger::StreamType& 
Logger::error()
{
    return log(eError);
}


Logger::StreamType& 
Logger::log(eLogType    logType)
{
    using std::ctime;
    using std::time;
    using std::time_t;

    time_t theTime;
    time(&theTime);

    // Not thread safe
    char* const timeStr = ctime(&theTime);
    timeStr[24] = '\0';

    m_stream << timeStr
             << std::setw(10)
             << logText[logType]
             << ": ";

    return m_stream;
}
