/*
 * This file is part of Nuts Framework.
 * Copyright (C) 2009 Nuts Develop Team.
 *
 * Nuts Framework 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 3 of the License any later version.
 * 
 * Nuts Framework 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 Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.exts.struts2.actions;

import nuts.core.lang.StringUtils;
import nuts.exts.fileupload.UploadManager;
import nuts.exts.struts2.NutsStrutsConstants;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSelectInfo;
import org.apache.commons.vfs.FileSelector;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;

import com.opensymphony.xwork2.inject.Inject;


/**
 * delete upload temporary files
 */
@SuppressWarnings("serial")
public class FileCleanupAction extends CommonServletAction {

	/**
	 * fileSystemManager
	 */
	protected FileSystemManager fileSystemManager;
	
	/**
	 * cleanUpDir
	 */
	protected String cleanupDir;
	
	/**
	 * milliseconds since last modified. (default: 1h) 
	 */
	protected long expiredTime = 60 * 60 * 1000;

	/**
	 * @return fileSystemManager
	 * @throws FileSystemException if an error occurs
	 */
	public FileSystemManager getFileSystemManager() throws FileSystemException {
		if (fileSystemManager == null) {
			fileSystemManager = UploadManager.getFileSystemManager();
		}
		return fileSystemManager;
	}

	/**
	 * @param fileSystemManager the fileSystemManager to set
	 */
	@Inject(required=false)
	public void setManager(FileSystemManager fileSystemManager) {
		this.fileSystemManager = fileSystemManager;
	}

	/**
	 * @return the expiredTime
	 */
	public long getExpiredTime() {
		return expiredTime;
	}

	/**
	 * @param expiredTime the expiredTime to set
	 */
	public void setExpiredTime(long expiredTime) {
		this.expiredTime = expiredTime;
	}
	
	/**
	 * @return the cleanupDir
	 */
	public String getCleanupDir() {
		if (StringUtils.isEmpty(cleanupDir)) {
			return UploadManager.getSaveDir();
		}
		return cleanupDir;
	}

	/**
	 * @param cleanupDir the cleanupDir to set
	 */
	@Inject(value = NutsStrutsConstants.NUTS_MULTIPART_SAVEDIR, required = false)
	public void setCleanupDir(String cleanupDir) {
		this.cleanupDir = cleanupDir;
	}

	private static class CleanUpFileSelector implements FileSelector {
		private long expiredTime;
		
		public CleanUpFileSelector(long expiredTime) {
			super();
			this.expiredTime = expiredTime;
		}

		public boolean includeFile(FileSelectInfo fileInfo) throws Exception {
			FileObject f = fileInfo.getFile();
			if (f.getType() == FileType.FILE) {
				long time = System.currentTimeMillis();
				if (time - f.getContent().getLastModifiedTime() > expiredTime) {
					return true;
				}
			}
			return false;
		}

		public boolean traverseDescendents(FileSelectInfo fileInfo)
				throws Exception {
			return true;
		}
	}
	
	/**
	 * execute
	 * 
	 * @return SUCCESS
	 * @throws Exception if an error occurs
	 */
	public synchronized String execute() throws Exception {
		FileObject repository = getFileSystemManager().resolveFile(getCleanupDir());
		
		if (repository.exists() && repository.getType() == FileType.FOLDER) {
			FileObject[] files = repository.findFiles(new CleanUpFileSelector(expiredTime));
			
			for (FileObject f : files) {
				if (f.delete()) {
					if (log.isDebugEnabled()) {
						log.debug("File deleted - " + f.getName());
					}
				}
				else {
					if (log.isWarnEnabled()) {
						log.warn("Fail to delete file - " + f.getName());
					}
				}
			}
		}

		return SUCCESS;
	}
}
