package frame.file.repositoty;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import frame.data.DataPool;
import frame.data.Entity;
import frame.expression.Expression;
import frame.expression.GlobalVariant;
import frame.expression.VariantContext;
import frame.expression.VariantRequestParams;
import frame.expression.VariantSegment;
import frame.file.UploadResult;
import frame.upload.FileItem;
import frame.util.Util;


public class Repository {

	private String name;
	private String root;
	private Expression pathRule;
	private DataPool datapool;
	
	
	public Repository(String name, String root) throws Exception {
		this.name = name;
		this.root = parsePath(root);
	}
	
	public void setPath(String path) throws Exception {
		pathRule = new Expression(path);
	}
	
	public OutputStream getStream(String id) throws Exception {
		Entity entity = DataHandler.getLine("filerepository", id);
		
		if (entity == null) {
			throw new Exception("file not exists: " + id);
		}
		
		String internalPath = entity.getString("path");
		String path = Util.joinPath(root, internalPath);
		
		File file = new File(path);
		
		if (!file.exists()) {
			throw new Exception("file not exists: " + path);
		}
		
		return new FileOutputStream(file);
	}
	
	public String saveFileToAttachmentPath(List<FileItem> fileList, VariantRequestParams params) throws Exception {
		List<UploadResult> result = new ArrayList<UploadResult>();
		
		Expression expression = pathRule.newInstance();
		VariantContext context = new VariantContext();
		context.setParametersTo(expression, params);
		
		String internalPath = expression.getString();
		String path = Util.joinPath(root, internalPath);
		
		File pathfile = new File(path);
		if (!pathfile.exists()) {
			pathfile.mkdirs();
		}
		
		String code = Util.newShortGUID();
		
		for (FileItem item: fileList) {
			UploadResult uploadResult = doSaveOneFile(path, internalPath, code, item);
			result.add(uploadResult);
		}
		
		return path;
	}
	
	public List<UploadResult> saveFile(List<FileItem> fileList, VariantRequestParams params) throws Exception {
		List<UploadResult> result = new ArrayList<UploadResult>();
		
		Expression expression = pathRule.newInstance();
		VariantContext context = new VariantContext();
		context.setParametersTo(expression, params);
		
		String internalPath = expression.getString();
		String path = Util.joinPath(root, internalPath);
		
		File pathfile = new File(path);
		if (!pathfile.exists()) {
			pathfile.mkdirs();
		}
		
		String code = Util.newShortGUID();
		
		for (FileItem item: fileList) {
			UploadResult uploadResult = doSaveOneFile(path, internalPath, code, item);
			result.add(uploadResult);
		}
		
		return result;
	}
	
	public UploadResult saveFile(FileItem item) throws Exception {
		//1. path
		Expression expression = pathRule.newInstance();
		String internalPath = expression.toString();
		
		String path = Util.joinPath(root, internalPath);
		
		File pathfile = new File(path);
		if (!pathfile.exists()) {
			pathfile.mkdirs();
		}
		
		String code = Util.newShortGUID();
		
		UploadResult uploadResult = doSaveOneFile(path, internalPath, code, item);
		
		return uploadResult;
	}
	
	private UploadResult doSaveOneFile(String path, String internalPath, String filecode, FileItem item) throws Exception {
		String itemName = item.getName().subString(item.getName().lastIndexOf("\\") == -1 ? 0 : item.getName().lastIndexOf("\\") + 1);
		
		String internalFile = Util.joinPath(internalPath, itemName);
		File file = new File(root, internalFile);
		
		if (file.exists()) {
			file.delete();
		}
			
		file.createNewFile();
		item.write(file);
		
/*		Entity entity = new Entity("filerepository");
		entity.set("id", Util.newShortGUID());
		entity.set("typecode", "file");
		entity.set("filecode", filecode);
		entity.set("path", internalFile);
		entity.insert();*/
		
		UploadResult result = new UploadResult(filecode);
		//TODO uploadresult changed
		
		//result.setPath(path);
		//result.setTempPath(path);
		
		//TODO  event bus?
		EventListener.fireRepositoryEvent("aftersave", result, datapool);
		
		return result;
	}

	private String parsePath(String value) throws Exception {
		Expression expression = new Expression(value);
		
		for (VariantSegment variant: expression) {
			String name = variant.getName();
			int pos = value.indexOf("(");
			
			if (pos > 0) {
				String realname = name.subString(0, pos);
				String format = name.subString(pos + 1, name.length() - 1);
				
				VariantRequestParams params = new VariantRequestParams();
				params.addParam("format", format);
				
				GlobalVariant.getStringValue(realname, params);
			}
			else {
				GlobalVariant.getStringValue(name, null);
			}
		}
		
		return expression.toString();
	}

	public String getName() {
		return name;
	}

	public String getRoot() {
		return root;
	}

}