package zall.bean;

import java.io.File;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;

import zutil.db.DBConnection;
import zutil.db.bean.DBBean;
import zutil.db.bean.DBBeanSQLResultHandler;
import zutil.db.bean.DBBean.*;
import zutil.log.LogUtil;

import zall.Zallery;

@DBTable("Folder")
public class Folder extends DBBean{
	private static final Logger logger = LogUtil.getLogger();

	protected transient String name;
	protected User user;
	protected String path;
	protected Folder parent;
	protected Timestamp date;
	protected boolean isPrivate;

	//@DBLinkTable(name="FolderTree", beanClass=Folder.class, idColumn="parent")
	//protected LinkedList<Folder> subFolders;


	public static Folder load(DBConnection db, Long id) throws SQLException{
		return load(db, Folder.class, id);
	}
	public static List<Folder> loadSubFolders(DBConnection db, Long id, User user) throws SQLException{
		PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE parent=? AND (isPrivate=0 OR user=? OR ?)");
		sql.setLong(1, id);
		sql.setLong(2, user.getId());
		sql.setBoolean(3, user.isSuperUser());
		return DBConnection.exec(sql, DBBeanSQLResultHandler.createList(Folder.class, db));
	}
	
	public static Folder loadRoot(DBConnection db, User user) throws SQLException{
		PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE path=? AND (isPrivate=0 OR user=? OR ?)");
		sql.setString(1, "/");
		sql.setLong(2, user.getId());
		sql.setBoolean(3, user.isSuperUser());
		return DBConnection.exec(sql, DBBeanSQLResultHandler.create(Folder.class, db));
	}
	
	public static Folder load(DBConnection db, String path, User user) throws SQLException{
		PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE path=? AND user=?");
		sql.setString(1, path);
		sql.setLong(2, user.getId());
		return DBConnection.exec(sql, DBBeanSQLResultHandler.create(Folder.class, db));
	}

	public static List<Folder> load(DBConnection db, User user) throws SQLException{
		if( user.getId() == null )
			return new LinkedList<Folder>();
		PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE user=?");
		sql.setLong(1, user.getId() );
		return DBConnection.exec(sql, DBBeanSQLResultHandler.createList(Folder.class, db));
	}

	public Folder(){
		//subFolders = new LinkedList<Folder>();
		date = new Timestamp( System.currentTimeMillis() );
	}

	public String getName(){
		if(name == null){
			String[] tmp = path.split("/");
			name = tmp[tmp.length-1];
		}
		String userName = user != null ? user.getName() : "UNKNOWN";
		String tmp = name.replaceAll("\\{NAME\\}", userName);
		return tmp;
	}
	public String getUnModName(){
		if(name == null)
			getName();
		return name;
	}
	public User getUser(){
		return user;
	}
	public void setUser(User user){
		this.user = user;
	}
	public boolean isPrivate(){
		return isPrivate;
	}
	public void setPrivate(boolean priv){
		this.isPrivate = priv;
	}
	public String getPath(){
		String tmp = path.replaceAll("\\{NAME\\}", user.getName());
		return tmp;
	}
	public String getUnModPath(){
		return path;
	}
	public void setName(String name){
		this.name = name;
		if( parent.path.endsWith("/") )
			this.path = parent.path+name;
		else
			this.path = parent.path+"/"+name;
	}
	public void setParent(Folder parent){
		if( this.parent != parent ){
			this.parent = parent;
			//parent.addSubFolder( this );
			if( parent.path.endsWith("/") )
				this.path = parent.path+name;
			else
				this.path = parent.path+"/"+name;
		}
	}
	public Folder getParent(){
		return parent;
	}

	/*public void addSubFolder(Folder f){
		if( !subFolders.contains(f) ){
			subFolders.add( f );
			f.setParent( this );
		}
	}*/

	/*public List<Folder> getSubFolders(){
		return subFolders;
	}*/

	public Timestamp getDate(){
		return date;
	}

	/**
	 * @param		filename		is the name of the file
	 * @param		size			specifies the size of the image
	 * @return 						a File object that points to the physical file on the disk, 
	 * 									or null if the user or the filename is null
	 */
	public File getFile(String filename, Image.Size size){
		// Zallery not initialized.
		while( Zallery.DATA_PATH.isEmpty() ){
			logger.warning("Zallery not initialized or DATA_PATH not set!");
			return null;
		}
		
		if( user == null || filename == null )
			return null;
		StringBuilder tmp = new StringBuilder();
		
		// Get the Root path of the given size
		tmp.append( Zallery.DATA_PATH );
		if( tmp.charAt(tmp.length()-1) != File.separatorChar )
			tmp.append( File.separatorChar );		
		tmp.append( size.toString() );
		if( path.charAt(0) != '/' )
			tmp.append( File.separatorChar );
		
		// Add UserID and this folders path
		String tmp_path = path.replaceAll("\\{NAME\\}", ""+user.getId());
		tmp_path = tmp_path.replaceAll("/", Matcher.quoteReplacement(File.separator));
		tmp.append( tmp_path );
		
		// check if folder exists or else create it
		File folder = new File(tmp.toString());
		if( !folder.exists() )
			if( !folder.mkdirs() ){
				logger.warning("Unable to create new folders: '"+folder+"'");
				throw new RuntimeException("Unable to create new folders: '"+folder+"'");
			}
		
		// Add the filename
		if( tmp.charAt(tmp.length()-1) != File.separatorChar )
			tmp.append( File.separatorChar );
		tmp.append(filename);
		
		logger.finest( "File path: "+tmp.toString() );
		return new File(tmp.toString());
	}

	public static Folder genRoot(){
		Folder root = new Folder();
		root.parent = null;
		root.path = "/";
		return root;
	}
	
	public boolean isEmpty(DBConnection db) throws SQLException {
		return Folder.loadSubFolders(db, this.getId(), user).isEmpty() && Media.load(db, this).isEmpty();
	}
}
