package smart_gs.logical;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.dnd.DragSource;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import smart_gs.GSConstants;
import smart_gs.drawing_tool.view.View;
import smart_gs.logical.filter.ImageFileDirFilterForSpreadTree;
import smart_gs.logical.region.BookmarkRegion;
import smart_gs.logical.visitor.CreateXMLElementVisitor;
import smart_gs.reasoning_web.logical.LinkRemover;
import smart_gs.smleditor.swingui.GSEditor;
import smart_gs.spread_selection.IndexChangeTable;
import smart_gs.swingui.WorkspaceWindow;
import smart_gs.util.CanonicalPathString;
import smart_gs.util.GSPathStringGrammarChecker;
import smart_gs.util.GSStandardPath;
import smart_gs.util.StringUtils;
import smart_gs.logical.Preference;

@SuppressWarnings("serial")
public class SpreadTreeForLineSegEditor extends JTree  {

	private JTree jtree;
	private List<Spread> registeredSpreads;
	private List<SpreadDirectory> registeredSpreadDirectories;
	private TreePath[] selectedPaths;
	private SpreadTree spreadTree;
	

	// 2007/10/10 kazuhiro kobayashi
	/*
	 * 外部のファイルにあるimageとtextを設定するために変更
	 */
	private static String IMAGE_FOLDER_PATH_STRING;
	private static String DSC_FOLDER_PATH_STRING;
	private static File IMAGE_FOLDER_PATH;
	private static File DSC_FOLDER_PATH;
	private SpreadDirectory root;
	private DefaultMutableTreeNode rootNode;

	// ADD NorthGrid
	private static final String NAME = "SpreadTree for LineSeg Editor";
	private static final DataFlavor localObjectFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME);
	private static final DataFlavor[] supportedFlavors = { localObjectFlavor };

	protected DragSource dragSource;
	protected DropTarget dropTarget;
	TreeNode dropTargetNode = null;
	TreeNode draggedNode = null;
	TreePath dragsourceTreePath = null;

	protected HashMap<String,String>  allowImageMap = new HashMap<String, String>();

	public SpreadTreeForLineSegEditor() {
		super(SpreadTree.getInstance().getModel());
	};
	
	public SpreadTreeForLineSegEditor(Spread spread) {
		super(SpreadTree.getInstance().getModel());
		this.expandPath(SpreadTree.getInstance().getSelectedPath());
		this.setSelectionPath(SpreadTree.getInstance().getSelectedPath());
	};

	public List<File> getDSCFiles() {
		List<File> files = new ArrayList<File>();
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			if (this.registeredSpreads.get(i).hasDscFile()) {
				files.add(this.registeredSpreads.get(i).getDscFile());
			}
		}
		return files;
	}

	public void loadAllImages() {
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			if (this.registeredSpreads.get(i).hasDscFile()) {
				this.registeredSpreads.get(i).loadImage();

			}

		}
	}

	public List<Spread> getSpreads() {
		return this.registeredSpreads;
	}

	public void registerSpread(Spread spread) {
		this.registeredSpreads.add(spread);
	}

	public List<Spread> getDSCSpreads() {
		List<Spread> results = new ArrayList<Spread>();
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			if (this.registeredSpreads.get(i).hasDscFile()) {
				results.add(this.registeredSpreads.get(i));
			}
		}
		return results;
	}
	
//	2011.03.13 shayashi
	public TreePath[] getSelectedPaths() {
		return this.getSelectionModel().getSelectionPaths();
	}
	
	public SpreadDirectory getRootSpreadDirectory(){
		return root;
	}

	public boolean isRegistered(File file) {
		for (int i = 0; i < this.registeredSpreadDirectories.size(); i++) {
			if (this.registeredSpreadDirectories.get(i).getFile().equals(file)) {
				return true;
			}
		}
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			if (this.registeredSpreads.get(i).getFile().equals(file)) {
				return true;
			}
		}
		return false;
	}

	//	public boolean isRegustedTree(File file){
	//		for(Enumeration e = rootNode.children(); e.hasMoreElements();){
	//			DefaultMutableTreeNode child = (DefaultMutableTreeNode)e.nextElement();
	//			GSResource r = (GSResource)child.getUserObject();
	//			if( r instanceof SpreadDirectory) {
	//				SpreadDirectory d = (SpreadDirectory)r ;
	//				if( d.getFile().equals(file) ){
	//					return child;
	//				}
	//			} 
	//		}		
	//	}

	public SpreadDirectory getCurrentDirectory() {
		TreePath path = this.getSelectionModel().getSelectionPath();
		if (path == null) {
			return (SpreadDirectory) ((DefaultMutableTreeNode) this.getModel()
					.getRoot()).getUserObject();
		}
		Object selectedObject = ((DefaultMutableTreeNode) path
				.getLastPathComponent()).getUserObject();
		while (!(selectedObject instanceof SpreadDirectory)) {
			path = path.getParentPath();
			selectedObject = ((DefaultMutableTreeNode) path
					.getLastPathComponent()).getUserObject();
		}
		return (SpreadDirectory) selectedObject;
	}

	public DefaultMutableTreeNode getSelectedNode() {
		TreePath path = this.getSelectionModel().getSelectionPath();
		if (path == null) {
			return this.rootNode;
		}
		return (DefaultMutableTreeNode) path.getLastPathComponent();
	}

	public boolean isImage(File file){
		String fileName = file.getName();
		int index = fileName.lastIndexOf('.');
		if (index >= 0) { //拡張子がある場合
			String ext = fileName.substring(index + 1);
			if(allowImageMap.containsKey(ext.toLowerCase())){
				return true;
			}
		}
		return false;
	}
	
    // Register SpreadDirectories, Spreads. (Adding them to the  variables: resource, spreads, directories.)
	private void loadImages(SpreadDirectory parent,boolean sort) {
		File[] files = parent.getFile().listFiles(new ImageFileDirFilterForSpreadTree());
		if(sort){
			Arrays.sort(files, new SpreadFileComparator()); 
		}
		for (int i = 0; i < files.length; i++) {
			File file = files[i];

			if (file.isDirectory()) {
				if (this.isRegistered(file)) {
					SpreadDirectory directory = this.getDirectory(file);
					this.loadImages(directory,sort);
				} else {
					SpreadDirectory directory = new SpreadDirectory(parent,
							file.getName(), file);
					this.registeredSpreadDirectories.add(directory);
					parent.addResource(directory);
					this.loadImages(directory,sort);
				}
			} else if (!this.isRegistered(file)) {
				if(isImage(file)){
					Spread spread = new Spread(parent, file);
					parent.addResource(spread);
					this.registeredSpreads.add(spread);
				}
			}
		}
	}

	private SpreadDirectory getDirectory(File file) {
		for (int i = 0; i < this.registeredSpreadDirectories.size(); i++) {
			if (this.registeredSpreadDirectories.get(i).getFile().equals(file)) {
				return this.registeredSpreadDirectories.get(i);
			}
		}
		return null;
	}
	
//2011.03.16 shayashi deleted
//	public static void main(String[] args) {
//		SpreadTree.getInstance();
//	}

	public void updateModel() {
		this.root.setTree(this.rootNode);
		((DefaultTreeModel) this.getModel()).setRoot(rootNode);
		((DefaultTreeModel) this.getModel()).reload();
	}

	public DefaultMutableTreeNode getRootNode(){
		return rootNode;
	}

//	public void restore(Element element) {
//		NodeList list = element.getElementsByTagName("directory");
//		if (list.getLength() < 1) {
//			System.out.println("list error");
//			return;
//		}
//		Element rootElement = (Element) list.item(0);
//		this.registeredSpreads.clear();
//		this.registeredSpreadDirectories.clear();
//		// 2007/10/22 kazuhiro kobayashi
//		Spread.resetIndex();
//		this.rootNode.removeAllChildren();
//		String imageFolderPath = Preference.getInstance().getImageFolderPathString();
//		String name = rootElement.getAttribute("name");
//		String uri = rootElement.getAttribute("uri");
//		String originalURI = rootElement.getAttribute(GSResource.ORIGINAL_URI);
//		String version = rootElement.getAttribute(GSResource.VERSION);
//		File filepath = new File(imageFolderPath);
//		this.root = new SpreadDirectory("root",filepath,uri,originalURI,version);
//		this.root.setVersion(version);
//		this.root.setName(name);
//		this.rootNode.setUserObject(this.root);
//		this.root.restore(rootElement,filepath);
//		registeredSpreads = root.getSpreads();
//		registeredSpreadDirectories = root.getSpreadDirectorys();
//		//		this.loadImages(this.root,false);
//		this.updateModel();
//		//
//		/*
//		 * 20080912 shimizu edited
//		if (!NAME_CORRESPONDENCE_FILE_PATH.equals("")) {
//			this.setNameCorrespondence();
//		}
//		 */
//	}

//	public void save(Document document, Element parent) {
//		Element element = document.createElement("spreadTree");
//		parent.appendChild(element);
//		CreateXMLElementVisitor visitor = new CreateXMLElementVisitor(document);
//		this.root.accept(visitor);
//		element.appendChild(visitor.getLastElement());
//	}

	public void registerSpreadDirectory(SpreadDirectory directory) {
		this.registeredSpreadDirectories.add(directory);
	}

	public Spread getSpreadByResourceURI(String uri) {
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			if (extractSpreadURI(uri).equals(URICreator.getURIWithoutHeader(registeredSpreads.get(i)))
					|| extractSpreadURI(uri).equals(registeredSpreads.get(i).getOriginalURI().substring(GSConstants.URI_HEADER.length()))
					|| uri.equals(this.registeredSpreads.get(i).getURI()))
			{
				return registeredSpreads.get(i);
			}
		}
		return null;
	}
	private Object extractSpreadURI(String uri) {
		return uri.substring(uri.indexOf(URICreator.SEP2 + URICreator.SPREAD)+1);
	}
	public Spread getSpreadByURI(String uri) {
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			if (registeredSpreads.get(i).getURI().equals(uri)){
				return registeredSpreads.get(i);
			}
		}
		return null;
	}


	/**
	 * 正規化されかつ含まれている文字列から取得.
	 * @param uri
	 * @return
	 */
	public Spread getSpreadByURI2(String uri) {
		for (int i = 0; i < this.registeredSpreads.size(); i++) {
			String srcurl = registeredSpreads.get(i).getURI();
			srcurl = GSStandardPath.toStandardOnCurrentOS(srcurl);
			if (srcurl.indexOf(uri) != -1) {
				return registeredSpreads.get(i);
			}
		}
		return null;
	}
	
	
	
	
	public void export(Writer writer) throws IOException{}
	// ADD NorthGrid 以下D&Dイベント
	/**
	 * ドラッグ＆ドロップ操作が完了.
	 * @param dsde
	 */
	public void dragDropEnd(DragSourceDropEvent dsde) {
		dropTargetNode = null;
		draggedNode = null;
		dragsourceTreePath = null;
		// 再表示
		WorkspaceWindow.setUpdated(true);
		repaint();
	}
	/**
	 * カーソルのホットスポットがプラットフォーム依存のドロップサイトに入力された.
	 * @param dsde
	 */
	public void dragEnter(DragSourceDragEvent dsde) {
		dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
	}
	/**
	 * カーソルのホットスポットがプラットフォーム依存のドロップサイトを終了したとき.
	 * @param dse
	 */
	public void dragExit(DragSourceEvent dse) {
		dse.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
	}


	private boolean areSelectedPathsInSameNode(TreePath[] selectedPaths2) {
		if (selectedPaths != null){
			int size = selectedPaths.length;
			if (size != 0){
				DefaultMutableTreeNode parentOfFirstSelectedNode = 
					(DefaultMutableTreeNode) selectedPaths[0].getParentPath().getLastPathComponent();
				for (int i = 1; i<size;i++){
					DefaultMutableTreeNode parentOfSelectedNode = 
						(DefaultMutableTreeNode) selectedPaths[i].getParentPath().getLastPathComponent();
					if (!parentOfSelectedNode.equals(parentOfFirstSelectedNode)){
						return false;
					}
				}
			}
		}
		return true;
	}

	/**
	 * 
	 * データ変換クラス.
	 * アプリ以外からのドラックをチェックする.
	 */
	class SpreadTreeTransferable implements Transferable {
		Object object;
		public SpreadTreeTransferable(Object o) {
			object = o;
		}
		//@Override
		public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException {
			if(isDataFlavorSupported(df)) {
				return object;
			}else{
				throw new UnsupportedFlavorException(df);
			}
		}
		//@Override
		public boolean isDataFlavorSupported(DataFlavor df) {
			return (df.getHumanPresentableName().equals(NAME));
		}
		//@Override
		public DataFlavor[] getTransferDataFlavors() {
			return supportedFlavors;
		}
	}
	/**
	 * 
	 * Rendererクラス
	 * D&D中の操作をラインを付加して表示する.
	 *
	 */
	class SpreadTreeCellRenderer
	extends DefaultTreeCellRenderer {
		boolean isTargetNode;
		boolean isTargetNodeLeaf;
		boolean isLastItem;
		Insets normalInsets, lastItemInsets;
		int BOTTOM_PAD = 30;
		public SpreadTreeCellRenderer() {
			super();
			normalInsets = super.getInsets();
			lastItemInsets =
				new Insets(normalInsets.top,
						normalInsets.left,
						normalInsets.bottom + BOTTOM_PAD,
						normalInsets.right);
		}
		public Component getTreeCellRendererComponent(JTree tree,
				Object value,
				boolean isSelected,
				boolean isExpanded,
				boolean isLeaf,
				int row,
				boolean hasFocus) {
			isTargetNode = (value == dropTargetNode);
			isTargetNodeLeaf = (isTargetNode &&
					((TreeNode)value).isLeaf());
			// isLastItem = (index == list.getModel().getSize()-1);
			boolean showSelected = isSelected & (dropTargetNode == null);
			DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer)super.getTreeCellRendererComponent(tree, value, isSelected, isExpanded,isLeaf, row, hasFocus);
			if(value != null){
				if(value instanceof DefaultMutableTreeNode){
					DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)value;
					Object obj = defaultMutableTreeNode.getUserObject();
					if(obj != null){
						if(obj instanceof SpreadDirectory){
							Icon icon = renderer.getOpenIcon();
							renderer.setIcon(icon);
						}
					}
				}
			}
			return renderer;

		}

//		2011.03.16 shayashi changed: moving items always underlined
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (isTargetNode) {
				g.setColor(Color.black);
				g.drawLine(0, 0, getSize().width, 0);
			}
		}
	}

	class SpreadFileComparator implements Comparator<File>{

		public int compare(File o1, File o2) {
			return o1.compareTo(o2);
		}
	}

	//　This generates an IndexChangeTable
	class 	AutomaticNumbering {
		private int counter = 0;
		int ict_max = Spread.getCurrentMaxPageIndex();
		IndexChangeTable ict = new IndexChangeTable(ict_max);

		private void exec(DefaultMutableTreeNode parentNode){
			Enumeration<DefaultMutableTreeNode> enumeration = parentNode.children();
			while(enumeration.hasMoreElements()){
				DefaultMutableTreeNode childrenNode = enumeration.nextElement();
				String childrenStr = childrenNode.toString();
				if(childrenNode.getUserObject() instanceof Spread){
					// shayashi 20101003 making index-map point2/2points (A)
					Spread spread = (Spread)childrenNode.getUserObject();
					if (counter <= ict_max) ict.set(spread.getPageViewIndex(), counter);
					spread.setPageViewIndex(counter);
					counter++;
				} else if(childrenNode.getUserObject() instanceof SpreadDirectory){
					exec(childrenNode);
				}
			}
			WorkspaceWindow.setUpdated(true);
		}

		public void execAndAdjustSpreadSelectionLists(DefaultMutableTreeNode rootNode){
			exec(rootNode);
			SpreadSelectionListManager.getInstance().adjustSpreadSelctionLists(ict);
		}
	}



	//	public Spread getSpreadByIndex (Integer index){ return getSpreads().get(2); }
	public Spread getSpreadByIndex (Integer index){
		List<Spread> toseek = getSpreads();
		Spread result = null;
		for (int i = toseek.size() - 1; i >= 0; i--) {
			if ( toseek.get(i).getPageIndex()== index ) {
				result = toseek.get(i);
			}
		}
		return result;
	}
	
	public List<GSResource> getBookmarks() {
		ArrayList<GSResource> bookmarks = new ArrayList<GSResource>();
		for (Spread spread:this.registeredSpreads) {
			for (Region region:spread.getRegions()) {
				if (region.getView().getType() == View.BOOKMARK) {
					bookmarks.add((BookmarkRegion)region);
				}
			}
		}
		return bookmarks;		
	}
	

	public void sortSelectedItemsByName() {
		DefaultTreeModel model = (DefaultTreeModel) this.getModel();
		selectedPaths = null;
		selectedPaths = getSelectedPaths();
		int size = selectedPaths.length;
		if (size == 0) return;
//		2011.03.28 shaysahi: checking if all the selected items are in the same directory.
		if (! areSelectedPathsInSameNode(selectedPaths)){
			JOptionPane.showMessageDialog(jtree, "Items must be in the same directory");
			return;
		}
		DefaultMutableTreeNode parentNode = 
			(DefaultMutableTreeNode) selectedPaths[0].getParentPath().getLastPathComponent();
		List<GSResource> resources = ((SpreadDirectory)parentNode.getUserObject()).getResources();
		
//		get all selected items' indexes, sort them, and its smallest, which is insertionPointIndex.
		int[] indexes = new int[size];
		for (int i=0;i<size;i++) {
			indexes[i] = parentNode.getIndex((DefaultMutableTreeNode) selectedPaths[i].getLastPathComponent());				
		}
		Arrays.sort(indexes);
		for (int i=0;i<size-1;i++) {
			if (indexes[i+1] > indexes[i]+1){
				JOptionPane.showMessageDialog(jtree, "Items must be consective:"+indexes[i]+","+indexes[i+1]+"\n");
				return;
			}
		}
		int insertionPointIndex = indexes[0];
		
//		Two buffers
		MutableTreeNode[] tmpForJTree = new MutableTreeNode[size];
		GSResource[] tmpForSpreadTree = new GSResource[size];
//		copy selected nodes to tmpForTree/tmpForSpreadTree buffers, and sort them.
		for (int i=0;i<size;i++){
			MutableTreeNode selectedNode = (MutableTreeNode)selectedPaths[i].getLastPathComponent();
			tmpForJTree[i] = selectedNode;
			tmpForSpreadTree[i] = resources.get(model.getIndexOfChild(parentNode, selectedNode));
		};
		size = size;
		Arrays.sort(tmpForJTree,new DefaultMutableTreeNodeNameComparator());
		Arrays.sort(tmpForSpreadTree,new GSResourceNameComparator());
		
		//		remove selected items from the children of parentNode and resource.
		for (int i=size-1;i>=0;i--){
			parentNode.remove(insertionPointIndex+i);
			resources.remove(insertionPointIndex+i);
		}

//		for debug 2011.03.23 shayashi
//		System.out.printf("insertPointIndex:%d\n",insertionPointIndex);
//		int bound = model.getChildCount(selectedPaths[0].getParentPath().getLastPathComponent());
//		for (int i = 0; i<bound;i++) System.out.printf("%d:%s\n", i,model.getChild(selectedPaths[0].getParentPath().getLastPathComponent(),i));
//		System.out.printf("%d\n",insertionPointIndex);
		//			insert items of two buffers to JTree and Spread/SpreadDirectory graph-tree.
		for (int i=size-1;i>=0;i--){
			resources.add(insertionPointIndex,tmpForSpreadTree[i]);
			model.insertNodeInto(tmpForJTree[i], parentNode ,insertionPointIndex);
		}
//		finally set the new SpreadDirectory
		((SpreadDirectory)parentNode.getUserObject()).setResources(resources);
		
//		renumbering and redraw
		new AutomaticNumbering().execAndAdjustSpreadSelectionLists(this.rootNode);
		WorkspaceWindow.setUpdated(true);
		updateUI();
		repaint();
	}

	
//	Making or adding Spreads, SpreadDirectories.
	
	// Make a node&SpreadDirectory under the parent pair of parentTreeNode&parentSpreadDir with the name "name".
	// It returns the "node" made. If the given name is already used in the parent node, it returns null.
	// If the OS directory does not exist, it is created.
	
	
	public DefaultMutableTreeNode makeNewSpreadDirectory(DefaultMutableTreeNode parentTreeNode,String name){
		return makeNewSpreadDirectory(parentTreeNode, name, false);
	}
	
	public DefaultMutableTreeNode makeNewSpreadDirectoryImportMode(DefaultMutableTreeNode parentTreeNode,String name){
		return makeNewSpreadDirectory(parentTreeNode, name, true);
	}
	
	public DefaultMutableTreeNode makeNewSpreadDirectory(DefaultMutableTreeNode parentTreeNode,String name, boolean importMode){
		if (!GSPathStringGrammarChecker.isFileDirIdentifier(name)) {
			JOptionPane.showMessageDialog(null, String.format("Error: name %s cannot be used in SMART-GS.",name));
			return null;
		}
		if ( name.equals(".") || name.equals("..")) {
			JOptionPane.showMessageDialog(null, String.format("Error: name %s is not allowed to avoid confusion.",name));
			return null;
		}
		if ( name.equals("DscLocation")) {
			JOptionPane.showMessageDialog(null, String.format("Error: name %s is used by SMART-GS system, and so cannot be used.",name));
			return null;
		}
		

		Enumeration<DefaultMutableTreeNode> enm = parentTreeNode.children();
		while (enm.hasMoreElements()){
			DefaultMutableTreeNode nextNode = enm.nextElement();
			GSResource rsrc = (GSResource)nextNode.getUserObject();
			String tmp = rsrc.getName();
			if (tmp.equalsIgnoreCase(name)) {
				JOptionPane.showMessageDialog(null, 
						String.format("Error: new directory   %s   cannot be made, since name   %s   already exists in %s\nRemark: name equality check is case-senseless for Windows File Systems",
								name, tmp, makePathString(parentTreeNode.getPath())));
				return null;
			}
		}


		SpreadDirectory parentSpreadDir = (SpreadDirectory) parentTreeNode.getUserObject();

		if (!importMode) {
			String[] children = parentSpreadDir.getFile().list();
			for (int i=0;i<children.length;i++) {
				String tmp = children[i];
				if (tmp.equalsIgnoreCase(name)) {
					JOptionPane.showMessageDialog(null, 
							String.format("Error: new directory   %s   cannot be made, since name   %s   already exists in the file system %s. Consider to import it\nRemark: name equality check is case-senseless for Windows File Systems",
									name, tmp, parentSpreadDir.getFile().getPath()));
					return null;
				}
			}
		}
		
		
		File newDir = new File(parentSpreadDir.getFile(),name);
		
		if (!newDir.exists()) {
			boolean check = newDir.mkdir();
			if (!check) {
				System.out.printf("Error: directory %s could not be made.\n", CanonicalPathString.get(newDir));
				return null;
			}
			File newDscDir = new File(newDir,"dsc");
			check = newDscDir.mkdir();
			if (!check) {
				System.out.printf("Error: dsc directory %s could not be made.\n", CanonicalPathString.get(newDscDir));
				return null;
			}
		}
		SpreadDirectory directory = new SpreadDirectory(parentSpreadDir,name, newDir);
		this.registeredSpreadDirectories.add(directory);
		parentSpreadDir.addResource(directory);
		DefaultMutableTreeNode directoryNode = new DefaultMutableTreeNode(directory);
		parentTreeNode.add(directoryNode);
		this.updateUI();
		repaint();
		return directoryNode;
	}

	public static String makePathString(TreeNode[] array_path) {
		StringBuffer tmp = new StringBuffer();
		int size = array_path.length;
		for (int i=0; i<size;i++){
			tmp.append("/");
			tmp.append(array_path[i]);
		}
		return tmp.toString();
	}

	public void clear() {
		this.registeredSpreads.clear();
		this.registeredSpreadDirectories.clear();
		this.rootNode.removeAllChildren();
		this.root.clear();

		this.updateUI();
		this.repaint();
	}
	
	//	End of SpreadTree Class
}
