/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.nplusc.izc.tools.UiToolz;

import de.nplusc.izc.tools.IOtools.DirectoryTreeNode;
import de.nplusc.izc.tools.baseTools.Tools;
import de.nplusc.izc.tools.baseTools.arraytools;
import java.util.ArrayList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

/**
 *
 * @author LH
 */
//kann als JTree-daten benutzt werden oder als Verzeichnisbrowser-Grundlage
public abstract class DirectoryTree implements TreeModel
{

    protected ArrayList<TreeModelListener> tml = new ArrayList<>();
    protected ArrayList<DirectoryTreeNode> directoryTree = new ArrayList<>();

    
    public abstract void insertDirectory(DirectoryTreeNode node);
    protected abstract void rebuildDatabase();
    public abstract void insertFile(DirectoryTreeNode node);
    public abstract String getRootPathValue();
    
    public void forceReload()
    {
        rebuildDatabase();
    }
    
    
    //muss wohl diese Scheisse erneut programmieren :(
    
    /**
     * GIbt den COntent des Pfades aus (entspricht dir
     * @param path Pfad... ohne ROot-Element (wird mit \ dargestellt)
     * @return Array mit Inhalt...
     */
    
    private String clearPathFromInvalidSt00f(String path)
    {
        return path.replaceAll(">>>", "");
    }
    
    
    public String[] getDirectoryContent(String path)
    {
        path = clearPathFromInvalidSt00f(path);
        DirectoryTreeNode[] content = new DirectoryTreeNode[]{new DirectoryTreeNode(0+"", 0+"","Fotze",true)};
        DirectoryTreeNode rn = (DirectoryTreeNode) getRoot();
        if(path.equals("\\"))//rootdetector
        {
            int cc = getChildCount(rn);
            content = new DirectoryTreeNode[cc];
            for (int i = 0; i < content.length; i++)
            {
                content[i] = (DirectoryTreeNode) getChild(rn, i);
            }
        }
        else
        {
            path=path.substring(1);
            
            DirectoryTreeNode currentNode = rn;//initialisiert den "Tree-Pointer" auf root
            String[] PathSplitted = path.split("\\\\");


            for (int i=0;i<PathSplitted.length;i++)
            {
                String pe = PathSplitted[i];
                int ct = getChildCount(currentNode);
                content = new DirectoryTreeNode[ct];
                //System.out.print("");//NOP
                //System.err.println(">>"+currentNode);
                for (int j = 0; j < content.length; j++)
                {
                    content[j] = (DirectoryTreeNode) getChild(currentNode, j);
                }
                //if(i<PathSplitted.length-1)
                //{
                    for (DirectoryTreeNode chk : content)
                    {
                        if((chk+"").equals(pe))
                        {
                            currentNode=chk;
                            break;//raus aus der schleife nin den nxxten lauf
                        }
                    }
                //}
            }
            int ct = getChildCount(currentNode);
            content = new DirectoryTreeNode[ct];
            //System.err.println("------------");
            //System.err.println(currentNode);
            //System.out.print("");//NOP
            for (int j = 0; j < content.length; j++)
            {
                content[j] = (DirectoryTreeNode) getChild(currentNode, j);
                
            }
        }
        String[] rtvl = new String[content.length];
        for (int i = 0; i < rtvl.length; i++)
        {
            if(content[i].isDirectory())
            {
                rtvl[i] = content[i]+">>>";
            }
            else
            {
            rtvl[i] = content[i]+"";
            }
            
        }
        
        
        
    return rtvl;//reimplementing...    
    // <editor-fold defaultstate="collapsed" desc="Fette altlast... Bugalert">       
      /*  String root = getRootPathValue().replaceAll("\\\\", "/");
        boolean sil = true;
        path = root+ path;
        path = path.replaceAll("\\\\", "/");
        path = path.replaceAll(root,"root");
        String[] spath = path.split("/");
        int apos = 1;//obwohl unlogisch gehts nicht mit  0....
        DirectoryTreeNode currentTreePosition = (DirectoryTreeNode) getRoot();
        DirectoryTreeNode temp = null;
        if (!path.equals("root/"))
        {
            while (sil)//intended :) muss ne rekursion umgehen da java gerne stackoverflowt.........
            {
                int cts = getChildCount(currentTreePosition);
                boolean nothingFound = true;
                for (int i = 0; i < cts; i++)
                {
                    temp = (DirectoryTreeNode) getChild(currentTreePosition, i);
                    System.err.println("######"+temp.toString()+"|"+spath[apos]+"|"+apos+"|"+spath.length);
                    if (temp.toString().equals(spath[apos]) && apos <= spath.length)
                    {
                        System.err.println(">"+spath[apos]);
                        currentTreePosition = temp;
                        if (apos < spath.length - 1)
                        {
                            apos++;
                        }
                        nothingFound = false;
                        break;
                    }
                    if (apos == spath.length - 1)
                    {
                        System.err.println(nothingFound);
                        sil = false;
                        break;
                    }
                }

                if (nothingFound)
                {
                    return null;
                }
            }
        }
        else
        {
            temp = (DirectoryTreeNode) getRoot();
        }
        int cc = getChildCount(temp);
        String[] rslt = new String[cc];
        for (int i = 0; i < cc; i++)
        {
            rslt[i] = getChild(temp, i).toString();
        }
        System.err.println("------");
        return rslt;
        
        </editor-fold> */
    }

    //public abstract void
    public void insertDirectory(String path)
    {
        
        path = clearPathFromInvalidSt00f(path);
        DirectoryTreeNode[] content = new DirectoryTreeNode[]{new DirectoryTreeNode(0+"", 0+"","Fotze",true)};
        DirectoryTreeNode rn = (DirectoryTreeNode) getRoot();
        if(!path.equals("\\"))//rootdetector
        {
            path=path.substring(1);
            //path=FileTK.getFilePath(path);
                    
            
            DirectoryTreeNode currentNode = rn;//initialisiert den "Tree-Pointer" auf root
            String[] PathSplitted = path.split("\\\\");


            for (int i=0;i<PathSplitted.length;i++)
            {
                String pe = PathSplitted[i];
                int ct = getChildCount(currentNode);
                content = new DirectoryTreeNode[ct];
                //System.out.print("");//NOP
                //System.err.println(">>"+currentNode);
                for (int j = 0; j < content.length; j++)
                {
                    content[j] = (DirectoryTreeNode) getChild(currentNode, j);
                }
                //if(i<PathSplitted.length-1)
                //{
                    for (DirectoryTreeNode chk : content)
                    {
                        if((chk+"").equals(pe))
                        {
                            currentNode=chk;
                            break;//raus aus der schleife nin den nxxten lauf
                        }
                    }
                //}
            }
            String pid = currentNode.getNodeID();
            insertDirectory(new DirectoryTreeNode(null, pid, PathSplitted[PathSplitted.length-1], true));
        }            
        
        /*
        path = clearPathFromInvalidSt00f(path);
        path = "root" + path;
        path = path.replaceAll("\\\\", "/");
        String[] spath = path.split("/");
        int apos = 1;
        DirectoryTreeNode currentTreePosition = (DirectoryTreeNode) getRoot();
        while (true)//intended :) muss ne rekursion umgehen da java gerne stackoverflowt.........
        {
            int cts = getChildCount(currentTreePosition);
            boolean nothingFound = true;
            for (int i = 0; i < cts; i++)
            {
                DirectoryTreeNode temp = (DirectoryTreeNode) getChild(currentTreePosition, i);
                if (temp.toString().equals(spath[i]))
                {
                    currentTreePosition = temp;
                    apos++;
                    nothingFound = false;
                    break;
                }
                if (apos == spath.length)
                {
                    insertDirectory(temp);
                    return;
                }
            }
            if (nothingFound)
            {
                return;
            }
        }
        */
    }

    public DirectoryTreeNode getNodeWithID(String ID)
    {
        for (DirectoryTreeNode dtn : directoryTree)
        {
            if(dtn.getNodeID().equals(ID))
                return dtn;
        }
        return null;
    }
    @Override
    public Object getRoot()
    {
        return directoryTree.get(0); //hardgecodet. muss in datenbank so sein
    }

    /**
     * Prüft ob der Node ein FIle ist
     *
     * @param path pfad ohne root vor dem ersten slash <<wie wenns auf ner
     * echten Platte wär(exampe: /path/to/file/or/directory wird zu
     * root/path/to/file/or/directory konvertiert)
     * @return true wenn file
     */
    public boolean nodeIsFile(String path)
    {
        path = clearPathFromInvalidSt00f(path);
        DirectoryTreeNode[] content = new DirectoryTreeNode[]{new DirectoryTreeNode(0+"", 0+"","Fotze",true)};
        DirectoryTreeNode rn = (DirectoryTreeNode) getRoot();
        if(path.equals("\\"))//rootdetector
        {
            return !rn.isDirectory();
        }
        else
        {
            path=path.substring(1);
            
            DirectoryTreeNode currentNode = rn;//initialisiert den "Tree-Pointer" auf root
            String[] PathSplitted = path.split("\\\\");


            for (int i=0;i<PathSplitted.length;i++)
            {
                String pe = PathSplitted[i];
                int ct = getChildCount(currentNode);
                content = new DirectoryTreeNode[ct];
                //System.out.print("");//NOP
                //System.err.println(">>"+currentNode);
                for (int j = 0; j < content.length; j++)
                {
                    content[j] = (DirectoryTreeNode) getChild(currentNode, j);
                }
                //if(i<PathSplitted.length-1)
                //{
                    for (DirectoryTreeNode chk : content)
                    {
                        if((chk+"").equals(pe))
                        {
                            currentNode=chk;
                            break;//raus aus der schleife nin den nxxten lauf
                        }
                    }
                //}
            }
            return !currentNode.isDirectory();
        }
        //<editor-fold defaultstate="collapsed" desc="Altlast">
        /**
        path = clearPathFromInvalidSt00f(path);
        path = "root" + path;
        path = path.replaceAll("\\\\", "/");
        String[] spath = path.split("/");
        int apos = 0;
        DirectoryTreeNode currentTreePosition = (DirectoryTreeNode) getRoot();

        while (true)//intended :) muss ne rekursion umgehen da java gerne stackoverflowt.........
        {
            int cts = getChildCount(currentTreePosition);
            boolean nothingFound = true;
            for (int i = 0; i < cts; i++)
            {
                DirectoryTreeNode temp = (DirectoryTreeNode) getChild(currentTreePosition, i);
                if (temp.toString().equals(spath[apos]) && apos < spath.length)
                {
                    currentTreePosition = temp;
                    apos++;
                    nothingFound = false;
                    break;
                }
                if (apos == spath.length)
                {
                    return !temp.isDirectory();
                }
            }
            if (nothingFound)
            {
                return false;
            }
        }*/
        //</editor-fold>
    }

    /**
     * Rotzt NodeID raus
     *
     * @param path pfad ohne root vor dem ersten slash <<wie wenns auf ner
     * echten Platte wär(exampe: /path/to/file/or/directory wird zu
     * root/path/to/file/or/directory konvertiert)
     * @return wert
     */
    public String getNodeID(String path)
    {
        path = clearPathFromInvalidSt00f(path);
        DirectoryTreeNode[] content = new DirectoryTreeNode[]{new DirectoryTreeNode(0+"", 0+"","Fotze",true)};
        DirectoryTreeNode rn = (DirectoryTreeNode) getRoot();
        if(path.equals("\\"))//rootdetector
        {
            System.err.println(rn.getNodeID());
            return rn.getNodeID();
            
        }
        else
        {
            path=path.substring(1);
            
            DirectoryTreeNode currentNode = rn;//initialisiert den "Tree-Pointer" auf root
            String[] PathSplitted = path.split("\\\\");


            for (int i=0;i<PathSplitted.length;i++)
            {
                String pe = PathSplitted[i];
                int ct = getChildCount(currentNode);
                content = new DirectoryTreeNode[ct];
                //System.out.print("");//NOP
                //System.err.println(">>"+currentNode);
                for (int j = 0; j < content.length; j++)
                {
                    content[j] = (DirectoryTreeNode) getChild(currentNode, j);
                }
                //if(i<PathSplitted.length-1)
                //{
                    for (DirectoryTreeNode chk : content)
                    {
                        if((chk+"").equals(pe))
                        {
                            currentNode=chk;
                            break;//raus aus der schleife nin den nxxten lauf
                        }
                    }
                //}
            }
            return currentNode.getNodeID();
        }
    }


    @Override
    public void addTreeModelListener(TreeModelListener l)
    {
        tml.add(l);
    }

    @Override
    public void removeTreeModelListener(TreeModelListener l)
    {
        tml.remove(l);
    }

    @Override
    public Object getChild(Object parent, int index)
    {
        ArrayList<DirectoryTreeNode> localList = getNodeList(parent);
        return localList.get(index);
    }

    private ArrayList<DirectoryTreeNode> getNodeList(Object parent)
    {
        ArrayList<DirectoryTreeNode> localList = new ArrayList<>();
        String parentID = ((DirectoryTreeNode) parent).getNodeID();
        for (DirectoryTreeNode tNode : directoryTree)
        {
            if (tNode.getParentID() != null && tNode.getParentID().equals(parentID) && !tNode.getNodeID().equals(tNode.getParentID()))
            {
                localList.add(tNode);
            }

        }
        return localList;
    }

    @Override
    public int getChildCount(Object parent)
    {
        ArrayList<DirectoryTreeNode> localList = getNodeList(parent);
        return localList.size();
    }

    @Override
    public boolean isLeaf(Object node)
    {
        return !((DirectoryTreeNode) node).isDirectory();
    }

    @Override
    public void valueForPathChanged(TreePath path, Object newValue)
    {
        //NotImplementedAndNotUsed
    }

    @Override
    public int getIndexOfChild(Object parent, Object child)
    {
        ArrayList<DirectoryTreeNode> localList = getNodeList(parent);
        return localList.indexOf(child);
    }

    public DirectoryTreeNode getSelectedNode(TreePath selp)
    {
        return (DirectoryTreeNode) selp.getLastPathComponent();
    }
    
        
    @SuppressWarnings("SleepWhileInLoop")
    public void updateTreeTo(DirectoryTreeNode node)
    {
        TreePath ptn = getPathToThis(node);
        
        
        TreeModelEvent tme = new TreeModelEvent(this, ptn);
        for (TreeModelListener tmll : tml)
        {
            tmll.treeNodesInserted(null);
            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException ex)
            {
                //Null
            }
        }
    }
    
    public synchronized TreePath getPathToThis(DirectoryTreeNode n)
    {
        DirectoryTreeNode root = (DirectoryTreeNode) getRoot(),currentTreePos=n;
        ArrayList<DirectoryTreeNode> revPath = new ArrayList<>();
        String pid = n.getParentID();
        revPath.add(currentTreePos);
        boolean sil=true;
        boolean foundNothing = true;
        
        while(sil)
        {
            for (int i=0;i<directoryTree.size();i++)//foreach=gift
            {
                DirectoryTreeNode ldtn = directoryTree.get(i);
                if(ldtn.getParentID()!=null)
                {
                    if(ldtn.getNodeID().equals(pid))
                    {
                        currentTreePos=ldtn;
                        Tools.DebugHelperPrint(ldtn+"|discov", true, "Toolkit.enableFinerDebug");
                        foundNothing=false;
                        revPath.add(currentTreePos);
                    }
                }
                else
                {
                   Tools.DebugHelperPrint("FARK", true, "Toolkit.enableFinerDebug");
                }
                
                if(foundNothing&&i==directoryTree.size()-1)
                {
                    return null;
                }
                if(!(currentTreePos.getNodeID().equals(root.getNodeID())))
                {
                    pid=currentTreePos.getParentID();
                    Tools.DebugHelperPrint(pid+"|"+currentTreePos+"|parentIDandCurrentTree", true, "Toolkit.enableFinerDebug");
                }
                else
                {
                    sil=false;
                    break;
                }
                
            }
        }
        Object[] path = arraytools.arrayReverse(revPath.toArray());
        return new TreePath(path);
    }
    
    
}
