/**
 * License Agreement.
 *
 *  JBoss RichFaces - Ajax4jsf Component Library
 *
 * Copyright (C) 2007  Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */
package org.richfaces.realworld.fileupload;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.faces.context.FacesContext;
import javax.imageio.ImageIO;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.richfaces.realworld.service.Constants;
import org.richfaces.realworld.util.ImageUtils;

@Name("fileManager")
@Scope(ScopeType.CONVERSATION)
public class FileManager {

	
	private static final String _MEDIUM = "_medium";
	private static final String _MINI = "_mini";
	private String uploadRoot;
	
	public String getUploadRoot() {
		return uploadRoot;
	}

	public void setUploadRoot(String uploadRoot) {
		this.uploadRoot = uploadRoot;
	}
	
	public FileManager(){
		FacesContext fc = FacesContext.getCurrentInstance();
		if(fc!=null){
			this.setUploadRoot(fc.getExternalContext().getInitParameter(Constants.UPLOAD_ROOT));
		}	
	}
	
	public String getFileSeparator() {
		return System.getProperty(Constants.FILE_SEPARATOR);
	}

	public boolean isDirectoryPresent(String directory) {
		String fullPath = getAbsolutePath(directory);
		File file = new File(fullPath);
		return file.exists() && file.isDirectory();
	}
	
	public void deleteDirectory(String... directories) {
		String directory = new String();
		for (String chunk: directories){
			directory += chunk + getFileSeparator();
		}
		String fullPath = getAbsolutePath(directory);
		File file = new File(fullPath);
		if(file.exists()){
			for(String f :file.list()){
				File temp = new File(fullPath+getFileSeparator()+f);
				temp.delete();
			}
			file.delete();
		}
	}
	
	public String concat(String... directories){
		String directory = new String();
		for (String chunk: directories){
			directory += chunk + getFileSeparator();
		}
		return directory;
	}
	
	public String concatwithSlash(String... directories){
		String directory = new String();
		for (String chunk: directories){
			directory += chunk + Constants.SLASH;
		}
		return directory;
	}

	public boolean renameDirectory(String directoryOld, String directoryNew){
		String fullPath = getAbsolutePath(directoryOld);
		File fileOld = new File(fullPath);
		File fileNew = new File(getUploadRoot() + directoryNew);
		createDirectoryIfNotExist(directoryNew);
		if(fileNew.exists())
			if( fileNew.isDirectory() ){
				return false;
			}else{
				fileNew.delete();
			}
		fileOld.renameTo(fileNew);
		return true;
	}
	
	public void addDirectory(String... directories) {
		String directory = new String();
		for (String chunk: directories){
			directory += chunk ;
		}
		String fullPath = getAbsolutePath(directory);
		File file = new File(fullPath);
		file.mkdirs();
	}

	public boolean addImage(String fileName, byte[] data) {
		createDirectoryIfNotExist(fileName);
		/*
		try {
			
			writeFileTodisk(data, fileName, 0, 0, "" );
			writeFileTodisk(data, fileName, 100, 100, _MINI );
			writeFileTodisk(data, fileName, 500, 500, _MEDIUM );
					
		} catch (IOException e) {
			return false;
		}
		*/
		return true;
	}
	
	private void writeFileTodisk(byte[] data, String fileName, int width, int height, String format) throws IOException{
		InputStream inputStream = new ByteArrayInputStream(data);
		BufferedImage bsrc = ImageIO.read(inputStream);
		if(width == 0){
			String dest = getUploadRoot() + fileName;
			ImageIO.write(bsrc, Constants.JPG, new File(dest));
			return;
		}
		BufferedImage bdest = new ImageUtils(bsrc).resizeImage(width, height);
		/*
		BufferedImage bdest = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = bdest.createGraphics();
		AffineTransform at = AffineTransform.getScaleInstance((double) width
				/ bsrc.getWidth(), (double) height / bsrc.getHeight());
		Map<RenderingHints.Key, Object> hints = new HashMap<RenderingHints.Key, Object>();
		hints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g.addRenderingHints(hints);
		g.drawRenderedImage(bsrc, at);
		*/
		String dest = getUploadRoot() + transformPath(fileName, format);
		
		ImageIO.write(bdest, Constants.JPG, new File(dest));
		inputStream.close();
	}
	
	public String transformPath(String target, String substitute){
		String begin = target.substring(0, target.lastIndexOf(Constants.DOT));
		String end = target.substring(target.lastIndexOf(Constants.DOT));
		return begin + substitute + end;
	}
	
	public void deleteImage(String fileName) {
		String fullPath = getAbsolutePath(fileName);
		deleteImage(new File(fullPath));
		deleteImage(new File(transformPath(fullPath, _MINI)));
		deleteImage(new File(transformPath(fullPath, _MEDIUM)));
	}

	private void deleteImage(File file){
		if(file.exists()){
			file.delete();
		}
	}
	
	public String getPathOfImage(String path){
		int i = path.lastIndexOf(Constants.SLASH);
		return path.substring(i);
	}
	
	public void renameImage(String fileNameOld, String fileNameNew) {
		createDirectoryIfNotExist(fileNameNew);
		String fullPath = getAbsolutePath(fileNameOld);
		renameImage(new File(getAbsolutePath(fileNameNew)), new File(fullPath));
		renameImage(new File(getAbsolutePath(transformPath(fileNameNew, _MINI))), new File(transformPath(fullPath, _MINI)));
		renameImage(new File(getAbsolutePath(transformPath(fileNameNew, _MEDIUM))), new File(transformPath(fullPath, _MEDIUM)));
	}
	
	private void renameImage(File fileNew, File fileOld){
		if(fileNew.exists()){
			fileNew.delete();
		}
		fileOld.renameTo(fileNew);
	}

	private void createDirectoryIfNotExist(String fileNameNew) {
		int lastIndexOf = fileNameNew.lastIndexOf(getFileSeparator());
		if(lastIndexOf > 0){
			String directory = fileNameNew.substring(0, lastIndexOf);
			File file = new File(getUploadRoot()+directory);
			if(!file.exists()){
				file.mkdirs();
			}
		}
	}

	public boolean isImagePresent(String fileName) {
		String fullPath = getAbsolutePath(fileName);
		File file = new File(fullPath);
		return file.exists() && !file.isDirectory();
	}
	
	public File getImage(String fileName){
		if(isImagePresent(fileName)){
			return new File(getAbsolutePath(fileName));
		}
		return null;
	}

	private String getAbsolutePath(String fileName) {
		return getUploadRoot() + fileName;
	}
	
	public String transformToServerPath(String filename){
		String[] res = filename.split(Constants.SLASH);
		StringBuilder sb = new StringBuilder();
		sb.append(res[0]);
		for(int i = 1; i < res.length; i++){
			sb.append(this.getFileSeparator() + res[i]);
		}
		String string = sb.toString();
		return string;
	}
}
