/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 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.fileupload;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;

import nuts.core.io.IOUtils;
import nuts.core.lang.StringUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;


/**
 */
@SuppressWarnings("serial")
public class UploadFile implements Serializable {

	protected static final Log log = LogFactory.getLog(UploadFile.class);

	/**
	 * constructor
	 */
	public UploadFile() {
	}

	protected FileObject file;
	protected String contentType;
	protected String fileName;
	
	protected byte[] data;
	protected Long dataLength;

	/**
	 * @return the file
	 */
	public FileObject getFile() {
		return file;
	}

	/**
	 * @param file the file to set
	 */
	public void setFile(FileObject file) {
		this.file = file;
	}
	
	/**
	 * @return the contentType
	 */
	public String getContentType() {
		return contentType;
	}
	
	/**
	 * @param contentType the contentType to set
	 */
	public void setContentType(String contentType) {
		this.contentType = contentType;
	}
	
	/**
	 * @return the fileName
	 */
	public String getFileName() {
		return fileName;
	}

	/**
	 * @param fileName the fileName to set
	 */
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	
	/**
	 * @return the saveName
	 */
	public String getSaveName() {
		return file == null ? null : file.getName().getBaseName();
	}

	/**
	 * @param saveName the saveName to set
	 * @throws IOException if an I/O error occurs
	 */
	public void setSaveName(String saveName) throws IOException {
		if (StringUtils.isNotEmpty(saveName)) {
			this.file = UploadManager.resolveUploadFile(saveName);
		}
	}
	
	/**
	 * @return the saveTime
	 */
	public Long getSaveTime() {
		Long st = null;
		if (file != null) {
			try {
				st = file.getContent().getLastModifiedTime();
			}
			catch (IOException ex) {
			}
		}
		return st;
	}

	/**
	 * @return the data
	 * @throws FileNotFoundException if file not found
	 * @throws IOException if an I/O error occurs
	 */
	public byte[] getData() throws FileNotFoundException, IOException {
		if (data == null && file != null && file.exists()) {
			data = IOUtils.toByteArray(file);
		}
		return data;
	}

	/**
	 * @param data the data to set
	 * @throws IOException IOException
	 */
	public void setData(byte[] data) throws IOException {
		this.data = data;
		if (this.file != null) {
			IOUtils.write(this.data, this.file);
		}
		this.dataLength = (data == null ? null : (long)data.length);
	}

	/**
	 * @return the dataLength
	 */
	public Long getDataLength() {
		return dataLength;
	}

	/**
	 * @param dataLength the dataLength to set
	 */
	public void setDataLength(Long dataLength) {
		this.dataLength = dataLength;
	}

	/**
	 * @return the fileSize
	 */
	public long getFileSize() {
		if (data != null) {
			return data.length;
		}
		else if (file != null) {
			try {
				if (file.exists()) {
					return file.getContent().getSize();
				}
			}
			catch (FileSystemException e) {
				log.warn("Failed to getFileSize", e);
			}
		}
		else if (dataLength != null) {
			return dataLength;
		}

		return 0L;
	}

	/**
	 * create a upload file
	 * @throws IOException IOException
	 */
	public void newFile() throws IOException {
		this.file = UploadManager.createUploadFile(this.fileName);
	}

	/**
	 * create a upload file
	 * @param baseName base name
	 * @throws IOException IOException
	 */
	public void newFile(String baseName) throws IOException {
		this.file = UploadManager.createUploadFile(baseName);
	}

	/**
	 * @return true if file exists
	 */
	public boolean isExist() {
		if (data != null) {
			return true;
		}
		
		if (file != null) {
			try {
				return file.exists();
			}
			catch (FileSystemException e) {
				log.warn("Failed to get file exist", e);
			}
		}
		
		if (dataLength != null && dataLength > 0) {
			return true;
		}
		
		return false;
	}
	
	/**
     * @return  a string representation of the object.
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();

		sb.append("{ ");
		sb.append("file: ").append(file);
		sb.append(", ");
		sb.append("contentType: ").append(contentType);
		sb.append(", ");
		sb.append("fileName: ").append(fileName);
		sb.append(", ");
		sb.append("fileSize: ").append(getFileSize());
		sb.append(" }");
		
		return sb.toString();
	}
}
