/**
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 *
 * Copyright (C)
 * <a href="http://www.inab.org">Spanish National Institute of Bioinformatics (INB)</a>
 * <a href="http://www.bsc.es">Barcelona Supercomputing Center (BSC)</a>
 * <a href="http://inb.bsc.es">Computational Node 6</a>
 */

package org.inb.biomoby.central.gui.model;

import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.inb.biomoby.central.model.ModelListener;
import org.inb.biomoby.central.model.ServicesModel;
import org.inb.biomoby.shared.registry.Service;

/**
 * TreeModel that contains Service elements.
 * The model implements an Service ModelListener to automatically synchronize with ServicesModel singleton model
 *
 * @author Dmitry Repchevsky
 */

public class ServicesTreeModel extends DefaultTreeModel implements ModelListener<Service>
{
    public ServicesTreeModel()
    {
        super(new DefaultMutableTreeNode(""));
        
        ServicesModel.instance().addListener(this);
    }

    @Override
    public DefaultMutableTreeNode getRoot()
    {
        return (DefaultMutableTreeNode)super.getRoot();
    }

    private void addService(Service service)
    {
        AbstractEntityTreeNode node = new AbstractEntityTreeNode(service);
        
        String authURI = service.getAuthURI();
        
        for (int i = 0, n = root.getChildCount(); i < n; i++)
        {
            DefaultMutableTreeNode parent = (DefaultMutableTreeNode)root.getChildAt(i);
            
            String authority = parent.toString();
            
            if (authority.equals(authURI))
            {
                int index = 0;
                for(int z = parent.getChildCount(); index < z; index++)
                {
                    DefaultMutableTreeNode child = (DefaultMutableTreeNode)parent.getChildAt(index);
                    Service srv = (Service)child.getUserObject();

                    if (service.compareTo(srv) < 0)
                    {
                        break;
                    }
                }

                insertNodeInto(node, parent, index);

                return;
            }
        }
        
        // not found the authority...
        
        DefaultMutableTreeNode parent = new DefaultMutableTreeNode(authURI);
        parent.add(node);
        getRoot().add(parent);

        nodeStructureChanged(root);
    }

    @Override
    public void modelCleared()
    {
        getRoot().removeAllChildren();

        if (SwingUtilities.isEventDispatchThread())
        {
            nodeStructureChanged(root);
        }
        else
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    nodeStructureChanged(root);
                }
            });
        }
    }

    @Override
    public void modelObjectInserted(final Service service)
    {
        if (SwingUtilities.isEventDispatchThread())
        {
            addService(service);
        }
        else
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    addService(service);
                }
            });
        }
    }
    @Override public void modelObjectRemoved(Service service) {}
    @Override public void modelObjectChanged(Service service1, Service service2) {}
}
