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

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.SourcePositions;
import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.lang.model.element.Element;
import javax.swing.Action;
import javax.swing.JEditorPane;
import javax.swing.text.StyledDocument;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.queries.UnitTestForSourceQuery;
import org.netbeans.api.java.source.CancellableTask;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.ElementHandle;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.modules.junit.api.JUnitTestUtil;
import org.netbeans.spi.java.classpath.PathResourceImplementation;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.openide.ErrorManager;
import org.openide.cookies.EditorCookie;
import org.openide.cookies.LineCookie;
import org.openide.cookies.OpenCookie;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.Node;
import org.openide.text.Line;
import org.openide.text.Line.ShowOpenType;
import org.openide.text.Line.ShowVisibilityType;
import org.openide.text.NbDocument;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;

/** Action sensitive to some DataFolder or SourceCookie cookie
 * which tries to open JUnit test corresponding to the selected source file.
 *
 * @author  Nathan W. Phelps, David Konecny
 * @author  Marian Petras
 * @ version 1.0
 */
@SuppressWarnings("serial")
public class OpenTestAction extends TestAction {

    public OpenTestAction() {
        putValue("noIconInMenu", Boolean.TRUE);
    }
    

    protected void performAction (Node[] nodes) {
        FileObject selectedFO;
        
        for (int i = 0; i < nodes.length; i++) {
            // get test class or suite class file, if it was not such one pointed by the node
            selectedFO = org.netbeans.modules.gsf.testrunner.ui.api.UICommonUtils.getFileObjectFromNode(nodes[i]);
            if (selectedFO == null) {
                JUnitTestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class, "MSG_file_from_node_failed"));
                continue;
            }
            ClassPath cp = ClassPath.getClassPath(selectedFO, ClassPath.SOURCE);
            if (cp == null) {
                JUnitTestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class, 
                    "MSG_no_project", selectedFO));
                continue;
            }
 
            FileObject packageRoot = cp.findOwnerRoot(selectedFO);            
            URL[] testRoots = UnitTestForSourceQuery.findUnitTests(packageRoot);
            FileObject fileToOpen = null;
            for (int j = 0 ; j < testRoots.length; j++) {
                fileToOpen = findUnitTestInTestRoot(cp, selectedFO, testRoots[j]);
                if (fileToOpen != null) break;
            }
            
            if (fileToOpen != null) {
                openFile(fileToOpen);
            } else {                
                String testClsName = getTestName(cp, selectedFO).replace('/','.');                                                
                String pkgName = cp.getResourceName(selectedFO, '.', false);                
                boolean isPackage = selectedFO.isFolder();
                boolean isDefPkg = isPackage && (pkgName.length() == 0);
                String msgPattern = !isPackage
                       ? "MSG_test_class_not_found"                     //NOI18N
                       : isDefPkg
                         ? "MSG_testsuite_class_not_found_def_pkg"      //NOI18N
                         : "MSG_testsuite_class_not_found";             //NOI18N
                                
                String[] params = isDefPkg ? new String[] { testClsName }
                                           : new String[] { testClsName,
                                                            pkgName };                                                                             
                                 
                JUnitTestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class,
                                                        msgPattern, params),
                                    ErrorManager.INFORMATIONAL);
                continue;
            }
        }
    }

    private static FileObject findUnitTestInTestRoot(ClassPath cp, FileObject selectedFO, URL testRoot) {
        ClassPath testClassPath = null;
        if (testRoot == null) { //no tests, use sources instead
            testClassPath = cp;
        } else {
            try {
                List<PathResourceImplementation> cpItems
                        = new ArrayList<PathResourceImplementation>();
                cpItems.add(ClassPathSupport.createResource(testRoot));
                testClassPath = ClassPathSupport.createClassPath(cpItems);
            } catch (IllegalArgumentException ex) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
                testClassPath = cp; 
            }
        }
        String testName = getTestName(cp, selectedFO);
        return testClassPath.findResource(testName+".java");
    }

    private static String getTestName(ClassPath cp, FileObject selectedFO) {
        String resource = cp.getResourceName(selectedFO, '/', false);        
        String testName = null;
        if (selectedFO.isFolder()) {
        //find Suite for package
            testName = JUnitTestUtil.convertPackage2SuiteName(resource);
        } else {
        // find Test for class
            testName = JUnitTestUtil.convertClass2TestName(resource);
        }
        
        return testName;
    }
    
    /**
     * Open given file in editor.
     * @return true if file was opened or false
     */
    public static boolean openFile(FileObject fo) {
        DataObject dobj;
        try {
            dobj = DataObject.find(fo);
        } catch (DataObjectNotFoundException e) {
            getLogger().log(Level.WARNING, null, e);
            return false;
        }
        assert dobj != null;
        
        EditorCookie editorCookie = dobj.getCookie(EditorCookie.class);
        if (editorCookie != null) {
            editorCookie.open();
            return true;
        }
        
        OpenCookie openCookie = dobj.getCookie(OpenCookie.class);
        if (openCookie != null) {
            openCookie.open();                
            return true;
        }
        
        return false;
    }
    
    /**
     */
    static boolean openFileAtElement(FileObject fileObject,
                                     ElementHandle<Element> element) {
        final DataObject dataObject;
        try {
            dataObject = DataObject.find(fileObject);
        } catch (DataObjectNotFoundException e) {
            getLogger().log(Level.INFO, null, e);
            return false;
        }
        assert dataObject != null;

        final EditorCookie editorCookie = dataObject.getCookie(EditorCookie.class);
        if (editorCookie != null) {
            
            StyledDocument doc;
            try {
                doc = editorCookie.openDocument();
            } catch (IOException ex) {
                String msg = ex.getLocalizedMessage();
                if (msg == null) {
                    msg = ex.getMessage();
                }
                getLogger().log(Level.SEVERE, msg, ex);
                return false;
            }
            
            editorCookie.open();
            
            LineCookie lineCookie = dataObject.getCookie(LineCookie.class);
            if ((lineCookie != null) && (element != null) && (doc != null)) {
                int currentPos = -1;
                JEditorPane[] editorPanes = editorCookie.getOpenedPanes();
                if ((editorPanes != null) && (editorPanes.length != 0)) {
                    currentPos = editorPanes[0].getCaretPosition();
                }
                int[] elementPositionBounds = null;
                try {
                    elementPositionBounds = getPositionRange(fileObject, element);
                } catch (IOException ex) {
                    getLogger().log(Level.WARNING, null, ex);
                }
                if ((currentPos == -1)
                    || (elementPositionBounds != null)
                       && ((currentPos < elementPositionBounds[0])
                           ||(currentPos >= elementPositionBounds[1]))) {
                    int startPos = elementPositionBounds[0];
                    int lineNum = NbDocument.findLineNumber(doc, startPos);
                    if (lineNum != -1) {
                        Line line = lineCookie.getLineSet().getCurrent(lineNum);
                        try {
                            int lineOffset = NbDocument.findLineOffset(doc,
                                                                       lineNum);
                            int column = startPos - lineOffset;
                            line.show(ShowOpenType.OPEN, ShowVisibilityType.FOCUS, column);
                        } catch (IndexOutOfBoundsException ex) {
                            Logger.getLogger(OpenTestAction.class.getName())
                                  .log(Level.INFO, null, ex);
                            line.show(ShowOpenType.OPEN, ShowVisibilityType.FOCUS);
                        }
                    }
                }
            }
            return true;
        }
        
        OpenCookie openCookie = dataObject.getCookie(OpenCookie.class);
        if (openCookie != null) {
            openCookie.open();                
            return true;
        }
        
        return false;
    }
    
    /**
     */
    private static Logger getLogger() {
        return Logger.getLogger(OpenTestAction.class.getName());
    }
    
    /**
     */
    private static int[] getPositionRange(
                         FileObject fileObj,
                         ElementHandle<Element> elemHandle) throws IOException {
        PositionRangeFinder posFinder = new PositionRangeFinder(fileObj, elemHandle);
        JavaSource.forFileObject(fileObj).runUserActionTask(posFinder, true);
        return posFinder.getPositionRange();
    }
        
    /**
     *
     */
    private static class PositionRangeFinder
                            implements CancellableTask<CompilationController> {
        
        private final FileObject fileObj;
        private final ElementHandle<Element> elemHandle;
        private int[] positionRange = null;
        private volatile boolean cancelled;
        
        /**
         */
        private PositionRangeFinder(FileObject fileObj,
                                    ElementHandle<Element> elemHandle) {
            this.fileObj = fileObj;
            this.elemHandle = elemHandle;
        }
        
        /**
         */
        public void run(CompilationController controller) throws IOException {
            try {
                controller.toPhase(Phase.RESOLVED);     //cursor position needed
            } catch (IOException ex) {
                Logger.getLogger("global").log(Level.SEVERE, null, ex); //NOI18N
            }
            if (cancelled) {
                return;
            }
            
            Element element = elemHandle.resolve(controller);
            if (cancelled || (element == null)) {
                return;
            }

            Trees trees = controller.getTrees();
            CompilationUnitTree compUnit = controller.getCompilationUnit();
            DeclarationTreeFinder treeFinder = new DeclarationTreeFinder(
                                                        element, trees);
            treeFinder.scan(compUnit, null);
            Tree tree = treeFinder.getDeclarationTree();

            if (tree != null) {
                SourcePositions srcPositions = trees.getSourcePositions();
                long startPos = srcPositions.getStartPosition(compUnit, tree);
                long endPos = srcPositions.getEndPosition(compUnit, tree);
                
                if ((startPos >= 0) && (startPos <= (long) Integer.MAX_VALUE)
                     && (endPos >= 0) && (endPos <= (long) Integer.MAX_VALUE)) {
                    positionRange = new int[2];
                    positionRange[0] = (int) startPos;
                    positionRange[1] = (int) endPos;
                }
            }
        }

        /**
         */
        public void cancel() {
            cancelled = true;
        }
        
        /**
         */
        int[] getPositionRange() {
            return positionRange;
        }

    }
    
    /**
     *
     */
    private static class DeclarationTreeFinder extends ErrorAwareTreePathScanner<Void, Void> {

        private final Element element;
        private final Trees trees;
        private Tree declTree;
        
        /**
         */
        private DeclarationTreeFinder(Element element, Trees trees) {
            this.element = element;
            this.trees = trees;
        }
        
	@Override
        public Void visitClass(ClassTree tree, Void d) {
            if (declTree == null) {
                handleDeclaration();
                super.visitClass(tree, d);
            }
            return null;
        }
        
	@Override
        public Void visitMethod(MethodTree tree, Void d) {
            if (declTree == null) {
                handleDeclaration();
                super.visitMethod(tree, d);
            }
            return null;
        }
        
        /**
         */
        public void handleDeclaration() {
            Element found = trees.getElement(getCurrentPath());
            
            if (element.equals(found)) {
                declTree = getCurrentPath().getLeaf();
            }
        }
        
        /**
         */
        Tree getDeclarationTree() {
            return declTree;
        }
        
    }
    
    public String getName () {
        return NbBundle.getMessage (OpenTestAction.class, "LBL_Action_OpenTest");
    }

     protected String iconResource () {
         return "org/netbeans/modules/junit/resources/OpenTestActionIcon.gif";
     }

    public HelpCtx getHelpCtx () {
        return new HelpCtx(OpenTestAction.class);
    }

    /** Perform special enablement check in addition to the normal one.
    protected boolean enable (Node[] nodes) {
	if (! super.enable (nodes)) return false;
	if (...) ...;
    }
    */

    protected void initialize () {
	super.initialize ();
        putProperty(Action.SHORT_DESCRIPTION, NbBundle.getMessage(OpenTestAction.class, "HINT_Action_OpenTest"));
    }

}
