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

#if !defined(_LOG4CXX_ROLLING_ROLLING_FILE_APPENDER_SKELETON_H)
#define _LOG4CXX_ROLLING_ROLLING_FILE_APPENDER_SKELETON_H

#include <log4cxx/portability.h>
#include <log4cxx/spi/optionhandler.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/rolling/triggeringpolicy.h>
#include <log4cxx/rolling/rollingpolicy.h>
#include <log4cxx/rolling/action.h>

namespace log4cxx
{
namespace rolling
{


/**
 *  Base class for log4cxx::rolling::RollingFileAppender and log4cxx::RollingFileAppender
 * (analogues of org.apache.log4j.rolling.RFA from extras companion and
 *  org.apache.log4j.RFA from log4j 1.2, respectively).
 *
 * */
class LOG4CXX_EXPORT RollingFileAppenderSkeleton : public FileAppender
{
        DECLARE_LOG4CXX_OBJECT(RollingFileAppenderSkeleton)
        BEGIN_LOG4CXX_CAST_MAP()
        LOG4CXX_CAST_ENTRY(RollingFileAppenderSkeleton)
        LOG4CXX_CAST_ENTRY_CHAIN(FileAppender)
        END_LOG4CXX_CAST_MAP()

        /**
         * Triggering policy.
         */
        TriggeringPolicyPtr triggeringPolicy;

        /**
         * Rolling policy.
         */
        RollingPolicyPtr rollingPolicy;

        /**
         * Length of current active log file.
         */
        size_t fileLength;

        /**
         *  save the loggingevent
         */
        spi::LoggingEventPtr* _event;
    public:
        /**
         * The default constructor simply calls its {@link
         * FileAppender#FileAppender parents constructor}.
         * */
        RollingFileAppenderSkeleton();

        void activateOptions(log4cxx::helpers::Pool&);


        /**
           Implements the usual roll over behaviour.

           <p>If <code>MaxBackupIndex</code> is positive, then files
           {<code>File.1</code>, ..., <code>File.MaxBackupIndex -1</code>}
           are renamed to {<code>File.2</code>, ...,
           <code>File.MaxBackupIndex</code>}. Moreover, <code>File</code> is
           renamed <code>File.1</code> and closed. A new <code>File</code> is
           created to receive further log output.

           <p>If <code>MaxBackupIndex</code> is equal to zero, then the
           <code>File</code> is truncated with no backup files created.

         */
        bool rollover(log4cxx::helpers::Pool& p);

    protected:

        /**
         Actual writing occurs here.
        */
        virtual void subAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);

    protected:

        RollingPolicyPtr getRollingPolicy() const;

        TriggeringPolicyPtr getTriggeringPolicy() const;

        /**
         * Sets the rolling policy. In case the 'policy' argument also implements
         * {@link TriggeringPolicy}, then the triggering policy for this appender
         * is automatically set to be the policy argument.
         * @param policy
         */
        void setRollingPolicy(const RollingPolicyPtr& policy);

        void setTriggeringPolicy(const TriggeringPolicyPtr& policy);

    public:
        /**
          * Close appender.  Waits for any asynchronous file compression actions to be completed.
        */
        void close();

    protected:
        /**
           Returns an OutputStreamWriter when passed an OutputStream.  The
           encoding used will depend on the value of the
           <code>encoding</code> property.  If the encoding value is
           specified incorrectly the writer will be opened using the default
           system encoding (an error message will be printed to the loglog.
         @param os output stream, may not be null.
         @return new writer.
         */
        log4cxx::helpers::WriterPtr createWriter(log4cxx::helpers::OutputStreamPtr& os);

    public:



        /**
         * Get byte length of current active log file.
         * @return byte length of current active log file.
         */
        size_t getFileLength() const;

#ifdef LOG4CXX_MULTI_PROCESS
        /**
         * Set byte length of current active log file.
         * @return void
         */
        void setFileLength(size_t length);

        /**
         *  Release the file lock
         * @return void
         */
        void releaseFileLock(apr_file_t* lock_file);
        /**
         * re-open the latest file when its own handler has been renamed
         * @return void
         */
        void reopenLatestFile(log4cxx::helpers::Pool& p);
#endif

        /**
         * Increments estimated byte length of current active log file.
         * @param increment additional bytes written to log file.
         */
        void incrementFileLength(size_t increment);

};


LOG4CXX_PTR_DEF(RollingFileAppenderSkeleton);

}
}

#endif

