/*
 * 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.maven.junit.ui;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.util.ElementFilter;
import javax.swing.Action;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.extexecution.print.LineConvertors.FileLocator;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.Task;
import org.netbeans.modules.gsf.testrunner.api.CommonUtils;
import org.netbeans.modules.gsf.testrunner.ui.api.TestMethodNode;
import org.netbeans.modules.gsf.testrunner.ui.api.TestsuiteNode;
import org.netbeans.modules.junit.ui.api.JUnitTestMethodNode;
import org.netbeans.modules.java.testrunner.ui.api.NodeOpener;
import org.netbeans.modules.java.testrunner.ui.api.UIJavaUtils;
import org.netbeans.modules.junit.ui.api.JUnitCallstackFrameNode;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.nodes.Children;
import org.openide.nodes.Node;

/**
 *
 * @author Marian Petras
 */
@NodeOpener.Registration(projectType = CommonUtils.MAVEN_PROJECT_TYPE, testingFramework = CommonUtils.JUNIT_TF)
public final class MavenJUnitNodeOpener extends NodeOpener {

    private static final Logger LOG = Logger.getLogger(MavenJUnitNodeOpener.class.getName());

    static final Action[] NO_ACTIONS = new Action[0];

    public void openTestsuite(TestsuiteNode node) {
        Children childrens = node.getChildren();
        if (childrens != null) {
            Node child = childrens.getNodeAt(0);
            if ((child != null) && (child instanceof MavenJUnitTestMethodNode)) {
                final FileObject fo = ((MavenJUnitTestMethodNode) child).getTestcaseFileObject();
                if (fo != null) {
                    final long[] line = new long[]{0};
                    JavaSource javaSource = JavaSource.forFileObject(fo);
                    if (javaSource != null) {
                        try {
                            javaSource.runUserActionTask(new Task<CompilationController>() {
                                @Override
                                public void run(CompilationController compilationController) throws Exception {
                                    compilationController.toPhase(Phase.ELEMENTS_RESOLVED);
                                    Trees trees = compilationController.getTrees();
                                    CompilationUnitTree compilationUnitTree = compilationController.getCompilationUnit();
                                    List<? extends Tree> typeDecls = compilationUnitTree.getTypeDecls();
                                    for (Tree tree : typeDecls) {
                                        Element element = trees.getElement(trees.getPath(compilationUnitTree, tree));
                                        if (element != null && element.getKind() == ElementKind.CLASS && element.getSimpleName().contentEquals(fo.getName())) {
                                            long pos = trees.getSourcePositions().getStartPosition(compilationUnitTree, tree);
                                            line[0] = compilationUnitTree.getLineMap().getLineNumber(pos);
                                            break;
                                        }
                                    }
                                }
                            }, true);
                        } catch (IOException ioe) {
                            ErrorManager.getDefault().notify(ioe);
                        }
                    }
                    UIJavaUtils.openFile(fo, (int) line[0]);
                }
            }
        }
    }

    public void openTestMethod(final TestMethodNode node) {
        if (!(node instanceof MavenJUnitTestMethodNode)) {
            return;
        }
        final FileObject fo = ((MavenJUnitTestMethodNode) node).getTestcaseFileObject();
        if (fo != null) {
            final FileObject[] fo2open = new FileObject[]{fo};
            final long[] line = new long[]{0};
            JavaSource javaSource = JavaSource.forFileObject(fo2open[0]);
            if (javaSource != null) {
                try {
                    javaSource.runUserActionTask(new Task<CompilationController>() {
                        @Override
                        public void run(CompilationController compilationController) throws Exception {
                            compilationController.toPhase(Phase.ELEMENTS_RESOLVED);
                            Trees trees = compilationController.getTrees();
                            CompilationUnitTree compilationUnitTree = compilationController.getCompilationUnit();
                            List<? extends Tree> typeDecls = compilationUnitTree.getTypeDecls();
                            for (Tree tree : typeDecls) {
                                Element element = trees.getElement(trees.getPath(compilationUnitTree, tree));
                                if (element != null && element.getKind() == ElementKind.CLASS && element.getSimpleName().contentEquals(fo2open[0].getName())) {
                                    List<? extends ExecutableElement> methodElements = ElementFilter.methodsIn(element.getEnclosedElements());
                                    for (Element child : methodElements) {
                                        String name = node.getTestcase().getName(); // package.name.method.name
                                        if (child.getSimpleName().contentEquals(name.substring(name.lastIndexOf(".") + 1))) {
                                            long pos = trees.getSourcePositions().getStartPosition(compilationUnitTree, trees.getTree(child));
                                            line[0] = compilationUnitTree.getLineMap().getLineNumber(pos);
                                            break;
                                        }
                                    }
                                    // method not found in this FO, so try to find where this method belongs
                                    if (line[0] == 0) {
                                        UIJavaUtils.searchAllMethods(node, fo2open, line, compilationController, element);
                                    }
                                    break;
                                }
                            }
                        }
                    }, true);

                } catch (IOException ioe) {
                    ErrorManager.getDefault().notify(ioe);
                }
            }
            UIJavaUtils.openFile(fo2open[0], (int) line[0]);
        }
    }

    public void openCallstackFrame(Node node, @NonNull String frameInfo) {
        if(frameInfo.isEmpty()) { // user probably clicked on a failed test method node, find failing line within the testMethod using the stacktrace
            if (!(node instanceof JUnitTestMethodNode)) {
                return;
            }
        } else { // user probably clicked on a stacktrace node
            if (!(node instanceof JUnitCallstackFrameNode)) {
                return;
            }
        }
        JUnitTestMethodNode methodNode = (JUnitTestMethodNode) UIJavaUtils.getTestMethodNode(node);
        if (!(methodNode instanceof MavenJUnitTestMethodNode)) {
            return;
        }
        FileLocator locator = methodNode.getTestcase().getSession().getFileLocator();
        if (locator == null) {
            return;
        }
        FileObject testfo = ((MavenJUnitTestMethodNode) methodNode).getTestcaseFileObject();
        if (testfo == null) {
            //#221053 more logging
            StringBuilder stack = new StringBuilder();
            if (methodNode.getTestcase().getTrouble() != null) {
                String[] st = methodNode.getTestcase().getTrouble().getStackTrace();
                if (st != null) {
                    stack.append("\n");
                    for (String s : st) {
                        stack.append(s).append("\n");
                    }
                } else {
                    stack.append("<none>");
                }
            } else {
                stack.append("<none>");
            }
            LOG.log(Level.INFO, "#221053: unknown location: {0} classname:{1}, stacktrace:", new Object[]{methodNode.getTestcase().getLocation(), methodNode.getTestcase().getClassName(), stack});
        }
        final int[] lineNumStorage = new int[1];
        FileObject file = UIJavaUtils.getFile(frameInfo, lineNumStorage, locator);
        //lineNumStorage -1 means no regexp for stacktrace was matched.
        if (testfo != null && file == null && methodNode.getTestcase().getTrouble() != null && lineNumStorage[0] == -1) {
                //213935 we could not recognize the stack trace line and map it to known file
            //if it's a failure text, grab the testcase's own line from the stack.
            String[] st = methodNode.getTestcase().getTrouble().getStackTrace();
            if ((st != null) && (st.length > 0)) {
                int index = st.length - 1;
                    //213935 we need to find the testcase linenumber to jump to.
                // and ignore the infrastructure stack lines in the process
                while (!testfo.equals(file) && index != -1) {
                    file = UIJavaUtils.getFile(st[index], lineNumStorage, locator);
                    index = index - 1;
                }
            }
        }
        // Is this a @Test(expected = *Exception.class) test method that failed?
        if (file == null && lineNumStorage[0] == -1 && node instanceof MavenJUnitTestMethodNode) {
            openTestMethod((MavenJUnitTestMethodNode) node);
        }
        UIJavaUtils.openFile(file, lineNumStorage[0]);
    }

}
