/**
 * JOnAS
 * Copyright (C) 2010 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.audit.internal.logger.pool;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * This class manage a pool of dated files.
 * @author Vincent Michaud
 */
public class DatedFileLogPool extends FileLogPool {

    /**
     * Regular expression identifying a date.
     */
    private static final String DATE_PATTERN = "[0-9]{4}-[0-1][0-9]-[0-3][0-9]";

    /**
     * The date format.
     */
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * The calendar.
     */
    private Calendar calendar;

    /**
     * Date of the next day.
     */
    private long nextDay;

    /**
     * Constructor.
     * @param dirPath The directory of the pool
     * @param className Name of the class representative to the log files pool
     * @param positionVariablePattern Index where the variable pattern is
     *        inserted
     * @param fixedPattern A fixed pattern, without the variable pattern
     * @param msgPattern The pattern of the log message (standards are defined
     *        in Monolog documentation)
     * @param maxFiles Determine the maximum number of log files in the pool
     * @param fileLogger Determine if a file logger is used
     * @param consoleLogger Determine if a console logger is used
     * @throws IOException If the path of the pool is corresponding of a file
     *         path
     */
    public DatedFileLogPool(final String dirPath, final String className, final String fixedPattern,
            final int positionVariablePattern, final String msgPattern, final int maxFiles, final boolean fileLogger,
            final boolean consoleLogger) throws IOException {
        super(dirPath, className, fixedPattern, DATE_PATTERN, positionVariablePattern, msgPattern, maxFiles, fileLogger,
                consoleLogger);
    }

    /**
     * Determine the first pattern of the log file name.
     * @return The default pattern
     * @throws IOException If the initial pattern is invalid
     */
    @Override
    protected String initLogFilenamePattern() throws IOException {
        this.calendar = new GregorianCalendar();
        this.calendar.set(Calendar.HOUR, 0);
        this.calendar.set(Calendar.MINUTE, 0);
        this.calendar.set(Calendar.SECOND, 0);
        this.calendar.set(Calendar.MILLISECOND, 0);
        this.calendar.add(Calendar.DAY_OF_MONTH, 1);
        this.nextDay = this.calendar.getTimeInMillis();
        return DATE_FORMAT.format(new Date());
    }

    /**
     * Determine the missing pattern of the log file name.
     * @return The pattern of the log file name. If the return is null, the old
     *         pattern is kept.
     */
    @Override
    protected String getLogFilenamePattern() {
        if (System.currentTimeMillis() >= this.nextDay) {
            String res = DATE_FORMAT.format(this.calendar.getTime());
            this.calendar.add(Calendar.DAY_OF_MONTH, 1);
            this.nextDay = this.calendar.getTimeInMillis();
            return res;
        }
        return null;
    }

    /**
     * Compare two filename.
     * @param filename1 The first filename
     * @param filename2 The second filename
     * @return The value 0 if the second filename is equal to the first; a value
     *         less than 0 if the first filename is less than second; and a
     *         value greater than 0 if first pattern is greater than the second
     *         filename
     */
    @Override
    protected int compareFilename(final String filename1, final String filename2) {
        return filename1.compareTo(filename2);
    }

    /**
     * Find a log file with the specified date.
     * @param year The year of the log file
     * @param month The month of the log file
     * @param day The day of the log v
     * @return The file found, or null if nothing is found
     */
    public File findFile(final int year, final int month, final int day) {
        Calendar c = new GregorianCalendar(year, month - 1, day);
        return findFile(DATE_FORMAT.format(c.getTime()));
    }

    /**
     * Find the name of the log file with the specified motif.
     * @param year The year of the log file
     * @param month The month of the log file
     * @param day The day of the log file
     * @return The name of the file
     */
    public String findFileName(final int year, final int month, final int day) {
        Calendar c = new GregorianCalendar(year, month - 1, day);
        return findFileName(DATE_FORMAT.format(c.getTime()));
    }

    /**
     * Clean the log pool all files which are before or after a specific log.
     * The specific log is also removed.
     * @param year The year of the log file
     * @param month The month of the log file
     * @param day The day of the log file
     * @param old If true, old files are removed, otherwise, recent files are
     *        removed
     */
    public void cleanLogPool(final int year, final int month, final int day, final boolean old) {
        String name = findFileName(year, month, day);
        cleanLogPool(name, old);
    }

    /**
     * List all filenames which are older or more recent than the specified log
     * file.
     * @param year The year of the log file
     * @param month The month of the log file
     * @param day The day of the log file
     * @param action The action executed on log files
     * @param old If true, files older than the specified log file are listed
     *        otherwise, files more recent than the specified log file are
     *        listed
     * @param inclusive Determine if the specified log file is included in the
     *        result
     */
    public void listLogFiles(final int year, final int month, final int day, final LogFileAction action, final boolean old,
            final boolean inclusive) {
        String name = findFileName(year, month, day);
        listLogFiles(name, action, old, inclusive);
    }

    /**
     * Remove a specific log file.
     * @param filename The name of the file
     */
    public void removeLogFile(final int year, final int month, final int day) {
        String name = findFileName(year, month, day);
        removeLogFile(name);
    }

    /**
     * List all filenames which are older or more recent than the specified
     * filename.
     * @param filename The filename which others are compared
     * @param old If true, files older than the specified filename are listed
     *        otherwise, files more recent than the specified filename are
     *        listed
     * @param inclusive Determine if the specified filename is included in the
     *        result
     * @return The list of file sorted by file name, or null if not any files
     *         are found in the log pool
     */
    public File[] listLogFiles(final int year, final int month, final int day, final boolean old, final boolean inclusive) {
        String name = findFileName(year, month, day);
        return listLogFiles(name, old, inclusive);
    }

}
