// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.vdl;

import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.NavigationItem;
import com.intellij.psi.PsiElement;
import io.v.vdl.psi.*;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class VdlStructureViewElement implements StructureViewTreeElement {
    private PsiElement element;

    public VdlStructureViewElement(PsiElement element) {
        this.element = element;
    }

    @Override
    public Object getValue() {
        return element;
    }

    @Override
    public void navigate(boolean requestFocus) {
        if (element instanceof NavigationItem) {
            ((NavigationItem) element).navigate(requestFocus);
        }
    }

    @Override
    public boolean canNavigate() {
        return element instanceof NavigationItem && ((NavigationItem) element).canNavigate();
    }

    @Override
    public boolean canNavigateToSource() {
        return element instanceof NavigationItem && ((NavigationItem) element).canNavigateToSource();
    }

    @NotNull
    @Override
    public ItemPresentation getPresentation() {
        return element instanceof NavigationItem ? ((NavigationItem) element).getPresentation() : null;
    }

    @NotNull
    @Override
    public TreeElement[] getChildren() {
        List<TreeElement> result = new ArrayList<TreeElement>();

        if (element instanceof VdlFile) {
            for (VdlTypeSpec typeSpec : ((VdlFile) element).getTypes()) {
                result.add(new VdlStructureViewElement(typeSpec));
            }
        } else if (element instanceof VdlTypeSpec) {
            VdlType type = ((VdlTypeSpec) element).getSpecType().getType();
            if (type instanceof VdlInterfaceType) {
                for (VdlMethodSpec spec : ((VdlInterfaceType)type).getMethodSpecList()) {
                    result.add(new VdlStructureViewElement(spec));
                }
            } else if (type instanceof VdlStructOrUnionType) {
                for (VdlFieldDeclaration decl : ((VdlStructOrUnionType) type).getFieldDeclarationList()) {
                    for (VdlFieldDefinition defn : decl.getFieldDefinitionList()) {
                        result.add(new VdlStructureViewElement(defn));
                    }
                }
            }
        }
        return result.toArray(new TreeElement[result.size()]);
    }
}

@@ -500,16 +500,81 @@
 otNull;%0A
+import org.jetbrains.annotations.Nullable;%0A%0Aimport javax.swing.*;
 %0Aimport 
@@ -1481,38 +1481,96 @@
 ion() %7B%0A        
-return
+ItemPresentation result = null;%0A        if (element.isValid() &&
  element instanc
@@ -1591,10 +1591,32 @@
 Item
- ?
+) %7B%0A            result =
  ((N
@@ -1660,15 +1660,608 @@
 on()
- : null
+;%0A        %7D%0A%0A        if (result == null) %7B%0A            result = new ItemPresentation() %7B%0A                @Nullable%0A                @Override%0A                public String getPresentableText() %7B%0A                    return null;%0A                %7D%0A%0A                @Nullable%0A                @Override%0A                public String getLocationString() %7B%0A                    return null;%0A                %7D%0A%0A                @Nullable%0A                @Override%0A                public Icon getIcon(boolean b) %7B%0A                    return null;%0A                %7D%0A            %7D;%0A        %7D%0A        return result
 ;%0A  

fix crashes in structure view