/*
 * Copyright (C) 2015 AVM GmbH <info@avm.de>
 * Copyright (C) 2005 Luca Veltri - University of Parma - Italy
 * 
 * This file is part of MjSip (http://www.mjsip.org)
 * 
 * MjSip is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * MjSip 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with MjSip; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Author(s):
 * Luca Veltri (luca.veltri@unipr.it)
 */

package org.zoolu.tools;

import java.io.*;
import java.util.Calendar;

import de.avm.fundamentals.logger.FileLog;

// import java.util.GregorianCalendar;

/**
 * Class RotatingLog extends Log with log file rotation.
 */
public class RotatingLog extends Log {

    private static final String TAG = "RotatingLog";

	/** Month */
	// public static final int MONTH=GregorianCalendar.MONTH;
	public static final int MONTH = Calendar.MONTH;
	/** Day */
	// public static final int DAY=GregorianCalendar.DAY_OF_MONTH;
	public static final int DAY = Calendar.DAY_OF_MONTH;
	/** Hour */
	// public static final int HOUR=GregorianCalendar.HOUR;
	public static final int HOUR = Calendar.HOUR;
	/** Minute */
	// public static final int MINUTE=GregorianCalendar.MINUTE;
	public static final int MINUTE = Calendar.MINUTE;

	/** Number of log file rotations (value 0 means no rotation) */
	int num_rotations;

	/** Rotates log files */
	String file_name;

	/** Time scale (MONTH, DAY, HOUR, or MINUTE) */
	int time_scale;

	/** Time value that log files are rotated (time = time_scale * time_value) */
	int time_value;

	/** Date of the next rotation */
	long next_rotation;

	/** **************************** Constructors ***************************** */

	/**
	 * Creates a new RotatingLog file <i>filename</i> . RotatingLog size is
	 * limited to <i>logsize</i> [bytes]
	 */
	public RotatingLog(String filename, String logname, int loglevel,
			long logsize, int n_rotations, int t_scale, int t_value) {
		super(filename, logname, loglevel, logsize);
		rInit(filename, n_rotations, t_scale, t_value);
	}

	/** Rotates logs */
	public RotatingLog rotate() {
		if (num_rotations > 0) {
			for (int i = num_rotations - 2; i > 0; i--) { // rename back files
				rename(file_name + i, file_name + (i + 1));
			}
			// save and close current log file
			if (out_stream != null)
				out_stream.close();
			// rename current log file
			if (num_rotations > 1)
				rename(file_name, file_name + 1);
			// reset the log
			try {
				out_stream = new PrintStream(new FileOutputStream(file_name));
			} catch (IOException e) {
                FileLog.w(TAG, e.getMessage(), e);
			}
			init(out_stream, log_tag, verbose_level, max_size);
		}
		return this;
	}

	/**
	 * Prints the <i>log</i> if <i>level</i> isn't greater than the Log
	 * <i>verbose_level</i>
	 */
	public Log print(String message, int level) { // long
		// now=GregorianCalendar.getInstance().getTime().getTime();
		long now = Calendar.getInstance().getTime().getTime();
		if (now > next_rotation) {
			rotate();
			updateNextRotationTime();
		}
		return super.print(message, level);
	}

	/** ************************* Private methods ************************** */

	/** Inits rotation */
	private void rInit(String f_name, int n_rotations, int t_scale, int t_value) {
		file_name = f_name;
		num_rotations = n_rotations;
		time_scale = t_scale;
		time_value = t_value;
		updateNextRotationTime();
	}

	/** Renames a file */
	private static void rename(String src_file, String dst_file) {
		File src = new File(src_file);
		if (src.exists()) {
			File dst = new File(dst_file);
			if (dst.exists())
				dst.delete();
			src.renameTo(dst);
		}
	}

	/** Updates the next rotation date */
	private void updateNextRotationTime() { // Calendar
		// cal=GregorianCalendar.getInstance();
		Calendar cal = Calendar.getInstance();
		cal.add(time_scale, time_value);
		next_rotation = cal.getTime().getTime();
	}

}
