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

import java.awt.BorderLayout;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.modules.properties.PropertiesDataObject; // PENDING
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.NodeAcceptor;
import org.openide.nodes.NodeOperation;
import org.openide.util.UserCancelException;
import org.openide.filesystems.FileUtil;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.queries.VisibilityQuery;
import org.openide.awt.Mnemonics;
import org.openide.util.ImageUtilities;





/**
 * A static utility class grouping functions for dialogs for selection 
 * sources from project and other places.
 */
public class SelectorUtils {

  /**
   * The filter used to filter out folders and resource bundles.
   */
  public static final FilteredNode.NodeFilter BUNDLES_FILTER = 		    
    new FilteredNode.NodeFilter() {
      public boolean acceptNode(Node n) {
	// Has to be data object.
	DataObject dataObject = n.getCookie(DataObject.class);
	if(dataObject == null)
	  return false;
		   
	// Has to be a folder or a resource class.
	return 
	  ((dataObject instanceof DataFolder) && (isVisible(dataObject))) ||
	  (dataObject instanceof PropertiesDataObject); // PENDING same like above.
      }
    };

    private static boolean isVisible(DataObject dobj) {
        return (dobj.getPrimaryFile()==null) ||
            (VisibilityQuery.getDefault().isVisible(dobj.getPrimaryFile()));
            
    }
    
				       
  public static final FilteredNode.NodeFilter ALL_FILTER = 
    new FilteredNode.NodeFilter() {
      public boolean acceptNode(Node n) {
	return true;
      }
    };



  /**
   * Brings up a modal windows for selection of a resource bundle from
   * the given project.
   * @param prj the project to select from
   * @return DataObject representing the selected bundle file or null
   */
  static public DataObject selectBundle(Project prj, FileObject file) {
    try {
      Node root = bundlesNode(prj, file, true);

      Node[] selectedNodes= 
	NodeOperation.getDefault().
	select(
	       Util.getString("CTL_SelectPropDO_Dialog_Title"),
	       Util.getString("CTL_SelectPropDO_Dialog_RootTitle"),
	       root,
	       new NodeAcceptor() {
		 public boolean acceptNodes(Node[] nodes) {
		   if(nodes == null || nodes.length != 1) {
		     return false;
		   }

		   // Has to be data object.
		   DataObject dataObject = nodes[0].getCookie(DataObject.class);
		   if(dataObject == null)
		     return false;
                      
		   // Has to be of resource class.
		   return dataObject.getClass().equals(PropertiesDataObject.class); // PENDING same like above.
		 }
	       }
	       );
      return selectedNodes[0].getCookie(DataObject.class);
    } catch (UserCancelException uce) {
        //ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, uce);
            // nobody is interested in the message
        return null;
    }

  }


    /**
     * Prepare node structure for showing available bundles. The
     * structure is relative to the file that should access the
     * bundle.
     * @param prj the <code>Project</code> <code>file</code> is in
     * @param file <code>FileObject</code> to show bundles for
     * @param includeFiles specifies whether to show jar files or just folders
     * @return root <code>Node</code> 
     */
    static public Node bundlesNode(Project prj, FileObject file, boolean includeFiles) {
        List<Node> nodes = new LinkedList<Node>();
        if (prj == null) {
            prj = FileOwnerQuery.getOwner(file);
        }

        ClassPath cp = ClassPath.getClassPath(file, ClassPath.EXECUTE);
        if (cp != null) {
            nodes.addAll(getRootNodes(prj, getRoots(ClassPath.getClassPath(file, ClassPath.SOURCE), cp), BUNDLES_FILTER, includeFiles));
        }
        
        return createRootFor(nodes, prj);
    }

    private static List<FileObject> getRoots(ClassPath sources, ClassPath cp) {
        ArrayList<FileObject> l = new ArrayList<FileObject>(cp.entries().size());
        for (ClassPath.Entry e : sources.entries()) {
            if (e.getRoot() != null) {
                l.add(e.getRoot());
            }
        }
        for (ClassPath.Entry e : cp.entries()) {

            // try to map it to sources
            URL url = e.getURL();
            SourceForBinaryQuery.Result r= SourceForBinaryQuery.findSourceRoots(url);
            FileObject [] fos = r.getRoots();
            if (fos.length > 0) {
                for (FileObject fo : fos) {
                    if (!l.contains(fo)) {
                        l.add(fo);
                    }
                }
            } else {
                if (e.getRoot()!=null) 
                    if (!l.contains(e.getRoot())) {
                        l.add(e.getRoot()); // add the class-path location
                                        // directly
                    }
            }
        }

        return l;
    }


    private static List<Node> getRootNodes(Project prj,
                                           List<FileObject> roots, 
                                           FilteredNode.NodeFilter filter,
                                           boolean includeFiles) {
        List<Node> nodes = new ArrayList<Node>(roots.size());      
        for (FileObject rfo : roots) {
            try {
                if (includeFiles || (FileUtil.toFile(rfo)!=null)) {
                    Project owner = org.netbeans.api.project.FileOwnerQuery.getOwner(rfo);
                    Node origNode = DataObject.find(rfo).getNodeDelegate();
                    FilteredNode node =  new FilteredNode(origNode,filter, getDisplayName(rfo, owner, prj!=owner));
                    nodes.add(node);
                }
            } catch (org.openide.loaders.DataObjectNotFoundException ex) {}
        }
        return nodes;
    }


    private static String getDisplayName(FileObject fo, Project owner, boolean incPrjName) {
        if (owner != null) {
            SourceGroup grp = getSourceGroup(fo, owner);
            String n = (grp!=null)?grp.getDisplayName():FileUtil.getFileDisplayName(fo);
            if (incPrjName) {
                ProjectInformation pi = ProjectUtils.getInformation(owner);
                n  += " [" + pi.getDisplayName() + "]";
            }
            return n;
        } else 
            return FileUtil.getFileDisplayName(fo);
    }

    private static SourceGroup getSourceGroup(FileObject file, Project prj) {
      Sources src = ProjectUtils.getSources(prj);
      SourceGroup[] srcgrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
      for (SourceGroup srcGrp : srcgrps) {
          if (file == srcGrp.getRootFolder())
              return srcGrp;
      }
      return null;
    }


  /** 
   * Prepare node structure showing sources 
   * @param prj the project to select from
   * @param filter NodeFilter used to filter only relevant information
   * @return root Node of source files from <code>prj</code> filtered
   * by <code>filter</code>
   **/
  static public Node sourcesNode(Project prj, FilteredNode.NodeFilter filter) {
      Sources src = ProjectUtils.getSources(prj);
      SourceGroup[] srcgrps = src.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
      java.util.List<Node> nodes = new ArrayList<Node>();      
      for (SourceGroup srcGrp : srcgrps) {
	try {
	  FileObject rfo = srcGrp.getRootFolder();
	  FilteredNode node = new FilteredNode(DataObject.find(rfo).getNodeDelegate(),
					       filter);
	  //	  node.setName(srcGrp.getName());
	  node.setDisplayName(srcGrp.getDisplayName());
	  //	node.setIcon(srcGrp.getIcon());
					     
	  nodes.add(node);
	} catch (org.openide.loaders.DataObjectNotFoundException ex) {}
      }

      return createRootFor(nodes, prj);
  }

    private static Node createRootFor(java.util.List<Node> nodes, Project prj) {
        // create a root for all gathered nodes
        Children ch = new Children.Array();
        Node[] nodesArray = new Node[ nodes.size() ];
        nodes.toArray( nodesArray );
        ch.add( nodesArray );

        final Icon icon = ProjectUtils.getInformation(prj).getIcon();
        AbstractNode ret = new AbstractNode(ch) {

            @Override
            public Image getIcon(int type) {
                return ImageUtilities.icon2Image(icon);
            }

            @Override
            public Image getOpenedIcon(int type) {
                return getIcon(type);
            }
        };
        ret.setDisplayName(ProjectUtils.getInformation(prj).getDisplayName());
        return ret;
    }




  /** Instantiate a template object.
   * Asks user for the target file's folder and creates the file.
   * @param project the project the template should be instantiated in
   * @param refFile the file for which bundle is created 
   * @param template the template to use
   * @return the generated DataObject
   * @exception UserCancelException if the user cancels the action
   * @exception IOException on I/O error
   * @see DataObject#createFromTemplate
   */
  public static DataObject instantiateTemplate(Project project, FileObject refFile, DataObject template) throws IOException {
    // Create component for for file name input.
    ObjectNameInputPanel panel = new ObjectNameInputPanel();
        
    Node repositoryNode =  SelectorUtils.bundlesNode(project, refFile, false);
        
    // Selects one folder from data systems.
    DataFolder dataFolder = 
      NodeOperation.getDefault().select
      (
       I18nUtil.getBundle().getString ("CTL_Template_Dialog_Title"),
       I18nUtil.getBundle().getString ("CTL_Template_Dialog_RootTitle"),
       repositoryNode,
       new NodeAcceptor() {
	 public boolean acceptNodes(Node[] nodes) {
	   if(nodes == null || nodes.length != 1) {
	     return false;
	   }
                    
	   DataFolder cookie = nodes[0].getCookie(DataFolder.class);
	   return (cookie != null && cookie.getPrimaryFile().canWrite());
	 }
       },
       panel
       )[0].getCookie(DataFolder.class);
        
       String name = panel.getText();
        
       DataObject newObject;
        
       if(name.equals ("")) { // NOI18N
	 newObject = template.createFromTemplate(dataFolder);
       } else {
	 newObject = template.createFromTemplate(dataFolder, name);
       }
        
       try {
	 return newObject;
       } catch(ClassCastException cce) {
	 throw new UserCancelException();
       }
  }

    public static DataObject selectOrCreateBundle(FileObject refFile,
                                                    DataObject template,
                                                    DataObject actBundle) {
        Node rootNode = bundlesNode(null, refFile, true);

        FileObject actFile =  (actBundle != null) ?
                               actBundle.getPrimaryFile() :
                               null;

        FileSelector fs = new FileSelector(refFile, template, actFile);
        fs.getDialog(I18nUtil.getBundle().getString ("CTL_SelectPropDO_Dialog_Title"), null) // NOI18N
            .setVisible(true);
        return fs.isConfirmed() ? fs.getSelectedDataObject() : null;
    }

  /** Panel used by <code>instantiateTemplate</code> method. */
  private static class ObjectNameInputPanel extends JPanel {
        
    /** Generated Serialized Version UID. */
    static final long serialVersionUID = 1980214734060402958L;

    /** Text field. */
    JTextField text;

        
    /** Constructs panel. */
    public ObjectNameInputPanel () {
      BorderLayout layout = new BorderLayout();
      layout.setVgap(5);
      layout.setHgap(5);
      setLayout(layout);
            
      // label and text field with mnemonic
      String labelText = I18nUtil.getBundle().getString ("LBL_TemplateName");
      JLabel label = new JLabel();
      Mnemonics.setLocalizedText(label, labelText);
      text = new JTextField();
      text.getAccessibleContext().setAccessibleDescription(I18nUtil.getBundle().getString ("ACS_TEXT_ObjectNameInputPanel"));
            
      label.setLabelFor(text);
            
      add(BorderLayout.WEST, label);
      add(BorderLayout.CENTER, text);
    }

        
    /** Requets focus for text field. */
    public void requestFocus () {
      text.requestFocus ();
    }
        
    /** Getter for <code>text</code>. */
    public String getText () {
      return text.getText ();
    }

    /** Setter for <code>text</code>. */
    public void setText (String s) {
      setText(s);
    }
  } // End of nested class ObjectNameInputPanel
    



}
