package info.bukova.isspst.storage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.servlet.ServletContext;

public class LocalFileStorage implements FileStorage {

	private String rootPath;
	private ServletContext context;

	public void setRootPath(String rootPath) {
		this.rootPath = rootPath;
	}

	public void setContext(ServletContext ctx) {
		this.context = ctx;
	}

	private String getFullPath() {
		return context.getRealPath(rootPath) + File.separator;
	}

	@Override
	public void saveFile(byte[] data, String fileName) {

		File file = new File(getFullPath() + fileName);
		FileOutputStream os = null;
		try {
			os = new FileOutputStream(file);
			os.write(data);
			os.flush();
			os.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (os != null) {
					os.flush();
					os.close();
				}
			} catch (IOException e) {
				throw new StorageException("Cannot close stream", e.getCause());
			}
		}
	}

	@Override
	public void saveFile(File file, String path) {
		File dest = new File(getFullPath() + path + File.pathSeparator + file.getName());
		FileOutputStream fos = null;
		
		try {
			fos = new FileOutputStream(dest);
			fos.write(fileData(file.getName()));
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			throw new StorageException("Cannot move file: " + file.getName(), e.getCause());
		} catch (IOException e) {
			throw new StorageException("Cannot move file: " + file.getName(), e.getCause());
		} finally {
			if (fos != null) {
				try {
					fos.flush();
					fos.close();
				} catch (IOException e) {
					throw new StorageException("Cannot close stream", e.getCause());
				}
			}
		}
	}

	@Override
	public void removeFile(String fileName) {
		File f = new File(getFullPath() + fileName);
		if (!f.delete()) {
			throw new StorageException("Cannot delete file: " + getFullPath()
					+ fileName);
		}
	}

	@Override
	public byte[] fileData(String fileName) {
		File f = new File(getFullPath() + fileName);
		byte[] out = new byte[(int) f.length()];
		
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(f);
			fis.read(out);
			fis.close();
		} catch (FileNotFoundException e) {
			throw new StorageException("File cannot be found: " + fileName, e.getCause());
		} catch (IOException e) {
			throw new StorageException("Cannot read file: " + fileName, e.getCause());
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					throw new StorageException("Cannot close stream", e.getCause());
				}
			}
		}
				
		return out;
	}

	@Override
	public File file(String fileName) {
		return new File(getFullPath() + fileName);
	}

	@Override
	public void moveFile(String source, String destination) {
		saveFile(new File(getFullPath() + source), destination);
	}

	@Override
	public void createDirectory(String dir) {
		File f = new File(getFullPath() + dir);
		if (!f.mkdir()) {
			throw new StorageException("Cannot create directory: "
					+ getFullPath() + dir);
		}
	}

	@Override
	public boolean dirExists(String path) {
		File f = new File(getFullPath() + path);
		return f.exists() && f.isDirectory();
	}

	@Override
	public String serverPath(String fileName) {
		return context.getRealPath(rootPath + File.separator + fileName);
	}

}
