/*
 * 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_FIXED_WINDOW_ROLLING_POLICY_H)
#define _LOG4CXX_ROLLING_FIXED_WINDOW_ROLLING_POLICY_H

#include <log4cxx/rolling/rollingpolicybase.h>




namespace log4cxx
{

namespace helpers
{
class Pool;
}

namespace rolling
{


/**
 * When rolling over, <code>FixedWindowRollingPolicy</code> renames files
 * according to a fixed window algorithm as described below.
 *
 * <p>The <b>ActiveFileName</b> property, which is required, represents the name
 * of the file where current logging output will be written.
 * The <b>FileNamePattern</b>  option represents the file name pattern for the
 * archived (rolled over) log files. If present, the <b>FileNamePattern</b>
 * option must include an integer token, that is the string "%i" somwhere
 * within the pattern.
 *
 * <p>Let <em>max</em> and <em>min</em> represent the values of respectively
 * the <b>MaxIndex</b> and <b>MinIndex</b> options. Let "foo.log" be the value
 * of the <b>ActiveFile</b> option and "foo.%i.log" the value of
 * <b>FileNamePattern</b>. Then, when rolling over, the file
 * <code>foo.<em>max</em>.log</code> will be deleted, the file
 * <code>foo.<em>max-1</em>.log</code> will be renamed as
 * <code>foo.<em>max</em>.log</code>, the file <code>foo.<em>max-2</em>.log</code>
 * renamed as <code>foo.<em>max-1</em>.log</code>, and so on,
 * the file <code>foo.<em>min+1</em>.log</code> renamed as
 * <code>foo.<em>min+2</em>.log</code>. Lastly, the active file <code>foo.log</code>
 * will be renamed as <code>foo.<em>min</em>.log</code> and a new active file name
 * <code>foo.log</code> will be created.
 *
 * <p>Given that this rollover algorithm requires as many file renaming
 * operations as the window size, large window sizes are discouraged. The
 * current implementation will automatically reduce the window size to 12 when
 * larger values are specified by the user.
 *
 *
 *
 *
 * */
class LOG4CXX_EXPORT FixedWindowRollingPolicy : public RollingPolicyBase
{
        DECLARE_LOG4CXX_OBJECT(FixedWindowRollingPolicy)
        BEGIN_LOG4CXX_CAST_MAP()
        LOG4CXX_CAST_ENTRY(FixedWindowRollingPolicy)
        LOG4CXX_CAST_ENTRY_CHAIN(RollingPolicyBase)
        END_LOG4CXX_CAST_MAP()

        int minIndex;
        int maxIndex;
        bool explicitActiveFile;

        /**
         * It's almost always a bad idea to have a large window size, say over 12.
         */
        enum { MAX_WINDOW_SIZE = 12 };

        bool purge(int purgeStart, int maxIndex, log4cxx::helpers::Pool& p) const;

    public:

        FixedWindowRollingPolicy();

        void activateOptions(log4cxx::helpers::Pool& p);
        void setOption(const LogString& option,
                       const LogString& value);

        void rollover();

        int getMaxIndex() const;

        int getMinIndex() const;

        void setMaxIndex(int newVal);
        void setMinIndex(int newVal);

        /**
         * {@inheritDoc}
         */
        RolloverDescriptionPtr initialize(
            const   LogString&              currentActiveFile,
            const   bool                    append,
            log4cxx::helpers::Pool& pool);

        /**
         * {@inheritDoc}
         */
        RolloverDescriptionPtr rollover(
            const   LogString&              currentActiveFile,
            const   bool                    append,
            log4cxx::helpers::Pool& pool);

    protected:
        log4cxx::pattern::PatternMap getFormatSpecifiers() const;

};

LOG4CXX_PTR_DEF(FixedWindowRollingPolicy);

}
}

#endif
