// $Id: PmiiTreeModel.java,v 1.15 2004/05/10 20:13:20 m31 Exp $
//
// This file is part of the program suite "Principia Mathematica II"
// which is a working prototype for the main project:
// "Hilbert II" - http://www.qedeq.org
//
// Copyright 2001-2004  Michael Meyling <mime@qedeq.org>.
//
// "Principia Mathematica II" is free software; you can redistribute
// it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

package com.meyling.principia.gui.jtree;


import java.util.HashMap;
import java.util.Map;

import javax.swing.event.TreeModelListener;
import javax.swing.tree.*;

import com.meyling.principia.log.Logger;
import com.meyling.principia.log.Trace;
import com.meyling.principia.module.ModuleEventListener;
import com.meyling.principia.module.ModuleProperties;


/**
 * Model for a JTree.
 *
 * A Model, which represents the underlying, logical structure of data in a
 * software application and the high-level class associated with it. The
 * object model does not contain any information about the user interface.
 *
 * @version $Revision: 1.15 $
 * @author  Michael Meyling
 */
public final class PmiiTreeModel extends DefaultTreeModel implements ModuleEventListener {

    /**
     * properties of modules
     */
    private final Map module2Path = new HashMap();



    public PmiiTreeModel(TreeNode root) {
        super(root);
    }


    /**
     * Creates tree model.
     */
    public PmiiTreeModel() {
        this(new PmiiTreeNode(new ModuleElement(), true));
/*
        final PmiiTreeNode axioms = new PmiiTreeNode(
            new ModuleElement("Axioms", "Module 4",
            ModuleElement.LIST));
        final PmiiTreeNode definitions = new PmiiTreeNode(
            new ModuleElement("Definitions", "Module 4",
            ModuleElement.LIST));
        final PmiiTreeNode identy = new PmiiTreeNode(
            new ModuleElement("Identy", "Axioms",
            ModuleElement.LIST));
        final PmiiTreeNode idem = new PmiiTreeNode(
            new ModuleElement("Idempotence", "Axioms",
            ModuleElement.LIST));
        final PmiiTreeNode com = new PmiiTreeNode(
            new ModuleElement("Commutativity", "Axioms",
            ModuleElement.LIST));
/
        root.insert(module1, 0);
        root.insert(module2, 1);
        root.insert(module3, 2);
        root.insert(module4, 3);
*/
//        module4.insert(axioms,0);
//        module4.insert(definitions,0);
//        axioms.insert(identy,0);
//        axioms.insert(idem,1);
//        axioms.insert(com,2);

//        this.setRoot(root);
    }

    /*  (non-Javadoc)
     * @see javax.swing.tree.TreeModel#addTreeModelListener(javax.swing.event.TreeModelListener)
     */
    public void addTreeModelListener(TreeModelListener listener) {
        Trace.trace(this, "addTreeModelListener", listener);
        super.addTreeModelListener(listener);
    }


    /* (non-Javadoc)
     * @see com.meyling.principia.module.ModuleListener#addModule(com.meyling.principia.module.ModuleProperties)
     */
    public void addModule(ModuleProperties prop) {
        Logger.getInstance().logMessageState("Module added. "  + prop.getStateDescription() 
            + ":", prop.getAddress());

        final PmiiTreeNode root = (PmiiTreeNode) this.getRoot();
        final PmiiTreeNode node = new PmiiTreeNode(prop, false);
        Trace.trace(this, "addModule", "calls insertNodeInto=" + node);
        module2Path.put(prop.getAddress(), new TreePath(node.getPath()));
        for (int i = 0; i < root.getChildCount(); i++) {
            final PmiiTreeNode n = (PmiiTreeNode) root.getChildAt(i);
            final ModuleProperties p = (ModuleProperties) n.getUserObject();
            if (p.getModuleAddress().getFileName().compareTo(prop.getModuleAddress().getFileName()) 
                    > 0) {
                this.insertNodeInto(node, root, i);
                return;
            }
        }
        this.insertNodeInto(node, root, root.getChildCount());
    }


    /* (non-Javadoc)
     * @see com.meyling.principia.module.ModuleListener#stateChanged(com.meyling.principia.module.ModuleProperties)
     */
    public void stateChanged(final ModuleProperties prop) {
        Logger.getInstance().logMessageState("Module state changed. "  + prop.getStateDescription() 
            + ":", prop.getAddress());
        final TreePath path = (TreePath) module2Path.get(prop.getAddress());
        if (path == null) {
            throw new IllegalArgumentException("unknown property");
        }
        final PmiiTreeNode node = (PmiiTreeNode) path.getLastPathComponent();
        ModuleProperties sameProp = (ModuleProperties)node.getUserObject();
        if (!prop.equals(sameProp)) {
            throw new IllegalStateException("should not happen");
        }
        Trace.trace(this, "stateChanged", "nodeChanged=" + node);
        this.nodeChanged(node);
    }


    /* (non-Javadoc)
     * @see com.meyling.principia.module.ModuleListener#addModule(com.meyling.principia.module.ModuleProperties)
     */
    public void removeModule(ModuleProperties prop) {
        Logger.getInstance().logMessageState("Module removed. "  + prop.getStateDescription() 
            + ":", prop.getAddress());
        final TreePath path = (TreePath) module2Path.get(prop.getAddress());
        if (path == null) {
            throw new IllegalArgumentException("unknown property");
        }
        final PmiiTreeNode node = (PmiiTreeNode) path.getLastPathComponent();
        ModuleProperties sameProp = (ModuleProperties)node.getUserObject();
        if (!prop.equals(sameProp)) {
            throw new IllegalStateException("should not happen");
        }
        module2Path.remove(prop.getAddress());
        Trace.trace(this, "removeModule", "nodeRemoved=" + node);
        this.removeNodeFromParent(node);
    }


    public TreePath getSelectionPath(final ModuleProperties prop) {
        final TreePath path = (TreePath) module2Path.get(prop.getAddress());
        if (path == null) {
            throw new IllegalArgumentException("unknown property");
        }
        final PmiiTreeNode node = (PmiiTreeNode) path.getLastPathComponent();
        ModuleProperties sameProp = (ModuleProperties)node.getUserObject();
        if (!prop.equals(sameProp)) {
            throw new IllegalStateException("should not happen");
        }
        return path;
    }


}
