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

import java.awt.Component;
import java.awt.Cursor;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.io.CharConversionException;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.netbeans.api.actions.Openable;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import static org.netbeans.modules.project.ui.Bundle.*;
import org.netbeans.modules.project.ui.groups.Group;
import org.netbeans.spi.project.AuxiliaryConfiguration;
import org.netbeans.spi.project.ui.support.ProjectConvertors;
import org.openide.cookies.EditCookie;
import org.openide.cookies.OpenCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.Node;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/** The util methods for projectui module.
 *
 * @author  Jiri Rechtacek
 */
public class ProjectUtilities {
    
    static final String OPEN_FILES_NS = "http://www.netbeans.org/ns/projectui-open-files/1"; // NOI18N
    static final String OPEN_FILES_NS2 = "http://www.netbeans.org/ns/projectui-open-files/2"; // NOI18N
    static final String OPEN_FILES_ELEMENT = "open-files"; // NOI18N
    static final String FILE_ELEMENT = "file"; // NOI18N
    static final String GROUP_ELEMENT = "group"; // NOI18N
    static final String NAME_ATTR = "name";
    
    
    // support class for xtesting in OpenProjectListTest
    static OpenCloseProjectDocument OPEN_CLOSE_PROJECT_DOCUMENT_IMPL = new OpenCloseProjectDocument () {
        @Override
        public boolean open (FileObject fo) {
            DataObject dobj;
            try {
                dobj = DataObject.find (fo);
            } catch (DataObjectNotFoundException donfo) {
                assert false : "DataObject must exist for " + fo;
                return false;
            }
            EditCookie ec = dobj.getLookup().lookup(EditCookie.class);
            OpenCookie oc = dobj.getLookup().lookup(OpenCookie.class);
            Openable o = dobj.getLookup().lookup(Openable.class);
            if (ec != null) {
                ec.edit();
            } else if (oc != null) {
                oc.open();
            } else if (o != null) {
                o.open();
            } else {
                ERR.log(Level.INFO, "No EditCookie nor OpenCookie nor Openable for {0}", dobj);
                return false;
            }
            return true;
        }
         
        @Override
        public Map<Project,Set<String>> close(final Project[] projects,
                                                    final boolean notifyUI) {
            final Wrapper wr = new Wrapper();
            wr.urls4project = new HashMap<Project,Set<String>>();
            doClose(projects, notifyUI, wr);
            return wr.urls4project;
        }

        private void doClose(Project[] projects, boolean notifyUI, Wrapper wr) {
            List<Project> listOfProjects = Arrays.asList(projects);
            for (Project p : listOfProjects) { //#232668 all projects need an entry in the map - to handle projects without files correctly
                wr.urls4project.put(p, new LinkedHashSet<String>());
            }
            Set<DataObject> openFiles = new HashSet<DataObject>();
            final Set<TopComponent> tc2close = new HashSet<TopComponent>();
            
            ERR.finer("Closing TCs");
            final Set<TopComponent> openedTC = getOpenedTCs();
            
            for (TopComponent tc : openedTC) {
                DataObject dobj = tc.getLookup().lookup(DataObject.class);

                if (dobj != null) {
                    FileObject fobj = dobj.getPrimaryFile();
                    Project owner = ProjectConvertors.getNonConvertorOwner(fobj);
                    ERR.log(Level.FINER, "Found {0} owned by {1} in {2} of {3}", new Object[] {fobj, owner, tc.getName(), tc.getClass()});

                    if (listOfProjects.contains(owner)) {
                        if (notifyUI) {
                            openFiles.add(dobj);
                            tc2close.add(tc);
                        } else if (!dobj.isModified()) {
                            // when not called from UI, only include TCs that arenot modified
                            tc2close.add(tc);
                        }
                        //#235897 split a single line to detect NPE better
                        final Set<String> pwnr = wr.urls4project.get(owner);
                        assert pwnr != null : "Owner project for file:" + fobj + " prj:" + owner;
                        final FileObject pf = fobj;
                        assert pf != null;
                        URL u = pf.toURL();
                        assert u != null;
                        String uex = u.toExternalForm();                        
                        pwnr.add(uex);
                    }
                } else {
                    ERR.log(Level.FINE, "#194243: no DataObject in lookup of {0} of {1}", new Object[] {tc.getName(), tc.getClass()});
                }
            }
            if (notifyUI) {
                for (DataObject dobj : DataObject.getRegistry().getModifiedSet()) {
                    FileObject fobj = dobj.getPrimaryFile();
                    Project owner = ProjectConvertors.getNonConvertorOwner(fobj);

                    if (listOfProjects.contains(owner) &&
                        !openFiles.contains(dobj)) {
                        openFiles.add(dobj);
                    }
                }
            }
            if (!notifyUI ||
                (!openFiles.isEmpty() && ExitDialog.showDialog(openFiles))) {
                Runnable r = new Runnable() {
                    @Override
                    public void run() {
                        // close documents
                        for (TopComponent tc : tc2close) {
                            tc.close();
                        }
                    }
                };
                if(SwingUtilities.isEventDispatchThread()) {
                    r.run();
                } else {
                    SwingUtilities.invokeLater(r);
                }
            } else {
                // signal that close was vetoed
                if (!openFiles.isEmpty()) {
                    wr.urls4project = null;
                }
            }
        }

        private Set<TopComponent> getOpenedTCs() {
            final Set<TopComponent> openedTC = new HashSet<TopComponent>();
            Runnable r = new Runnable() {
                public void run() {
                    WindowManager wm = WindowManager.getDefault();
                    for (Mode mode : wm.getModes()) {
                        //#84546 - this condituon should allow us to close just editor related TCs that are in any imaginable mode.
                        if (!wm.isEditorMode(mode)) {
                            continue;
                        }
                        ERR.log(Level.FINER, "Closing TCs in mode {0}", mode.getName());
                        openedTC.addAll(Arrays.asList(wm.getOpenedTopComponents(mode)));
                    }
                }
            };
            if (SwingUtilities.isEventDispatchThread()) {
                r.run();
            } else {
                try {
                    SwingUtilities.invokeAndWait(r);
                }
                catch (Exception ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
            return openedTC;
        }
    };

    private static class Wrapper {
        Map<Project,Set<String>> urls4project;
    }
    
    private static final Logger ERR = Logger.getLogger(ProjectUtilities.class.getName());
    
    private ProjectUtilities() {}
    
    public static void selectAndExpandProject( final Project p ) {
        
        // invoke later to select the being opened project if the focus is outside ProjectTab
        SwingUtilities.invokeLater (new Runnable () {
            
            @Override
            public void run () {
                final ProjectTab ptLogial = ProjectTab.findDefault(ProjectTab.ID_LOGICAL);

                Node root = ptLogial.getExplorerManager ().getRootContext ();
                // Node projNode = root.getChildren ().findChild( p.getProjectDirectory().getName () );
                Node projNode = null;
                for (Node n : root.getChildren().getNodes()) {
                    Project prj = n.getLookup().lookup(Project.class);
                    if (prj != null && prj.getProjectDirectory().equals(p.getProjectDirectory())) {
                        projNode = n;
                        break;
                    }
                }
                if (projNode == null) {
                    // fallback..
                    projNode = root.getChildren ().findChild( ProjectUtils.getInformation( p ).getName() );
                }
                
                if ( projNode != null ) {
                    try {                            
                        ptLogial.getExplorerManager ().setSelectedNodes( new Node[] { projNode } );
                        ptLogial.expandNode( projNode );
                        // ptLogial.open ();
                        // ptLogial.requestActive ();
                    } catch (Exception ignore) {
                        // may ignore it
                    }
                }
            }
        });
        
    }
    
    /** Invokes the preferred action on given object and tries to select it in
     * corresponding view, e.g. in logical view if possible otherwise
     * in physical project's view.
     * Note: execution this methods can invokes new threads to assure the action
     * is called in EQ.
     *
     * @param newDo new data object
     */   
    public static void openAndSelectNewObject (final DataObject newDo) {
        // call the preferred action on main class
        Mutex.EVENT.writeAccess (new Runnable () {
            @Override
            public void run () {
                final Node node = newDo.getNodeDelegate ();
                Action a = node.getPreferredAction();
                if (a instanceof ContextAwareAction) {
                    a = ((ContextAwareAction) a).createContextAwareInstance(node.getLookup ());
                }
                if (a != null) {
                    a.actionPerformed(new ActionEvent(node, ActionEvent.ACTION_PERFORMED, "")); // NOI18N
                }

                // next action -> expand && select main class in package view
                final ProjectTab ptLogical = ProjectTab.findDefault(ProjectTab.ID_LOGICAL);
                final ProjectTab ptPhysical = ProjectTab.findDefault(ProjectTab.ID_PHYSICAL);
                ProjectTab.RP.post(new Runnable() {
                    public @Override void run() {
                        ProjectTab tab = ptLogical;
                        Node n = tab.findNode(newDo.getPrimaryFile());
                        if (n == null) {
                            tab = ptPhysical;
                            n = tab.findNode(newDo.getPrimaryFile());
                        }
                        if (n != null) {
                            tab.selectNode(n);
                        }
                    }
                });
            }
        });
    }
    
    /** Makes the project tab visible
     * @param requestFocus if set to true the project tab will not only become visible but also
     *        will gain focus
     */
    public static void makeProjectTabVisible() {
        if (Boolean.getBoolean("project.tab.no.selection")) {
            return;
        }
        ProjectTab ptLogical = ProjectTab.findDefault(ProjectTab.ID_LOGICAL);
        ptLogical.open();
        ptLogical.requestActive();
    }
    
    /** Checks if the given file name can be created in the target folder.
     *
     * @param targetFolder target folder (e.g. source group)
     * @param folderName name of the folder relative to target folder (null or /-separated)
     * @param newObjectName name of created file
     * @param extension extension of created file
     * @param allowFileSeparator if '/' (and possibly other file separator, see {@link FileUtil#createFolder FileUtil#createFolder})
     *                           is allowed in the newObjectName
     * @return localized error message (HTML-safe) or null if all right
     */    
    @Messages({
        "# {0} - name of the file", "# {1} - an integer representing the invalid characters:", "#       0: both '/' and '\\' are invalid", "#       1: '\\' is invalid", "MSG_not_valid_filename=The filename {0} is not permitted as it contains {1,choice,0#a slash (/) or a backslash (\\)|1#a backslash (\\)}.",
        "# {0} - name of the file", "# {1} - an integer representing the invalid characters:", "#       0: both '/' and '\\' are invalid", "#       1: '\\' is invalid", "MSG_not_valid_folder=The folder name {0} is not permitted as it contains {1,choice,0#a slash (/) or a backslash (\\)|1#a backslash (\\)}.",
        "MSG_fs_or_folder_does_not_exist=The target folder does not exist.",
        "MSG_fs_is_readonly=The target folder is read-only.",
        "# {0} - name of the existing file", "MSG_file_already_exist=The file {0} already exists."
    })
    public static String canUseFileName (FileObject targetFolder, String folderName, String newObjectName,
            String extension, boolean allowFileSeparator, boolean freeFileExtension) {
        assert newObjectName != null; // SimpleTargetChooserPanel.isValid returns false if it is... XXX should it use an error label instead?

        boolean allowSlash = false;
        boolean allowBackslash = false;
        int errorVariant = 0;
        
        if (allowFileSeparator) {
            if (File.separatorChar == '\\') {
                errorVariant = 3;
                allowSlash = allowBackslash = true;
            } else {
                errorVariant = 1;
                allowSlash = true;
            }
        }
        
        if ((!allowSlash && newObjectName.indexOf('/') != -1) || (!allowBackslash && newObjectName.indexOf('\\') != -1)) {
            //if errorVariant == 3, the test above should never be true:
            assert errorVariant == 0 || errorVariant == 1 : "Invalid error variant: " + errorVariant;
            
            return MSG_not_valid_filename(safeEncode(newObjectName), errorVariant);
        }
        
        // test whether the selected folder on selected filesystem already exists
        if (targetFolder == null) {
            return MSG_fs_or_folder_does_not_exist();
        }
        
        // target directory should be writable
        // We should not check this via java.io.File - this breaks not only non-file-based file systems,
        // but can break versioning as well. See issue #251857 (In Remote Favorites tab user can't create new file)
        FileObject targetDir = (folderName != null) ? targetFolder.getFileObject(folderName) : targetFolder;        
        if (targetDir != null) {
            if (targetDir.isValid()&& ! targetDir.canWrite ()) {
                return MSG_fs_is_readonly();
            }
        } else if (! targetFolder.canWrite ()) {
            return MSG_fs_is_readonly();
        }

        // file should not already exist
        StringBuilder relFileName = new StringBuilder();
        if (folderName != null) {
            if (!allowBackslash && folderName.indexOf('\\') != -1) {
                return MSG_not_valid_folder(safeEncode(folderName), 1);
            }
            relFileName.append(folderName);
            relFileName.append('/');
        }
        relFileName.append(newObjectName);
        String ext = "";
        if (extension != null && extension.length() != 0 && (!freeFileExtension || newObjectName.indexOf('.') == -1)) {
            ext = "." + extension;
            relFileName.append(ext);
        }
        if (targetFolder.getFileObject(relFileName.toString()) != null) {
            return MSG_file_already_exist(safeEncode(newObjectName + ext));
        }
        
        // all ok
        return null;
    }
    private static String safeEncode(String text) { // #208432
        if (text.length() > 30) {
            text = text.substring(0, 30) + '…';
        }
        try {
            return XMLUtil.toElementContent(text.replaceAll("\\s+", " "));
        } catch (CharConversionException ex) {
            return text;
        }
    }
    
    
    public static class WaitCursor implements Runnable {
        
        private boolean show;
        
        private WaitCursor( boolean show ) {
            this.show = show;
        }
       
        public static void show() {            
            invoke( new WaitCursor( true ) );
        }
        
        public static void hide() {
            invoke( new WaitCursor( false ) );            
        }
        
        private static void invoke( WaitCursor wc ) {
            if (GraphicsEnvironment.isHeadless()) {
                return;
            }
            if ( SwingUtilities.isEventDispatchThread() ) {
                wc.run();
            }
            else {
                SwingUtilities.invokeLater( wc );
            }
        }
        
        @Override
        public void run() {
            try {            
                JFrame f = (JFrame)WindowManager.getDefault ().getMainWindow ();
                Component c = f.getGlassPane ();
                c.setVisible ( show );
                c.setCursor (show ? Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR) : null);
            } 
            catch (NullPointerException npe) {
                Exceptions.printStackTrace(npe);
            }
        }
    }
    
    /** Closes all documents in editor area which are owned by one of given projects.
     * If some documents are modified then an user is notified by Save/Discard/Cancel dialog.
     * Dialog is showed only once for all project's documents together.
     * URLs of closed documents are stored to <code>private.xml</code>.
     *
     * @param p project to close
     * @return false if the user cancelled the Save/Discard/Cancel dialog, true otherwise
     */    
    public static boolean closeAllDocuments(Project[] projects, boolean notifyUI, String groupName) {
        if (projects == null) {
            throw new IllegalArgumentException ("No projects are specified."); // NOI18N
        }
        
        if (projects.length == 0) {
            // no projects to close, no documents will be closed
            return true;
        }
        
        Map<Project,Set<String>> urls4project = OPEN_CLOSE_PROJECT_DOCUMENT_IMPL.close(projects, notifyUI);

        if (urls4project != null) {
            // store project's documents
            // loop all project being closed
            for (Map.Entry<Project,Set<String>> entry : urls4project.entrySet()) {
                storeProjectOpenFiles(entry.getKey(), entry.getValue(), groupName);
            }
        }
        
        return urls4project != null;
    }
    
    public static void storeProjectOpenFiles(Project p, Set<String> urls, String groupName) {
        AuxiliaryConfiguration aux = ProjectUtils.getAuxiliaryConfiguration(p);
        
        Set<String> openFileUrls = getOpenFilesUrls(p, groupName);
        if(urls.isEmpty() && openFileUrls.isEmpty()) {
            // was empty, stays empty, leave
            return;                
        }        
        if(urls.size() == openFileUrls.size()) {
            boolean same = true;
            for (String url : openFileUrls) {
                if(!urls.contains(url)) {
                    same = false;
                    break;
                }
            }
            if(same) {
                // nothing changed, leave
                return;
            }
        }
        
        aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false);

        Element openFiles = aux.getConfigurationFragment(OPEN_FILES_ELEMENT, OPEN_FILES_NS2, false);
        if (openFiles == null) {
            Document xml = XMLUtil.createDocument (OPEN_FILES_ELEMENT, OPEN_FILES_NS2, null, null);
            openFiles = xml.createElementNS (OPEN_FILES_NS2, OPEN_FILES_ELEMENT);
        }
        NodeList groups = openFiles.getElementsByTagNameNS(OPEN_FILES_NS2, GROUP_ELEMENT);
        for (int i = 0; i < groups.getLength(); i++) {
            Element g = (Element) groups.item(i);
            String attr = g.getAttribute(NAME_ATTR);
            if (attr.equals(groupName) || (attr.equals("") && groupName == null)) {
                openFiles.removeChild(g);
                break;
            }
        }
        Element groupEl = openFiles.getOwnerDocument ().createElementNS(OPEN_FILES_NS2, GROUP_ELEMENT);
        if (groupName != null) {
            groupEl.setAttribute(NAME_ATTR, groupName);
        }
        openFiles.appendChild(groupEl);

        Element fileEl;
        // loop all open files of given project
        for (String url : urls) {
            fileEl = groupEl.getOwnerDocument ().createElementNS(OPEN_FILES_NS2, FILE_ELEMENT);
            fileEl.appendChild(fileEl.getOwnerDocument().createTextNode(url));
            groupEl.appendChild (fileEl);
        }

        aux.putConfigurationFragment (openFiles, false);
    }
    
    /** Opens the project's files read from the private <code>project.xml</code> file
     * 
     * @param p project
     */
    public static Set<FileObject> openProjectFiles (Project p) {
        Group grp = Group.getActiveGroup();
        return openProjectFiles(p, grp);
    }
    
    public static Set<FileObject> openProjectFiles (Project p, Group grp) {
        String groupName = grp == null ? null : grp.getName();
        ERR.log(Level.FINE, "Trying to open files from {0}...", p);
        
        Set<String> urls = getOpenFilesUrls(p, groupName);
        Set<FileObject> toRet = new HashSet<FileObject>();
        for (String url : urls) {
            ERR.log(Level.FINE, "Will try to open {0}", url);
            FileObject fo;
            try {
                fo = URLMapper.findFileObject (new URL (url));
            } catch (MalformedURLException mue) {
                assert false : "MalformedURLException in " + url;
                continue;
            }
            if (fo == null || !fo.isValid()) { //check for validity because of issue #238488
                ERR.log(Level.FINE, "Could not find {0}", url);
                continue;
            }
            
            //#109676
            if (ProjectConvertors.getNonConvertorOwner(fo) != p) {
                ERR.log(Level.FINE, "File {0} doesn''t belong to project at {1}", new Object[] {url, p.getProjectDirectory().getPath()});
                continue;
            }
            
            OPEN_CLOSE_PROJECT_DOCUMENT_IMPL.open (fo);
            toRet.add(fo);
        }
        
        // clean-up stored files -
        // mkleint: I've commented this out as it makes debugging what went wrong when switching groups or exiting the IDE very difficult
        // and now that we have per-group settings stored, removing a single group's values does not pose any real advantage.
        
        //aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS, false);
//        openFiles.removeChild(groupEl);
//        if (openFiles.getElementsByTagNameNS(OPEN_FILES_NS2, GROUP_ELEMENT).getLength() > 0) {
//            aux.putConfigurationFragment (openFiles, false);
//        } else {
//            aux.removeConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS2, false);
//        }
        return toRet;
    }
    
    private static Set<String> getOpenFilesUrls(Project p, String groupName) {
        AuxiliaryConfiguration aux = ProjectUtils.getAuxiliaryConfiguration(p);
        
        Element openFiles = aux.getConfigurationFragment (OPEN_FILES_ELEMENT, OPEN_FILES_NS2, false);
        if (openFiles == null) {
            return Collections.emptySet();
        }

        Element groupEl = null;
        
        NodeList groups = openFiles.getElementsByTagNameNS(OPEN_FILES_NS2, GROUP_ELEMENT);
        for (int i = 0; i < groups.getLength(); i++) {
            Element g = (Element) groups.item(i);
            String attr = g.getAttribute(NAME_ATTR);
            if (attr.equals(groupName) || (attr.equals("") && groupName == null)) {
                groupEl = g;
                break;
            }
        }
        
        if (groupEl == null) {
            return Collections.emptySet();
        }
        
        NodeList list = groupEl.getElementsByTagNameNS(OPEN_FILES_NS2, FILE_ELEMENT);
        Set<String> toRet = new HashSet<String>();
        for (int i = 0; i < list.getLength (); i++) {
            String url = list.item (i).getChildNodes ().item (0).getNodeValue ();
            toRet.add(url);
        }    
        return toRet;
    }

    // interface for handling project's documents stored in project private.xml
    // it serves for a unit test of OpenProjectList
    interface OpenCloseProjectDocument {
        
        // opens stored document in the document area
        boolean open(FileObject fo);
        
        // closes documents of given projects and returns mapped document's urls by project
        // it's used as base for storing documents in project private.xml
        Map<Project,Set<String>> close(Project[] projects, boolean notifyUI);
    }
    
}
