package usda.weru.util.tree;

import de.schlichtherle.truezip.file.TFile;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import javax.swing.ProgressMonitor;
import javax.swing.tree.MutableTreeNode;
import usda.weru.util.Caster;

public abstract class WepsTreeNode extends AbstractLazyLoadingTreeNode implements WepsTreeNodeIf {

    private static final long serialVersionUID = 1L;

    protected String displayName;

    protected HashMap<String, WepsTreeNode> childrenCache;
    private boolean createdChildren;

    public WepsTreeNode() {
        displayName = null;
        childrenCache = new HashMap<>();

        // calling this checks AND sets / intialize the flag variable
        getAllowsChildren();
    }

    protected synchronized void initChildren() {
        if (!createdChildren) {
            refreshChildren();
        }
    }

    @Override
    public void refreshChildren() {
        if (getAllowsChildren()) {
            if (createdChildren) {
                removeAllChildren();
            }

            MutableTreeNode[] newchildren = loadChildren();
            for (MutableTreeNode child : newchildren) {
                if (child instanceof WepsTreeNode) {
                    ((WepsTreeNode) child).refreshChildren();
                }
                insert(child, children != null ? children.size() : 0);
            }

            createdChildren = true;

            //keep the cache clean.
            Enumeration<Object> e = Caster.<Enumeration<Object>>cast(children());
            while (e.hasMoreElements()) {
                Object o = e.nextElement();
                if (!childrenCache.containsValue(o)) {
                    childrenCache.values().remove(o);
                }
            }
        }
    }

    protected void childCachePut(String key, WepsTreeNode val) {
        childrenCache.put(key, val);
    }

    protected WepsTreeNode childCacheGet(String key) {
        return childrenCache.get(key);
    }

    public WepsTreeNode[] getChildren() {
        WepsTreeNode[] temp = new WepsTreeNode[getChildCount()];
        for (int i = 0; i < getChildCount(); i++) {
            temp[i] = (WepsTreeNode) getChildAt(i);
        }
        return temp;
    }

    @Override
    protected WepsTreeNode[] createChildren() {
        createdChildren = true;
        return null;
    }

    @Override
    public abstract boolean updateSubtree();

    @Override
    public int getChildCount() {
// MEH, leave for later in LazyLoading process
//        initChildren();
        return super.getChildCount();
    }

    @Override
    public abstract boolean getAllowsChildren();

    public abstract TFile getNodeData() throws IOException;

    // obviously: need to override to activate...
    public TFile getNodeData(ProgressMonitor progress) throws IOException {
        return getNodeData();
    }

    @Override
    public abstract Object getUserObject();

    @Override
    public boolean isLeaf() {
        return !getAllowsChildren();
    }

    @Override
    public String getDisplayName() {
        return displayName;
    }

    @Override
    public void setDisplayName(String name) {
        displayName = name;
    }

    @Override
    public String toString() {
        if (displayName != null) {
            return displayName;
        } else {
            return super.toString();
        }
    }
}