/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#include "log_module.hxx"

#include <stdio.h>
#include <string>

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
#include <com/sun/star/logging/XCsvLogFormatter.hpp>
#endif
#ifndef _COM_SUN_STAR_LOGGING_XLOGFORMATTER_HPP_
#include <com/sun/star/logging/XLogFormatter.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
/** === end UNO includes === **/

#include <comphelper/componentcontext.hxx>

#include <cppuhelper/implbase2.hxx>

#include <rtl/ustrbuf.hxx>

#include <osl/thread.h>

namespace logging
{

    /** === begin UNO using === **/
    using ::com::sun::star::logging::XCsvLogFormatter;
    using ::com::sun::star::logging::XLogFormatter;
    using ::com::sun::star::uno::XComponentContext;
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::lang::XServiceInfo;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::logging::LogRecord;
    using ::com::sun::star::uno::XInterface;
    /** === end UNO using === **/

    //= CsvFormatter - declaration
    //= formats for csv files as defined by RFC4180
    typedef ::cppu::WeakImplHelper2 <   XCsvLogFormatter
                                    ,   XServiceInfo
                                    >   CsvFormatter_Base;
    class CsvFormatter : public CsvFormatter_Base
    {
    public:
        virtual ::rtl::OUString SAL_CALL formatMultiColumn(const Sequence< ::rtl::OUString>& column_data) throw (RuntimeException);
        
        // XServiceInfo - static version
        static ::rtl::OUString SAL_CALL getImplementationName_static();
        static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static();
        static Reference< XInterface > Create( const Reference< XComponentContext >& context );

    protected:
        CsvFormatter( const Reference< XComponentContext >& context );
        virtual ~CsvFormatter();

        // XCsvLogFormatter
        virtual ::sal_Bool SAL_CALL getLogEventNo() throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL getLogThread() throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL getLogTimestamp() throw (RuntimeException);
        virtual ::sal_Bool SAL_CALL getLogSource() throw (RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getColumnnames() throw (RuntimeException);

        virtual void SAL_CALL setLogEventNo( ::sal_Bool log_event_no ) throw (RuntimeException);
        virtual void SAL_CALL setLogThread( ::sal_Bool log_thread ) throw (RuntimeException);
        virtual void SAL_CALL setLogTimestamp( ::sal_Bool log_timestamp ) throw (RuntimeException);
        virtual void SAL_CALL setLogSource( ::sal_Bool log_source ) throw (RuntimeException);
        virtual void SAL_CALL setColumnnames( const Sequence< ::rtl::OUString>& column_names) throw (RuntimeException);

        // XLogFormatter
        virtual ::rtl::OUString SAL_CALL getHead(  ) throw (RuntimeException);
        virtual ::rtl::OUString SAL_CALL format( const LogRecord& Record ) throw (RuntimeException);
        virtual ::rtl::OUString SAL_CALL getTail(  ) throw (RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException);
        virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& service_name ) throw(RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);

    private:
        ::comphelper::ComponentContext m_aContext;
        ::sal_Bool m_LogEventNo;
        ::sal_Bool m_LogThread;
        ::sal_Bool m_LogTimestamp;
        ::sal_Bool m_LogSource;
        ::sal_Bool m_MultiColumn;
        ::com::sun::star::uno::Sequence< ::rtl::OUString > m_Columnnames;
    };
} // namespace logging

//= private helpers
namespace
{
    const sal_Unicode quote_char = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"")).toChar();
    const sal_Unicode comma_char = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")).toChar();
    const ::rtl::OUString dos_newline = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\r\n"));

    inline bool needsQuoting(const ::rtl::OUString& str)
    {
        static const ::rtl::OUString quote_trigger_chars = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("\",\n\r"));
        sal_Int32 len = str.getLength();
        for(sal_Int32 i=0; i<len; i++)
            if(quote_trigger_chars.indexOf(str[i])!=-1)
                return true;
        return false;
    };

    inline void appendEncodedString(::rtl::OUStringBuffer& buf, const ::rtl::OUString& str)
    {
        if(needsQuoting(str))
        {
            // each double-quote will get replaced by two double-quotes
            buf.append(quote_char);
            const sal_Int32 buf_offset = buf.getLength();
            const sal_Int32 str_length = str.getLength();
            buf.append(str);
            // special treatment for the last character
            if(quote_char==str[str_length-1])
                buf.append(quote_char);
            // iterating backwards because the index at which we insert wont be shifted 
            // when moving that way.
            for(sal_Int32 i = str_length; i>=0; )
            {
                i=str.lastIndexOf(quote_char, --i);
                if(i!=-1)
                    buf.insert(buf_offset + i, quote_char);
            }
            buf.append(quote_char);
        }
        else
            buf.append(str);
    }; 
    
    ::com::sun::star::uno::Sequence< ::rtl::OUString> initialColumns()
    {
        com::sun::star::uno::Sequence< ::rtl::OUString> result = ::com::sun::star::uno::Sequence< ::rtl::OUString>(1);
        result[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("message"));
        return result;
    };
}

//= CsvFormatter - implementation
namespace logging
{
    CsvFormatter::CsvFormatter( const Reference< XComponentContext >& context )
        :m_aContext( context ), 
        m_LogEventNo(true), 
        m_LogThread(true), 
        m_LogTimestamp(true), 
        m_LogSource(false), 
        m_MultiColumn(false),
        m_Columnnames(initialColumns())
    { }

    CsvFormatter::~CsvFormatter()
    { }

    ::sal_Bool CsvFormatter::getLogEventNo() throw (RuntimeException)
    {
        return m_LogEventNo;
    }

    ::sal_Bool CsvFormatter::getLogThread() throw (RuntimeException)
    {
        return m_LogThread;
    }

    ::sal_Bool CsvFormatter::getLogTimestamp() throw (RuntimeException)
    {
        return m_LogTimestamp;
    }

    ::sal_Bool CsvFormatter::getLogSource() throw (RuntimeException)
    {
        return m_LogSource;
    }

    Sequence< ::rtl::OUString > CsvFormatter::getColumnnames() throw (RuntimeException)
    {
        return m_Columnnames;
    }

    void CsvFormatter::setLogEventNo(::sal_Bool log_event_no) throw (RuntimeException)
    {
        m_LogEventNo = log_event_no;
    }

    void CsvFormatter::setLogThread(::sal_Bool log_thread) throw (RuntimeException)
    {
        m_LogThread = log_thread;
    }

    void CsvFormatter::setLogTimestamp(::sal_Bool log_timestamp) throw (RuntimeException)
    {
        m_LogTimestamp = log_timestamp;
    }

    void CsvFormatter::setLogSource(::sal_Bool log_source) throw (RuntimeException)
    {
        m_LogSource = log_source; 
    }

    void CsvFormatter::setColumnnames(const Sequence< ::rtl::OUString >& columnnames) throw (RuntimeException)
    {
        m_Columnnames = Sequence< ::rtl::OUString>(columnnames);
        m_MultiColumn = (m_Columnnames.getLength()>1);
    }

    ::rtl::OUString SAL_CALL CsvFormatter::getHead(  ) throw (RuntimeException)
    {
        ::rtl::OUStringBuffer buf;
        if(m_LogEventNo)
            buf.appendAscii("event no,");
        if(m_LogThread)
            buf.appendAscii("thread,");
        if(m_LogTimestamp)
            buf.appendAscii("timestamp,");
        if(m_LogSource)
            buf.appendAscii("class,method,");
        sal_Int32 columns = m_Columnnames.getLength();
        for(sal_Int32 i=0; i<columns; i++)
        {
            buf.append(m_Columnnames[i]); 
            buf.append(comma_char);
        }
        buf.setLength(buf.getLength()-1);
        buf.append(dos_newline);
        return buf.makeStringAndClear();
    }

    ::rtl::OUString SAL_CALL CsvFormatter::format( const LogRecord& record ) throw (RuntimeException)
    {
        ::rtl::OUStringBuffer aLogEntry;

        if(m_LogEventNo)
        {
            aLogEntry.append( record.SequenceNumber );
            aLogEntry.append(comma_char);
        }

        if(m_LogThread)
        {
            aLogEntry.append( record.ThreadID );
            aLogEntry.append(comma_char);
        }

        if(m_LogTimestamp)
        {
            // ISO 8601
            char buffer[ 30 ];
            const size_t buffer_size = sizeof( buffer );
            snprintf( buffer, buffer_size, "%04i-%02i-%02iT%02i:%02i:%02i.%02i",
                (int)record.LogTime.Year,
                (int)record.LogTime.Month,
                (int)record.LogTime.Day,
                (int)record.LogTime.Hours,
                (int)record.LogTime.Minutes,
                (int)record.LogTime.Seconds,
                (int)record.LogTime.HundredthSeconds );
            aLogEntry.appendAscii( buffer );
            aLogEntry.append(comma_char);
        }
        
        if(m_LogSource)
        {
            appendEncodedString(aLogEntry, record.SourceClassName);
            aLogEntry.append(comma_char);

            appendEncodedString(aLogEntry, record.SourceMethodName);
            aLogEntry.append(comma_char);
        }

        // if the CsvFormatter has multiple columns set via setColumnnames(), the
        // message of the record is expected to be encoded with formatMultiColumn
        // if the CsvFormatter has only one column set, the message is expected not
        // to be encoded
        if(m_MultiColumn)
            aLogEntry.append(record.Message);
        else
            appendEncodedString(aLogEntry, record.Message);

        aLogEntry.append( dos_newline );
        return aLogEntry.makeStringAndClear();
    }
    
    ::rtl::OUString SAL_CALL CsvFormatter::getTail(  ) throw (RuntimeException)
    {
        return ::rtl::OUString();
    }

    ::rtl::OUString SAL_CALL CsvFormatter::formatMultiColumn(const Sequence< ::rtl::OUString>& column_data) throw (RuntimeException)
    {
        sal_Int32 columns = column_data.getLength();
        ::rtl::OUStringBuffer buf;
        for(int i=0; i<columns; i++)
        {
            appendEncodedString(buf, column_data[i]);
            buf.append(comma_char);
        }
        buf.setLength(buf.getLength()-1);
        return buf.makeStringAndClear();
    }

    ::sal_Bool SAL_CALL CsvFormatter::supportsService( const ::rtl::OUString& service_name ) throw(RuntimeException)
    {
        const Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames() );
        for (   const ::rtl::OUString* pServiceNames = aServiceNames.getConstArray();
                pServiceNames != aServiceNames.getConstArray() + aServiceNames.getLength();
                ++pServiceNames
            )
            if ( service_name == *pServiceNames )
                return sal_True;
        return sal_False;
    }
    
    ::rtl::OUString SAL_CALL CsvFormatter::getImplementationName() throw(RuntimeException)
    {
        return getImplementationName_static();
    }
    
    Sequence< ::rtl::OUString > SAL_CALL CsvFormatter::getSupportedServiceNames() throw(RuntimeException)
    {
        return getSupportedServiceNames_static();
    }
    
    ::rtl::OUString SAL_CALL CsvFormatter::getImplementationName_static()
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.CsvFormatter" ) );
    }
    
    Sequence< ::rtl::OUString > SAL_CALL CsvFormatter::getSupportedServiceNames_static()
    {
        Sequence< ::rtl::OUString > aServiceNames(1);
        aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.logging.CsvFormatter" ) );
        return aServiceNames;
    }

    Reference< XInterface > CsvFormatter::Create( const Reference< XComponentContext >& context )
    {
        return *( new CsvFormatter( context ) );
    }

    void createRegistryInfo_CsvFormatter()
    {
        static OAutoRegistration< CsvFormatter > aAutoRegistration;
    }
} // namespace logging
