/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.csl.navigation;


import java.awt.Image;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.text.Document;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.Modifier;
import org.netbeans.modules.csl.api.StructureItem;
import org.netbeans.modules.csl.core.GsfHtmlFormatter;
import org.netbeans.modules.csl.core.Language;
import org.netbeans.modules.csl.core.LanguageRegistry;
import org.netbeans.modules.csl.navigation.actions.OpenAction;
import org.netbeans.modules.csl.spi.ParserResult;
import org.openide.filesystems.FileObject;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;

/** 
 * This file is originally from Retouche, the Java Support 
 * infrastructure in NetBeans. I have modified the file as little
 * as possible to make merging Retouche fixes back as simple as
 * possible. 
 * <p>
 * GSF changes made: Instead of accessing fields on Description object,
 * replace references to Description with StructureItem interface (descriptions
 * supplied by language plugins), make method calls on this interface rather
 * than accessing fields directly. Some data such as the "ui" field was moved
 * into ElementNode itself rather than sitting on the description object which
 * is no longer under our control.
 * <p>
 * Node representing an element
 * 
 * 
 * @author Petr Hrebejk
 */
public class ElementNode extends AbstractNode {

    
    private static Node WAIT_NODE;
    
    private OpenAction openAction;
    private StructureItem description;
    private ClassMemberPanelUI ui;
    private final FileObject fileObject; // For the root description
           
    /** Creates a new instance of TreeNode */
    public ElementNode( StructureItem description, ClassMemberPanelUI ui, FileObject fileObject) {
        super(description.isLeaf() ? Children.LEAF: new ElementChildren(description, ui, fileObject), Lookups.fixed(fileObject));
        this.description = description;
        setDisplayName( description.getName() ); 
        this.ui = ui;
        this.fileObject = fileObject;
    }
    
    @Override
    public Image getIcon(int type) {
        if (description.getCustomIcon() != null) {
            return ImageUtilities.icon2Image(description.getCustomIcon());
        }
        Icon icon = Icons.getElementIcon(description.getKind(), description.getModifiers());
        if (icon != null) {
            return ImageUtilities.icon2Image(icon);
        } else {
            return super.getIcon(type);
        }
    }

    @Override
    public Image getOpenedIcon(int type) {
        return getIcon(type);
    }
                   
    @Override
    public java.lang.String getDisplayName() {
        if (description.getName() == null) {
            return fileObject.getNameExt();
        } else {
            return description.getName();
        }
    }
            
    @Override
    public String getHtmlDisplayName() {
        return description.getHtml(new NavigatorFormatter());
    }
    
    @Override
    public Action[] getActions( boolean context ) {
        
        if ( context || description.getName() == null ) {
            return ui.getActions();
        }
        else {
            Action panelActions[] = ui.getActions();
            
            Action actions[]  = new Action[ 2 + panelActions.length ];
            actions[0] = getOpenAction();
            actions[1] = null;
            for( int i = 0; i < panelActions.length; i++ ){
                actions[2 + i] = panelActions[i];
            }
            return actions;
        }
    }        
    
    @Override
    public Action getPreferredAction() {
        return getOpenAction();
    }
    
    
    private synchronized Action getOpenAction() {
        if ( openAction == null ) {
            FileObject fo = ui.getFileObject();
            try {
                openAction = new OpenAction(description.getElementHandle(), fo,
                        description.getPosition());
            } catch (UnsupportedOperationException uo) {
                return null; // root node does not have element handle
            }
        }
        return openAction;
    }
    
    static synchronized Node getWaitNode() {
        if ( WAIT_NODE == null ) {
            WAIT_NODE = new WaitNode();
        }
        return WAIT_NODE;
    }

    /**
     * Refreshes the Node recursively. Only initiates the refresh; the refresh
     * itself may happen asynchronously.
     */
    public void refreshRecursively() {
        List<Node> toExpand = new ArrayList<Node>();
        refreshRecursively(Collections.singleton(this), toExpand);
        ui.performExpansion(toExpand, Collections.<Node>emptyList());
    }

    private void refreshRecursively(Collection<ElementNode> toDo, final Collection<Node> toExpand) {
        for (ElementNode elnod : toDo) {
            final Children ch = elnod.getChildren();
            if ( ch instanceof ElementChildren ) {
                ((ElementChildren)ch).resetKeys((List<StructureItem>)elnod.description.getNestedItems(), elnod.ui.getFilters());

                Collection<ElementNode> children = (Collection<ElementNode>)(List)Arrays.asList((Node[])ch.getNodes());
                toExpand.addAll(children);
                refreshRecursively(children, toExpand);
            }
        }
    }

    public ElementNode getMimeRootNodeForOffset(ParserResult info, int offset) {
        if (getDescription().getPosition() > offset) {
            return null;
        }
        
        // Look up the current mime type
        Document document = info.getSnapshot().getSource().getDocument(false);
        if (document == null) {
            return null;
        }
        BaseDocument doc = (BaseDocument)document;
        return getMimeRootNodeForOffset(doc, offset);
    }
    
    ElementNode getMimeRootNodeForOffset(BaseDocument doc, int offset) {
        List<Language> languages = LanguageRegistry.getInstance().getEmbeddedLanguages(doc, offset);

        // Look specifically within the
        if (languages.size() > 0) {
            Children ch = getChildren();
            if ( ch instanceof ElementChildren ) {
                Node[] children = ch.getNodes();
                for (Language language : languages) {
                    // Inefficient linear search because the children may not be
                    // ordered according to the source
                    for (int i = 0; i < children.length; i++) {
                        ElementNode c = (ElementNode) children[i];
                        if (c.getDescription() instanceof ElementScanningTask.MimetypeRootNode) {
                            ElementScanningTask.MimetypeRootNode mr = (ElementScanningTask.MimetypeRootNode)c.getDescription();
                            if (mr.language == language) {
                                return c.getNodeForOffset(offset);
                            }
                        }
                    }
                }
            }
        }

        // No match in embedded languages - do normal offset search
        return getNodeForOffset(offset);
    }
    
    public ElementNode getNodeForOffset(int offset) {
        if (getDescription().getPosition() > offset) {
            return null;
        }

        // Inefficient linear search because the children may not be
        // ordered according to the source
        Children ch = getChildren();
        if ( ch instanceof ElementChildren ) {
            Node[] children = ch.getNodes();
            for (int i = 0; i < children.length; i++) {
                ElementNode c = (ElementNode) children[i];
                // The promise of the API is broken at several places in the
                // codebase and thus this needs to be guarded. The assert is in
                // place to find the violating places.
                assert c.getDescription().getElementHandle() != null;
                @SuppressWarnings("null")
                FileObject childFileObject = c.getDescription().getElementHandle() != null
                        ? c.getDescription().getElementHandle().getFileObject()
                        : null;
                if (! Objects.equals(this.getFileObject(), childFileObject)) {
                    // e.g. inherited items may be in another file
                    // in such a case, incorrect item is highlighted on the navigator window if the FileObjects are not checked
                    continue;
                }
                long start = c.getDescription().getPosition();
                if (start <= offset) {
                    long end = c.getDescription().getEndPosition();
                    if (end >= offset) {
                        return c.getNodeForOffset(offset);
                    }
                }
            }
        }

        return this;
    }

    public void updateRecursively( StructureItem newDescription ) {
           List<Node> nodesToExpand = new LinkedList<Node>();
           List<Node> nodesToExpandRec = new LinkedList<Node>();
           updateRecursively(newDescription, nodesToExpand, nodesToExpandRec);
           ui.performExpansion(nodesToExpand, nodesToExpandRec);
    }

    private void updateRecursively( StructureItem newDescription, List<Node> nodesToExpand, List<Node> nodesToExpandRec ) {
        Children ch = getChildren();

        //If a node that was a LEAF now has children the child type has to be changed from Children.LEAF
        //to ElementChildren to be able to hold the new child data
        if(!(ch instanceof ElementChildren) && newDescription.getNestedItems() != null && 
                newDescription.getNestedItems().size()>0) {
            ch=new ElementChildren(ui, fileObject);
            setChildren(ch);
        }
        
        if ( ch instanceof ElementChildren ) {           
           HashSet<StructureItem> oldSubs = new HashSet<StructureItem>( description.getNestedItems() );

           
           // Create a hashtable which maps StructureItem to node.
           // We will then identify the nodes by the description. The trick is 
           // that the new and old description are equal and have the same hashcode
           Node[] nodes = ch.getNodes( true );           
           HashMap<StructureItem,ElementNode> oldD2node = new HashMap<StructureItem,ElementNode>();           
           for (Node node : nodes) {
               oldD2node.put(((ElementNode)node).description, (ElementNode)node);
           }
           
           // Now refresh keys
           ((ElementChildren)ch).resetKeys((List<StructureItem>)newDescription.getNestedItems(), ui.getFilters());

           
           // Reread nodes
           nodes = ch.getNodes( true );

           boolean alreadyExpanded = false;
           
           for( StructureItem newSub : newDescription.getNestedItems() ) {
                ElementNode node = oldD2node.get(newSub);
                if ( node != null ) { // filtered out
                    if ( !oldSubs.contains(newSub)) {
                       nodesToExpand.add(node);
                    }
                    node.updateRecursively( newSub, nodesToExpand, nodesToExpandRec ); // update the node recursively
                } else { // a new node
                    if (! alreadyExpanded) {
                        alreadyExpanded = true;
                        if (ui.isExpandedByDefault(this)) {
                            nodesToExpand.add(this);
                        }
                    }
                    for (Node newNode : nodes) {
                        if (newNode instanceof ElementNode  &&  ((ElementNode) newNode).getDescription() == newSub) {
                            nodesToExpandRec.add(newNode);
                            break;
                        }
                    }
                }
           }
        }
                        
        StructureItem oldDescription = description; // Remember old description        
        description = newDescription; // set new descrioption to the new node
        String oldHtml = oldDescription.getHtml(new NavigatorFormatter());
        String descHtml = description.getHtml(new NavigatorFormatter());
        if ( oldHtml != null && !oldHtml.equals(descHtml)) {
            // Different headers => we need to fire displayname change
            fireDisplayNameChange(oldHtml, descHtml);
        }
        if( oldDescription.getModifiers() != null &&  !oldDescription.getModifiers().equals(newDescription.getModifiers())) {
            fireIconChange();
            fireOpenedIconChange();
        }
    }
    
    public StructureItem getDescription() {
        return description;
    }
    
    public FileObject getFileObject() {
        return fileObject;
    }
    
    private static final class ElementChildren extends Children.Keys<StructureItem> {
        private ClassMemberPanelUI ui;
        private FileObject fileObject;
        private StructureItem   parent;
        
        @Override
        protected void addNotify() {
            super.addNotify();
            if (parent != null) {
                resetKeys((List<StructureItem>)parent.getNestedItems(), ui.getFilters());
            }
        }
        
        public ElementChildren(ClassMemberPanelUI ui, FileObject fileObject) {
            this.ui = ui;
            this.fileObject = fileObject;
        }
        
        public ElementChildren(StructureItem parent, ClassMemberPanelUI ui, FileObject fileObject) {
            this.parent = parent;
            this.ui = ui;
            this.fileObject = fileObject;
        }
        
        protected Node[] createNodes(StructureItem key) {
            return new Node[] {new  ElementNode(key, ui, fileObject)};
        }
        
        void resetKeys( List<StructureItem> descriptions, ClassMemberFilters filters ) {            
            setKeys( filters.filter(descriptions) );
        }
    }
                       
    /** Stores all interesting data about given element.
     */    
    static class Description {
        
        public static final Comparator<StructureItem> ALPHA_COMPARATOR =
            new DescriptionComparator(true);
        public static final Comparator<StructureItem> POSITION_COMPARATOR = 
            new DescriptionComparator(false);    
        
        ClassMemberPanelUI ui;
                
        //FileObject fileObject; // For the root description
        
        String name;
        ElementHandle elementHandle;
        ElementKind kind;
        Set<Modifier> modifiers;        
        List<Description> subs; 
        String htmlHeader;
        long pos;
        
        Description( ClassMemberPanelUI ui ) {
            this.ui = ui;
        }
                                
        @Override
        public boolean equals(Object o) {
                        
            if ( o == null ) {
                //System.out.println("- f nul");
                return false;
            }
            
            if ( !(o instanceof Description)) {
                // System.out.println("- not a desc");
                return false;
            }
            
            Description d = (Description)o;
            
            if ( kind != d.kind ) {
                // System.out.println("- kind");
                return false;
            }
            
            // Findbugs warns about this field being uninitialized on the following line!
            if ( !name.equals(d.name) ) {
                // System.out.println("- name");
                return false;
            }

//            if ( !this.elementHandle.signatureEquals(d.elementHandle) ) {
//                return false;
//            }
            
            /*
            if ( !modifiers.equals(d.modifiers)) {
                // E.println("- modifiers");
                return false;
            }
            */
            
            // System.out.println("Equals called");            
            return true;
        }
        
        
        @Override
        public int hashCode() {
            int hash = 7;

            hash = 29 * hash + (this.name != null ? this.name.hashCode() : 0);
            hash = 29 * hash + (this.kind != null ? this.kind.hashCode() : 0);
            // hash = 29 * hash + (this.modifiers != null ? this.modifiers.hashCode() : 0);
            return hash;
        }

        private static class DescriptionComparator implements Comparator<StructureItem> {
            
            boolean alpha;
            
            DescriptionComparator( boolean alpha ) {
                this.alpha = alpha;
            }
            
            public int compare(StructureItem d1, StructureItem d2) {
                if ( alpha ) {
                    if ( k2i(d1.getKind()) != k2i(d2.getKind()) ) {
                        return k2i(d1.getKind()) - k2i(d2.getKind());
                    } 
                    
                    return d1.getSortText().compareTo(d2.getSortText());
                }
                else {
                    return d1.getPosition() == d2.getPosition() ? 0 : d1.getPosition() < d2.getPosition() ? -1 : 1;
                }
            }
            
            int k2i( ElementKind kind ) {
                switch( kind ) {
                    case CONSTRUCTOR:
                        return 1;
                    case METHOD:
                    case DB:
                        return 2;
                    case FIELD:
                        return 3;
                    case CLASS:
                    case INTERFACE:
//                    case ENUM:
//                    case ANNOTATION_TYPE:                        
//                        return 4;
                        
                        // TODO - what about other types?
                    default:
                        return 100;
                }
            }
        }
        
    }
        
    private static class WaitNode extends AbstractNode {
        
        private Image waitIcon = ImageUtilities.loadImage("org/netbeans/modules/csl/navigation/resources/wait.gif"); // NOI18N
        private String displayName;
        
        WaitNode( ) {
            super( Children.LEAF );
            displayName = NbBundle.getMessage(ElementNode.class, "LBL_WaitNode");
        }
        
        @Override
        public Image getIcon(int type) {
             return waitIcon;
        }

        @Override
        public Image getOpenedIcon(int type) {
            return getIcon(type);
        }

        @java.lang.Override
        public java.lang.String getDisplayName() {
            return displayName;
        }
    }
    
    private static class NavigatorFormatter extends GsfHtmlFormatter {
        @Override
        public void name(ElementKind kind, boolean start) {
            // No special formatting for names
        }
    }
}
