/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in 
 * compliance with the License.  You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is Protege-2000.
 *
 * The Initial Developer of the Original Code is Stanford University. Portions
 * created by Stanford University are Copyright (C) 2007.  All Rights Reserved.
 *
 * Protege was developed by Stanford Medical Informatics
 * (http://www.smi.stanford.edu) at the Stanford University School of Medicine
 * with support from the National Library of Medicine, the National Science
 * Foundation, and the Defense Advanced Research Projects Agency.  Current
 * information about Protege can be obtained at http://protege.stanford.edu.
 *
 */

package edu.stanford.smi.protege.ui;

import java.util.*;

import edu.stanford.smi.protege.event.*;
import edu.stanford.smi.protege.model.*;
import edu.stanford.smi.protege.util.*;

/**
 * Tree root for the superslot-subslot relationship tree nodes.
 *
 * @author    Ray Fergerson <fergerson@smi.stanford.edu>
 */
public class SlotSubslotRoot extends LazyTreeRoot {
    private KnowledgeBase _knowledgeBase;

    private KnowledgeBaseListener _listener = new KnowledgeBaseAdapter() {
        public void slotCreated(KnowledgeBaseEvent event) {
        	if (event.isReplacementEvent()) return;
            super.slotCreated(event);
            Slot slot = event.getSlot();
            if (slot.getDirectSuperslots().isEmpty()) {
                List slots = (List) getUserObject();
                int index = 0;
                slots.add(index, slot);
                childAdded(slot, index);
                // This probably shouldn't be needed but is.  If the tree is empty and you add a node it doesn't
                // get displayed if you don't send the structure changed event.
                if (getChildCount() == 1) {
                    notifyNodeStructureChanged(SlotSubslotRoot.this);
                }
            }
        }

        public void slotDeleted(KnowledgeBaseEvent event) {
        	if (event.isReplacementEvent()) return;
            super.slotDeleted(event);
            Slot slot = event.getSlot();
            List slots = (List) getUserObject();
            boolean changed = slots.remove(slot);
            if (changed) {
                childRemoved(slot);
            }
        }
    };

    private SlotListener _slotListener = new SlotAdapter() {
        public void directSuperslotAdded(SlotEvent event) {
        	if (event.isReplacementEvent()) return;
            Slot slot = event.getSlot();
            if (slot.getDirectSuperslotCount() == 1) {
                removeChild(slot);
            }
        }

        public void directSuperslotRemoved(SlotEvent event) {
        	if (event.isReplacementEvent()) return;
            Slot slot = event.getSlot();
            if (slot.getDirectSuperslotCount() == 0) {
                addChild(slot);
            }
        }
    };

    private void removeChild(Slot slot) {
        List slots = (List) getUserObject();
        slots.remove(slot);
        childRemoved(slot);
    }

    private void addChild(Slot slot) {
        List slots = (List) getUserObject();
        slots.add(slot);
        childAdded(slot);
    }

    public SlotSubslotRoot(KnowledgeBase kb) {
    	this(kb, getSlots(kb));
    }
    
    public SlotSubslotRoot(KnowledgeBase kb, Collection slots) {
    	this(kb, slots, ApplicationProperties.getSortSlotTreeOption());
    }

    public SlotSubslotRoot(KnowledgeBase kb, Collection slots, boolean isSorted) {
        super(slots);
        kb.addKnowledgeBaseListener(_listener);
        kb.addSlotListener(_slotListener);
        _knowledgeBase = kb;
    }

    public LazyTreeNode createNode(Object o) {
        return new SlotSubslotNode(this, (Slot) o);
    }

    public void dispose() {
        super.dispose();
        _knowledgeBase.removeKnowledgeBaseListener(_listener);
        _knowledgeBase.removeSlotListener(_slotListener);
    }

    public Comparator getComparator() {
        return new LazyTreeNodeFrameComparator();
    }

    private static Collection getSlots(KnowledgeBase kb) {
        List results = new ArrayList(kb.getSlots());
        Iterator i = results.iterator();
        while (i.hasNext()) {
            Slot slot = (Slot) i.next();
            if (slot.getDirectSuperslotCount() > 0) {
                i.remove();
            }
        }
        
        if (ApplicationProperties.getSortSlotTreeOption()) {
        	Collections.sort(results, new FrameComparator());
        }
        return results;
    }
}
