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

#include <log4cxx/logstring.h>
#include <log4cxx/dailyrollingfileappender.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/rolling/timebasedrollingpolicy.h>

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::rolling;

IMPLEMENT_LOG4CXX_OBJECT(DailyRollingFileAppender)



DailyRollingFileAppender::DailyRollingFileAppender()
{
}


DailyRollingFileAppender::DailyRollingFileAppender(
    const LayoutPtr& l,
    const LogString& filename,
    const LogString& datePattern1)
    : datePattern(datePattern1)
{
    setLayout(l);
    setFile(filename);
    Pool p;
    activateOptions(p);
}

void DailyRollingFileAppender::setDatePattern(const LogString& newPattern)
{
    datePattern = newPattern;
}

LogString DailyRollingFileAppender::getDatePattern()
{
    return datePattern;
}

void DailyRollingFileAppender::activateOptions(log4cxx::helpers::Pool& p)
{
    TimeBasedRollingPolicyPtr policy = new TimeBasedRollingPolicy();
    LogString pattern(getFile());
    bool inLiteral = false;
    bool inPattern = false;

    for (size_t i = 0; i < datePattern.length(); i++)
    {
        if (datePattern[i] == 0x27 /* '\'' */)
        {
            inLiteral = !inLiteral;

            if (inLiteral && inPattern)
            {
                pattern.append(1, (logchar) 0x7D /* '}' */);
                inPattern = false;
            }
        }
        else
        {
            if (!inLiteral && !inPattern)
            {
                const logchar dbrace[] = { 0x25, 0x64, 0x7B, 0 }; // "%d{"
                pattern.append(dbrace);
                inPattern = true;
            }

            pattern.append(1, datePattern[i]);
        }
    }

    if (inPattern)
    {
        pattern.append(1, (logchar) 0x7D /* '}' */);
    }

    policy->setFileNamePattern(pattern);
    policy->activateOptions(p);
    setTriggeringPolicy(policy);
    setRollingPolicy(policy);

    RollingFileAppenderSkeleton::activateOptions(p);
}


void DailyRollingFileAppender::setOption(const LogString& option,
        const LogString& value)
{
    if (StringHelper::equalsIgnoreCase(option,
                                       LOG4CXX_STR("DATEPATTERN"), LOG4CXX_STR("datepattern")))
    {
        setDatePattern(value);
    }
    else
    {
        RollingFileAppenderSkeleton::setOption(option, value);
    }
}




