package filemanager;

import com.classpath.util.Characters;
import com.one.IntStack;
import com.one.ModuleRegistry;
import com.vmx.AuxClass;
import javax.microedition.lcdui.Image;
import java.util.Vector;

public class FileItem
{
	public static final int COMPARE_NAME = 1;
	public static final int COMPARE_TYPE = 2;
	public static final int COMPARE_LAST_MODIFIED = 3;
	public static final int COMPARE_SIZE = 4;
	
	protected String path;
	protected String name;
	protected String fullname;
	protected String dispname;
	protected Image icon;
	protected boolean readonly;
	protected boolean hidden;
	
	protected String type;
	protected long lastmod;
	protected long size;
	protected boolean lmexact;
	protected boolean szexact;

	protected String fullnamelc;
	protected String namelc;
	protected String typelc;
	
	protected boolean dir;
	protected boolean marked;
	protected boolean exact;
	protected boolean special;
	
	public FileItem(String fullname, boolean dispfullname)
	{
		this.fullname = fullname;
		
		int index = fullname.substring(0, fullname.length() - 1).lastIndexOf('/') + 1;
		
		path = fullname.substring(0, index);
		name = fullname.substring(index);
		
		init(dispfullname);
	}
	
	public FileItem(String path, String name, boolean dispfullname)
	{
		this.path = path;
		this.name = name;

		fullname = path + name;
		
		init(dispfullname);
	}

	protected void init(boolean dispfullname)
	{
		if(dispfullname)
		{
			dispname = fullname;
		}
		else
		{
			dispname = name;
		}

		readonly = false;
		hidden = false;

		type = AuxClass.getFileExtension(name);

		fullnamelc = Characters.toLowerCase(fullname);
		namelc = Characters.toLowerCase(name);
		typelc = Characters.toLowerCase(type);

		lastmod = -1;
		size = -1;
		lmexact = false;
		szexact = false;

		dir = false;
		marked = false;
		exact = false;
		special = false;
	}
	
	public FileItem(String name, Image icon)
	{
		this.name = name;
		this.icon = icon;
		
		path = "";
		readonly = false;
		hidden = false;
		
		type = "";

		fullname = name;
		dispname = name;
		
		namelc = Characters.toLowerCase(name);
		typelc = Characters.toLowerCase(type);

		fullnamelc = namelc;
		
		lastmod = -1;
		size = -1;
		lmexact = false;
		szexact = false;
		
		dir = true;
		marked = false;
		exact = true;
		special = true;
	}
	
	public String getPath()
	{
		return path;
	}
	
	public String getName()
	{
		return name;
	}
	
	public String getFullName()
	{
		return fullname;
	}

	public String getDisplayName()
	{
		return dispname;
	}
	
	public String getType()
	{
		return type;
	}
	
	public Image getIcon()
	{
		if(!exact)
		{
			updateFileType();
		}
		
		return icon;
	}
	
	public boolean isReadOnly()
	{
		if(!exact)
		{
			updateFileType();
		}
		
		return readonly;
	}
	
	public boolean isHidden()
	{
		if(!exact)
		{
			updateFileType();
		}
		
		return hidden;
	}
	
	public boolean isDirectory()
	{
		if(!exact)
		{
			updateFileType();
		}
		
		return dir;
	}
	
	public long getLastModified()
	{
		if(!lmexact && !special)
		{
			lastmod = filesystem.lastModified(getFullName());
			lmexact = true;
		}
		
		return lastmod;
	}
	
	public long getSize()
	{
		if(!szexact && !special)
		{
			size = filesystem.getSize(getFullName(), true);
			szexact = true;
		}
		
		return size;
	}
	
	public boolean isMarked()
	{
		return marked;
	}
	
	public void setMarked(boolean marked)
	{
		if(special)
		{
			return;
		}
		
		this.marked = marked;
	}
	
	public boolean isSpecial()
	{
		return special;
	}
	
	public void updateFileType()
	{
		if(special)
		{
			return;
		}
		
		String file = fullname;
		
		if(options.checkFileAttrib)
		{
			readonly = filesystem.isReadOnly(file);
			hidden = filesystem.isHidden(file);
		}
		
		if(dir = filesystem.isDir(file))
		{
			if(options.checkFileAttrib && filesystem.isHidden(file))
			{
				icon = images.getIcon(images.iHiddenFolder);
			}
			else
			{
				icon = images.getIcon(images.iFolder);
			}
		}
		else
		{
			icon = ModuleRegistry.getIcon(type);

			if(icon == null)
			{
				icon = images.getIcon(images.iFile);
			}
		}
		
		exact = true;
	}

	public void invalidate()
	{
		exact = false;
	}

	public String getFullNameLowerCase()
	{
		return fullnamelc;
	}
	
	public String getNameLowerCase()
	{
		return namelc;
	}
	
	public String getTypeLowerCase()
	{
		return typelc;
	}
	
	public int compareTo(FileItem item, int param, boolean ignorecase, boolean order)
	{
		if(!exact)
		{
			updateFileType();
		}
		
		if(dir)
		{
			if(!item.isDirectory())
			{
				return -1;
			}
		}
		else
		{
			if(item.isDirectory())
			{
				return 1;
			}
		}

		int res = 0;
		
		if(order)
		{
			if(param == COMPARE_NAME)
			{
				if(ignorecase)
				{
					return namelc.compareTo(item.getNameLowerCase());
				}
				else
				{
					return name.compareTo(item.getName());
				}
			}
			else if(param == COMPARE_TYPE)
			{
				if(ignorecase)
				{
					res = typelc.compareTo(item.getTypeLowerCase());
				}
				else
				{
					res = type.compareTo(item.getType());
				}
			}
			else if(param == COMPARE_LAST_MODIFIED)
			{
				res = (int)(getLastModified() - item.getLastModified());
			}
			else if(param == COMPARE_SIZE)
			{
				res = (int)(getSize() - item.getSize());
			}

			if(res == 0)
			{
				if(ignorecase)
				{
					return namelc.compareTo(item.getNameLowerCase());
				}
				else
				{
					return name.compareTo(item.getName());
				}
			}
		}
		else
		{
			if(param == COMPARE_NAME)
			{
				if(ignorecase)
				{
					return item.getNameLowerCase().compareTo(namelc);
				}
				else
				{
					return item.getName().compareTo(name);
				}
			}
			else if(param == COMPARE_TYPE)
			{
				if(ignorecase)
				{
					res = item.getTypeLowerCase().compareTo(typelc);
				}
				else
				{
					res = item.getType().compareTo(type);
				}
			}
			else if(param == COMPARE_LAST_MODIFIED)
			{
				res = (int)(item.getLastModified() - getLastModified());
			}
			else if(param == COMPARE_SIZE)
			{
				res = (int)(item.getSize() - getSize());
			}

			if(res == 0)
			{
				if(ignorecase)
				{
					return namelc.compareTo(item.getNameLowerCase());
				}
				else
				{
					return name.compareTo(item.getName());
				}
			}
		}
		
		return res;
	}
	
	protected static IntStack lbstack = new IntStack();
	protected static IntStack ubstack = new IntStack();

	public static void sortFileList(Vector files, int param, boolean ignorecase, boolean order, int first, int last)
	{
		if(first == last || first < 0 || last < 0 || first >= files.size() || last >= files.size())
		{
			return;
		}

		int i, j;
		int lb, ub;

		int ppos;
		FileItem pivot;
		Object temp;

		lbstack.clear();
		ubstack.clear();

		lbstack.push(first);
		ubstack.push(last);

		do
		{
			lb = lbstack.pop();
			ub = ubstack.pop();

			do
			{
				ppos = (lb + ub) >>> 1;

				i = lb;
				j = ub;

				pivot = (FileItem)files.elementAt(ppos);

				do
				{
					while(((FileItem)files.elementAt(i)).compareTo(pivot, param, ignorecase, order) < 0) i++;
					while(((FileItem)files.elementAt(j)).compareTo(pivot, param, ignorecase, order) > 0) j--;

					if(i <= j)
					{
						temp = files.elementAt(i);
						files.setElementAt(files.elementAt(j), i);
						files.setElementAt(temp, j);

						i++;
						j--;
					}
				}
				while(i <= j);

				if(i < ppos)
				{
					if(i < ub)
					{
						lbstack.push(i);
						ubstack.push(ub);
					}

					ub = j;
				}
				else
				{
					if(j > lb)
					{
						lbstack.push(lb);
						ubstack.push(j);
					}

					lb = i;
				}
			}
			while(lb < ub);
		}
		while(!lbstack.empty());
	}

	/*
	public static void sortFileList(Vector files, int param, boolean ignorecase, boolean order, int first, int last)
	{
		if(first < 0 || last < 0 || first >= files.size() || last >= files.size())
		{
			return;
		}

		FileItem p = (FileItem)files.elementAt((last - first) / 2 + first);

		Object temp;

		int i = first;
		int j = last;

		while(i <= j)
		{
			while(((FileItem)files.elementAt(i)).compareTo(p, param, ignorecase, order) < 0 && i++ < last);
			while(((FileItem)files.elementAt(j)).compareTo(p, param, ignorecase, order) > 0 && j-- > first);

			if(i <= j)
			{
				temp = files.elementAt(i);
				files.setElementAt(files.elementAt(j), i);
				files.setElementAt(temp, j);

				i++;
				j--;
			}
		}

		if(j > first)
		{
			sortFileList(files, param, ignorecase, order, first, j);
		}

		if(i < last)
		{
			sortFileList(files, param, ignorecase, order, i, last);
		}
	}
	*/
}
