/*
 * 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.refactoring.java;

import com.sun.source.tree.*;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.swing.Icon;
import javax.swing.text.Position.Bias;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.TreeUtilities;
import org.netbeans.modules.refactoring.java.plugins.JavaWhereUsedQueryPlugin;
import org.netbeans.modules.refactoring.java.spi.JavaWhereUsedFilters;
import org.netbeans.modules.refactoring.java.spi.JavaWhereUsedFilters.ReadWrite;
import org.netbeans.modules.refactoring.java.ui.UIUtilities;
import org.netbeans.modules.refactoring.java.ui.WhereUsedPanel;
import org.netbeans.modules.refactoring.java.ui.tree.ElementGripFactory;
import org.netbeans.modules.refactoring.spi.FiltersManager;
import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
import org.openide.ErrorManager;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.CloneableEditorSupport;
import org.openide.text.PositionBounds;
import org.openide.text.PositionRef;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import static org.netbeans.modules.refactoring.java.Bundle.*;

@NbBundle.Messages({"WARN_ElementNotFound=The destination was not found."})
public class WhereUsedElement extends SimpleRefactoringElementImplementation implements FiltersManager.Filterable {
    private final PositionBounds bounds;
    private final String htmlText;
    private final String elementText;
    private final FileObject parentFile;
    private final JavaWhereUsedFilters.ReadWrite access;
    private final boolean inComment;
    private final boolean inImport;
    private final boolean inPlatform;
    private final boolean inDependency;
    private final boolean inTestclass;

    public WhereUsedElement(PositionBounds bounds, String htmlText, String elementText, FileObject parentFile, TreePath tp, CompilationInfo info, ReadWrite access, boolean inTestclass, boolean inPlatform, boolean inDependency, boolean inComment, boolean inImport) {
        this.bounds = bounds;
        this.htmlText = htmlText;
        this.elementText = elementText;
        this.parentFile = parentFile;
        if (tp != null) {
            ElementGripFactory.getDefault().put(parentFile, tp, info);
        }
        ElementGripFactory.getDefault().put(parentFile, inTestclass);
        this.access = access;
        this.inTestclass = inTestclass;
        this.inPlatform = inPlatform;
        this.inDependency = inDependency;
        this.inComment = inComment;
        this.inImport = inImport;
    }

    @Override
    public String getDisplayText() {
        return htmlText;
    }

    @Override
    public Lookup getLookup() {
        Object composite = null;
        if(bounds != null) {
            composite = ElementGripFactory.getDefault().get(parentFile, bounds.getBegin().getOffset());
        }
        if (composite==null) {
            composite = parentFile;
        }
        Icon icon = null;
        if(access != null) {
            switch(access) {
                case WRITE:
                    icon = ImageUtilities.loadImageIcon("org/netbeans/modules/refactoring/java/resources/found_item_write.png", false);
                    break;
                case READ_WRITE:
                    icon = ImageUtilities.loadImageIcon("org/netbeans/modules/refactoring/java/resources/found_item_readwrite.png", false);
                    break;
                default:
                case READ:
                    icon = ImageUtilities.loadImageIcon("org/netbeans/modules/refactoring/java/resources/found_item_read.png", false);
                    break;
            }
        } else if(inComment) {
            icon = ImageUtilities.loadImageIcon("org/netbeans/modules/refactoring/java/resources/found_item_comment.png", false);
        } else if(inImport) {
            icon = ImageUtilities.loadImageIcon("org/netbeans/modules/refactoring/java/resources/found_item_import.png", false);
        }
        return icon != null ? Lookups.fixed(composite, icon) : Lookups.singleton(composite);
    }

    @Override
    public PositionBounds getPosition() {
        return bounds;
    }

    @Override
    public String getText() {
        return elementText;
    }

    @Override
    public void performChange() {
    }

    @Override
    public void openInEditor() {
        if(parentFile == null || !parentFile.isValid()) {
             StatusDisplayer.getDefault().setStatusText(WARN_ElementNotFound());
        } else {
            super.openInEditor();
        }
    }

    @Override
    public FileObject getParentFile() {
        return parentFile;
    }

    public JavaWhereUsedFilters.ReadWrite getAccess() {
        return access;
    }
    
    public static WhereUsedElement create(CompilationInfo compiler, TreePath tree, boolean inTest) {
        return create(compiler, tree, inTest, false, false);
    }
    
    public static WhereUsedElement create(CompilationInfo compiler, TreePath tree, boolean inTest, boolean inPlatform, boolean inDependency) {
        return create(compiler, tree, null, inTest, inPlatform, inDependency, new AtomicBoolean());
    }
    
    public static WhereUsedElement create(CompilationInfo compiler, TreePath tree, boolean inTest, boolean inPlatform, boolean inDependency, AtomicBoolean inImport) {
        return create(compiler, tree, null, inTest, inPlatform, inDependency, inImport);
    }
    
    public static WhereUsedElement create(CompilationInfo compiler, TreePath tree, JavaWhereUsedFilters.ReadWrite access, boolean inTest, boolean inPlatform, boolean inDependency, AtomicBoolean inImport) {
        CompilationUnitTree unit = tree.getCompilationUnit();
        CharSequence content = compiler.getSnapshot().getText();
        SourcePositions sp = compiler.getTrees().getSourcePositions();
        Tree t= tree.getLeaf();
        int start;
        int end;
        boolean anonClassNameBug128074 = false;
        TreeUtilities treeUtils = compiler.getTreeUtilities();

        if (t.getKind() == Tree.Kind.IDENTIFIER
                && "super".contentEquals(((IdentifierTree) t).getName()) // NOI18N
                && treeUtils.isSynthetic(tree)) {
            // in case of synthetic constructor call find real constructor or class declaration
            tree = getEnclosingTree(tree);
            if (treeUtils.isSynthetic(tree)) {
                tree = getEnclosingTree(tree.getParentPath());
            }
            t = tree.getLeaf();
        }
        
        boolean elementInImport = false;
        if(t.getKind() == Tree.Kind.IDENTIFIER || t.getKind() == Tree.Kind.MEMBER_SELECT) {
            TreePath enclosingTree = getEnclosingImportTree(tree);
            if(enclosingTree != null) {
                elementInImport = true;
                inImport.set(true);
            }
        }

        if (TreeUtilities.CLASS_TREE_KINDS.contains(t.getKind())) {
            int[] pos = treeUtils.findNameSpan((ClassTree)t);
            if (pos == null) {
                Tree tr = tree.getParentPath().getLeaf();
                if (tr instanceof NewClassTree) {
                    NewClassTree newClass = (NewClassTree) tr;
                    start = (int) sp.getStartPosition(unit, newClass.getIdentifier());
                    end = (int) sp.getEndPosition(unit, newClass.getIdentifier());
                } else {
                    //#121084 hotfix
                    //happens for anonymous innerclasses
                    anonClassNameBug128074 = true;
                    start = end = (int) sp.getStartPosition(unit, t);
                }
                // #213723 hotfix, happens for enum values
                if(start < 0) {
                    TreePath parentPath = tree.getParentPath();
                    if(parentPath != null && (parentPath = parentPath.getParentPath()) != null
                            && parentPath.getLeaf().getKind() == Tree.Kind.VARIABLE) {
                        VariableTree enum_var = (VariableTree) parentPath.getLeaf();
                        pos = treeUtils.findNameSpan(enum_var);
                        if (pos == null) {
                            //#121084 hotfix
                            start = end = (int) sp.getStartPosition(unit, enum_var);
                        } else {
                            start = pos[0];
                            end = pos[1];
                        }
                    }
                }
            } else {
                start = pos[0];
                end = pos[1];
            }
        } else if (t.getKind() == Tree.Kind.METHOD) {
            int[] pos = treeUtils.findNameSpan((MethodTree)t);
            if (pos == null) {
                //#121084 hotfix
                start = end = (int) sp.getStartPosition(unit, t);
            } else {
                start = pos[0];
                end = pos[1];
            }
        } else if (t.getKind() == Tree.Kind.NEW_CLASS) {
            Tree ident = ((NewClassTree)t).getIdentifier();
            if (ident.getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
                ident = ((ParameterizedTypeTree)ident).getType();
            }
            if (ident.getKind()== Tree.Kind.MEMBER_SELECT) {
                int[] pos = treeUtils.findNameSpan((MemberSelectTree) ident);
                if (pos == null) {
                    //#121084 hotfix
                    start = end = (int) sp.getStartPosition(unit, ident);
                } else {
                    start = pos[0];
                    end = pos[1];
                }
            } else {
                TreePath varTreePath = tree.getParentPath();
                Tree varTree = varTreePath.getLeaf();
                Trees trees = compiler.getTrees();
                Element element = trees.getElement(varTreePath);
                if (element != null && varTree.getKind() == Tree.Kind.VARIABLE && element.getKind() == ElementKind.ENUM_CONSTANT) {
                    int[] pos = treeUtils.findNameSpan((VariableTree)varTree);
                    if (pos == null) {
                        //#121084 hotfix
                        start = end = (int) sp.getStartPosition(unit, varTree);
                    } else {
                        start = pos[0];
                        end = pos[1];
                    }
                } else {
                    start = (int) sp.getStartPosition(unit, ident);
                    end = (int) sp.getEndPosition(unit, ident);
                }
            }
        } else if (t.getKind() == Tree.Kind.MEMBER_SELECT) {
            int[] pos = treeUtils.findNameSpan((MemberSelectTree) t);
            if (pos == null) {
                //#121084 hotfix
                start = end = (int) sp.getStartPosition(unit, t);
            } else {
                start = pos[0];
                end = pos[1];
            }
        } else {
            start = (int) sp.getStartPosition(unit, t);
            end = (int) sp.getEndPosition(unit, t);
            if (end == -1) {
                if (!compiler.getTreeUtilities().isSynthetic(tree)) {
                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new RuntimeException("Cannot get end position for " + t.getClass().getName() + " " + t + " file:" + compiler.getFileObject().getPath())); // NOI18N
                }
                end = start;
            }
        }

        assert start>0:"Cannot find start position in file " + unit.getSourceFile().getName() + "\n tree=" + tree.toString();
        assert end>0:"Cannot find end position in file " + unit.getSourceFile().getName() + "\n tree=" + tree.toString();
        LineMap lm = tree.getCompilationUnit().getLineMap();
        long line = lm.getLineNumber(start);
        long endLine = lm.getLineNumber(end);
        long sta = lm.getStartPosition(line);
        int eof = content.length();
        long lastLine = lm.getLineNumber(eof);
        long en = lastLine > endLine ? lm.getStartPosition(endLine + 1) - 1 : eof;
        StringBuilder sb = new StringBuilder();
        sb.append(UIUtilities.getHtml(trimStart(content.subSequence((int) sta, start).toString())));
        sb.append("<b>"); //NOI18N
        sb.append(content.subSequence(start, end));
        sb.append("</b>");//NOI18N
        sb.append(UIUtilities.getHtml(trimEnd(content.subSequence(end, (int) en).toString())));
        
        DataObject dob = null;
        try {
            dob = DataObject.find(compiler.getFileObject());
        } catch (DataObjectNotFoundException ex) {
            Exceptions.printStackTrace(ex);
        }
        CloneableEditorSupport ces = JavaWhereUsedQueryPlugin.findCloneableEditorSupport(dob);
        PositionRef ref1 = ces.createPositionRef(start, Bias.Forward);
        PositionRef ref2 = ces.createPositionRef(end, Bias.Forward);
        PositionBounds bounds = new PositionBounds(ref1, ref2);
        TreePath tr = getEnclosingTree(tree);
        return new WhereUsedElement(
                bounds,
                start==end && anonClassNameBug128074 ? NbBundle.getMessage(WhereUsedPanel.class, "LBL_AnonymousClass"):sb.toString().trim(),
                start==end && anonClassNameBug128074 ? NbBundle.getMessage(WhereUsedPanel.class, "LBL_AnonymousClass"):content.subSequence((int)sta, (int)en).toString().trim(),
                compiler.getFileObject(),
                tr,
                compiler, access, inTest, inPlatform,inDependency, false, elementInImport);
    }
    
    private static String trimStart(String s) {
        for (int x = 0; x < s.length(); x++) {
            if (!Character.isWhitespace(s.charAt(x))) {
                return s.substring(x, s.length());
            }
        }
        return "";
    }
    
    private static String trimEnd(String s) {
        for (int x = s.length()-1; x >=0; x--) {
            if (!Character.isWhitespace(s.charAt(x))) {
                return s.substring(0, x + 1);
            }
        }
        return "";
    }
    
    public static WhereUsedElement create(int start, int end, CompilationInfo compiler, boolean inTest, boolean inPlatform, boolean inDependency) {
        CharSequence content = compiler.getSnapshot().getText();
        LineMap lm = compiler.getCompilationUnit().getLineMap();
        long line = lm.getLineNumber(start);
        long endLine = lm.getLineNumber(end);
        long sta = lm.getStartPosition(line);
        int eof = content.length();
        long lastLine = lm.getLineNumber(eof);
        long en = lastLine > endLine ? lm.getStartPosition(endLine + 1) - 1 : eof;
        StringBuilder sb = new StringBuilder();
        sb.append(UIUtilities.getHtml(trimStart(content.subSequence((int) sta, start).toString())));
        sb.append("<b>"); //NOI18N
        sb.append(content.subSequence(start, end));
        sb.append("</b>");//NOI18N
        sb.append(UIUtilities.getHtml(trimEnd(content.subSequence(end, (int) en).toString())));
        
        DataObject dob = null;
        try {
            dob = DataObject.find(compiler.getFileObject());
        } catch (DataObjectNotFoundException ex) {
            Exceptions.printStackTrace(ex);
        }
        CloneableEditorSupport ces = JavaWhereUsedQueryPlugin.findCloneableEditorSupport(dob);
        PositionRef ref1 = ces.createPositionRef(start, Bias.Forward);
        PositionRef ref2 = ces.createPositionRef(end, Bias.Forward);
        PositionBounds bounds = new PositionBounds(ref1, ref2);
        return new WhereUsedElement(bounds, sb.toString().trim(),
                content.subSequence((int)sta, (int)en).toString(),
                compiler.getFileObject(), null, compiler, null, inTest, inPlatform, inDependency, true, false);
    }
    
    private static TreePath getEnclosingImportTree(TreePath tp) {
        while(tp != null) {
            Tree tree = tp.getLeaf();
            if (tree.getKind() == Tree.Kind.IMPORT) {
                return tp;
            }
            tp = tp.getParentPath();
        }
        return null;
    }
    
    private static TreePath getEnclosingTree(TreePath tp) {
        while(tp != null) {
            Tree tree = tp.getLeaf();
            if (TreeUtilities.CLASS_TREE_KINDS.contains(tree.getKind()) || tree.getKind() == Tree.Kind.METHOD || tree.getKind() == Tree.Kind.IMPORT || tree.getKind() == Tree.Kind.VARIABLE) {
                return tp;
            } 
            tp = tp.getParentPath();
        }
        return null;
    }

    @Override
    public boolean filter(FiltersManager manager) {
        boolean show = true;

        if(JavaWhereUsedQueryPlugin.DEPENDENCIES) {
            if (inPlatform) {
                show = show && manager.isSelected(JavaWhereUsedFilters.PLATFORM.getKey());
            }

            if (inDependency) {
                show = show && manager.isSelected(JavaWhereUsedFilters.DEPENDENCY.getKey());
            }
        }

        if (inTestclass) {
            show = show && manager.isSelected(JavaWhereUsedFilters.TESTFILE.getKey());
        }

        show = show && manager.isSelected(JavaWhereUsedFilters.SOURCEFILE.getKey());

        if (access != null) {
            show = show && manager.isSelected(access.getKey());
        }
        
        if (inComment) {
            show = show && manager.isSelected(JavaWhereUsedFilters.COMMENT.getKey());
        }
        
        if (inImport) {
            show = show && manager.isSelected(JavaWhereUsedFilters.IMPORT.getKey());
        }
        return show;
    }
}
