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

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.platform.JavaPlatformManager;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
import org.netbeans.api.queries.FileEncodingQuery;
import org.netbeans.modules.java.api.common.project.ProjectProperties;
import org.netbeans.modules.javafx2.platform.api.JavaFXPlatformUtils;
import org.netbeans.modules.javafx2.platform.api.JavaFxRuntimeInclusion;
import org.netbeans.modules.javafx2.project.JavaFXProjectWizardIterator.WizardType;
import org.netbeans.modules.javafx2.project.fxml.ConfigureFXMLControllerPanelVisual;
import org.netbeans.spi.project.libraries.support.LibrariesSupport;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
import org.netbeans.spi.project.support.ant.ProjectGenerator;
import org.netbeans.spi.project.support.ant.PropertyUtils;
import org.netbeans.spi.project.support.ant.ReferenceHelper;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.modules.SpecificationVersion;
import org.openide.util.Exceptions;
import org.openide.util.Mutex;
import org.openide.util.MutexException;
import org.openide.util.NbBundle;
import org.openide.util.Parameters;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Creates a JavaFX Project from scratch according to some initial configuration.
 * 
 * TODO use J2SEProjectBuider instead
 */
public class JFXProjectGenerator {

    private static final String METRICS_LOGGER = "org.netbeans.ui.metrics.projects"; //NOI18N
    private static final String JFX_METRICS_LOGGER = "org.netbeans.ui.metrics.jfx";  //NOI18N
    private static final String PROJECT_TYPE = "org.netbeans.modules.javafx2.project.JFXProject";   //NOI18N
    
    enum Action {
        CREATE("USG_PROJECT_CREATE", "USG_PROJECT_CREATE_JFX"),   //NOI18N
        OPEN("USG_PROJECT_OPEN", "USG_PROJECT_OPEN_JFX"),       //NOI18N
        CLOSE("USG_PROJECT_CLOSE", "USG_PROJECT_CLOSE_JFX"),     //NOI18N
        BUILD_NATIVE("USG_PROJECT_BUILD_NATIVE", "USG_PROJECT_BUILD_NATIVE_JFX");     //NOI18N
        
        private final String genericLogMessage;
        private final String specificLogMessage;
        
        private Action(
            @NonNull final String genericLogMessage,
            @NonNull final String specificLogMessage) {
            assert genericLogMessage != null;
            assert specificLogMessage != null;
            this.genericLogMessage = genericLogMessage;
            this.specificLogMessage = specificLogMessage;
        }
        
        @NonNull
        public String getGenericLogMessage() {
            return genericLogMessage;
        }
        
        @NonNull
        public String getSpecificLogMessage() {
            return specificLogMessage;
        }
    }

    private JFXProjectGenerator() {
    }

    /**
     * Create a new empty JavaFX project.
     * @param dir the top-level directory (need not yet exist but if it does it must be empty)
     * @param name the name for the project
     * @param librariesDefinition project relative or absolute OS path to libraries definition; can be null
     * @return the helper object permitting it to be further customized
     * @throws IOException in case something went wrong
     */
    public static AntProjectHelper createProject(final File dir, final String name, final String mainClass,
            final String fxmlName, final String manifestFile, final String librariesDefinition,
            final String platformName, final String preloader, final WizardType type) throws IOException {
        Parameters.notNull("dir", dir); //NOI18N
        Parameters.notNull("name", name);   //NOI18N
        
        final FileObject dirFO = FileUtil.createFolder(dir);
        // if manifestFile is null => it's TYPE_LIB
        final AntProjectHelper[] h = new AntProjectHelper[1];
        final FileObject[] srcFolder = new FileObject[1];
        dirFO.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
            @Override
            public void run() throws IOException {
                h[0] = createProject(dirFO, name, "src", "test", mainClass, manifestFile, //NOI18N
                        librariesDefinition, platformName, preloader, type);
                final Project p = ProjectManager.getDefault().findProject(dirFO);
                JFXProjectUtils.createJfxExtension(p, dirFO, type);
                ProjectManager.getDefault().saveProject(p);
                if(type != WizardType.SWING) {
                    JFXGeneratedFilesHelper.generateBuildScriptFromStylesheet(h[0],
                        GeneratedFilesHelper.BUILD_XML_PATH,
                        JFXProjectGenerator.class.getResource("resources/build.xsl")); //NOI18N
                }
                final ReferenceHelper refHelper = getReferenceHelper(p);
                try {
                    ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
                        @Override
                        public Void run() throws Exception {
                            copyRequiredLibraries(h[0], refHelper);
                            return null;
                        }
                    });
                } catch (MutexException ex) {
                    Exceptions.printStackTrace(ex.getException());
                }
                srcFolder[0] = dirFO.createFolder("src"); // NOI18N
            }
        });
        if (srcFolder[0] != null) {
            createFiles(mainClass, fxmlName, srcFolder[0], type);
        }
        return h[0];
    }
   
    private static ReferenceHelper getReferenceHelper(Project p) {
        try {
            return (ReferenceHelper) p.getClass().getMethod("getReferenceHelper").invoke(p); // NOI18N
        } catch (Exception e) {
            return null;
        }
    }

    static AntProjectHelper createProject(final File dir, final String name,
            final File[] sourceFolders, final File[] testFolders,
            final String manifestFile, final String librariesDefinition,
            final String buildXmlName, final String platformName,
            final String preloader, final WizardType type) throws IOException {
        Parameters.notNull("dir", dir); //NOI18N
        Parameters.notNull("name", name);   //NOI8N
        Parameters.notNull("sourceFolders", sourceFolders); //NOI18N
        Parameters.notNull("testFolders", testFolders); //NOI18N
        
        final FileObject dirFO = FileUtil.createFolder(dir);
        final AntProjectHelper[] h = new AntProjectHelper[1];
        // this constructor creates only java application type
        dirFO.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
            @Override
            public void run() throws IOException {
                h[0] = createProject(dirFO, name, null, null, null, manifestFile,
                        librariesDefinition, platformName, preloader, type);
                final Project p = ProjectManager.getDefault().findProject(dirFO);
                final ReferenceHelper refHelper = getReferenceHelper(p);
                try {
                    ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
                        @Override
                        public Void run() throws Exception {
                            Element data = h[0].getPrimaryConfigurationData(true);
                            Document doc = data.getOwnerDocument();
                            NodeList nl = data.getElementsByTagNameNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "source-roots"); // NOI18N
                            assert nl.getLength() == 1;
                            Element sourceRoots = (Element) nl.item(0);
                            nl = data.getElementsByTagNameNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "test-roots");  //NOI18N
                            assert nl.getLength() == 1;
                            Element testRoots = (Element) nl.item(0);
                            for (int i = 0; i < sourceFolders.length; i++) {
                                String propName;
                                if (i == 0) {
                                    //Name the first src root src.dir to be compatible with NB 4.0
                                    propName = "src.dir";       //NOI18N
                                } else {
                                    String name = sourceFolders[i].getName();
                                    propName = name + ".dir";    //NOI18N
                                }

                                int rootIndex = 1;
                                EditableProperties props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
                                while (props.containsKey(propName)) {
                                    rootIndex++;
                                    propName = name + rootIndex + ".dir";   //NOI18N
                                }
                                String srcReference = refHelper.createForeignFileReference(sourceFolders[i], JavaProjectConstants.SOURCES_TYPE_JAVA);
                                Element root = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root");   //NOI18N
                                root.setAttribute("id", propName);   //NOI18N
                                sourceRoots.appendChild(root);
                                props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
                                props.put(propName, srcReference);
                                h[0].putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props); // #47609
                            }
                            for (int i = 0; i < testFolders.length; i++) {
                                if (!testFolders[i].exists()) {
                                    testFolders[i].mkdirs();
                                }
                                String propName;
                                if (i == 0) {
                                    //Name the first test root test.src.dir to be compatible with NB 4.0
                                    propName = "test.src.dir";  //NOI18N
                                } else {
                                    String name = testFolders[i].getName();
                                    propName = "test." + name + ".dir"; // NOI18N
                                }
                                int rootIndex = 1;
                                EditableProperties props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
                                while (props.containsKey(propName)) {
                                    rootIndex++;
                                    propName = "test." + name + rootIndex + ".dir"; // NOI18N
                                }
                                String testReference = refHelper.createForeignFileReference(testFolders[i], JavaProjectConstants.SOURCES_TYPE_JAVA);
                                Element root = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root"); // NOI18N
                                root.setAttribute("id", propName); // NOI18N
                                testRoots.appendChild(root);
                                props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH); // #47609
                                props.put(propName, testReference);
                                h[0].putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
                            }
                            h[0].putPrimaryConfigurationData(data, true);
                            if (buildXmlName != null) {
                                final EditableProperties props = h[0].getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
                                props.put(JFXProjectProperties.BUILD_SCRIPT, buildXmlName);
                                h[0].putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, props);
                            }
                            JFXProjectUtils.createJfxExtension(p, dirFO, type);
                            ProjectManager.getDefault().saveProject(p);
                            if(type != WizardType.SWING) {
                                JFXGeneratedFilesHelper.generateBuildScriptFromStylesheet(h[0],
                                    GeneratedFilesHelper.BUILD_XML_PATH,
                                    JFXProjectGenerator.class.getResource("resources/build.xsl")); //NOI18N
                            }
                            copyRequiredLibraries(h[0], refHelper);
                            ProjectUtils.getSources(p).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
                            return null;
                        }
                    });
                } catch (MutexException me) {
                    ErrorManager.getDefault().notify(me);
                }
            }
        });
        return h[0];
    }

    static AntProjectHelper createPreloaderProject(final File dir, final String name,
            final String librariesDefinition, final String platformName, final String preloaderClassName) throws IOException {
        Parameters.notNull("dir", dir); //NOI18N
        Parameters.notNull("name", name);   //NOI18N

        final FileObject dirFO = FileUtil.createFolder(dir);
        final AntProjectHelper[] h = new AntProjectHelper[1];
        final FileObject[] srcFolder = new FileObject[1];
        dirFO.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
            @Override
            public void run() throws IOException {
//                h[0] = createProject(dirFO, name, "src", "test", preloaderClassName, // NOI18N
//                        JavaFXProjectWizardIterator.MANIFEST_FILE, librariesDefinition,
//                        platformName, null, WizardType.PRELOADER);
                h[0] = createProject(dirFO, name, "src", "test", preloaderClassName, // NOI18N
                        JavaFXProjectWizardIterator.MANIFEST_FILE, librariesDefinition,
                        platformName, null, WizardType.PRELOADER);
                
                final Project p = ProjectManager.getDefault().findProject(dirFO);
                JFXProjectUtils.createJfxExtension(p, dirFO, WizardType.PRELOADER);
                ProjectManager.getDefault().saveProject(p);
                JFXGeneratedFilesHelper.generateBuildScriptFromStylesheet(h[0],
                    GeneratedFilesHelper.BUILD_XML_PATH,
                    JFXProjectGenerator.class.getResource("resources/build.xsl")); //NOI18N
                final ReferenceHelper refHelper = getReferenceHelper(p);
                try {
                    ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {
                        @Override
                        public Void run() throws Exception {
                            copyRequiredLibraries(h[0], refHelper);
                            return null;
                        }
                    });
                } catch (MutexException ex) {
                    Exceptions.printStackTrace(ex.getException());
                }                
                srcFolder[0] = dirFO.createFolder("src"); // NOI18N
            }
        });
        if (srcFolder[0] != null && preloaderClassName != null) {
            createPreloaderClass(preloaderClassName, srcFolder[0]);
        }
        JavaFXProjectWizardIterator.createManifest(FileUtil.toFileObject(dir), true);

        return h[0];
    }

    private static AntProjectHelper createProject(FileObject dirFO, String name,
            String srcRoot, String testRoot, String mainClass, String manifestFile,
            String librariesDefinition, String platformName, String preloader,
            WizardType type) throws IOException {
        
        AntProjectHelper h = ProjectGenerator.createProject(dirFO, J2SEProjectType.TYPE, librariesDefinition);
        Element data = h.getPrimaryConfigurationData(true);
        Document doc = data.getOwnerDocument();
        Element nameEl = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); // NOI18N
        nameEl.appendChild(doc.createTextNode(name));
        data.appendChild(nameEl);
        if (!isDefaultPlatform(platformName)) {
            final Element explicitPlatformEl = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "explicit-platform"); //NOI18N
            explicitPlatformEl.setAttribute("explicit-source-supported", "true");   //NOI18N
            data.appendChild(explicitPlatformEl);
        }
        
        EditableProperties ep = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
        Element sourceRoots = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "source-roots");  //NOI18N
        if (srcRoot != null) {
            Element root = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root");   //NOI18N
            root.setAttribute("id", "src.dir");   //NOI18N
            sourceRoots.appendChild(root);
            ep.setProperty("src.dir", srcRoot); // NOI18N
        }
        data.appendChild(sourceRoots);
        Element testRoots = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "test-roots");  //NOI18N
        if (testRoot != null) {
            Element root = doc.createElementNS(J2SEProjectType.PROJECT_CONFIGURATION_NAMESPACE, "root");   //NOI18N
            root.setAttribute("id", "test.src.dir");   //NOI18N
            testRoots.appendChild(root);
            ep.setProperty("test.src.dir", testRoot); // NOI18N
        }
        data.appendChild(testRoots);
        h.putPrimaryConfigurationData(data, true);
        
        // ===========================
        //   JavaFX specific stuff
        // ===========================
        JFXProjectUtils.initializeJavaFXProperties(ep, type, platformName, mainClass, preloader);
                
        // ===========================
        //     J2SE Project stuff
        // ===========================
        ep.setProperty(ProjectProperties.ANNOTATION_PROCESSING_ENABLED, "true"); // NOI18N
        ep.setProperty(ProjectProperties.ANNOTATION_PROCESSING_ENABLED_IN_EDITOR, "false"); // NOI18N
        ep.setProperty(ProjectProperties.ANNOTATION_PROCESSING_RUN_ALL_PROCESSORS, "true"); // NOI18N
        ep.setProperty(ProjectProperties.ANNOTATION_PROCESSING_PROCESSORS_LIST, ""); // NOI18N
        ep.setProperty(ProjectProperties.ANNOTATION_PROCESSING_SOURCE_OUTPUT, "${build.generated.sources.dir}/ap-source-output"); // NOI18N
        ep.setProperty(ProjectProperties.ANNOTATION_PROCESSING_PROCESSOR_OPTIONS, ""); // NOI18N
        
        ep.setProperty("dist.dir", "dist"); // NOI18N
        ep.setComment("dist.dir", new String[]{"# " + NbBundle.getMessage(JFXProjectGenerator.class, "COMMENT_dist.dir")}, false); // NOI18N
        ep.setProperty("dist.jar", "${dist.dir}/" + validatePropertyValue(name) + ".jar"); // NOI18N
        ep.setProperty("application.vendor", System.getProperty("user.name", "User Name")); //NOI18N
        ep.setProperty("application.title", name); // NOI18N
        
        ep.setProperty(ProjectProperties.JAVAC_PROCESSORPATH, new String[]{"${javac.classpath}"}); // NOI18N
        ep.setProperty("javac.test.processorpath", new String[]{"${javac.test.classpath}"}); // NOI18N
        ep.setProperty("build.sysclasspath", "ignore"); // NOI18N
        ep.setComment("build.sysclasspath", new String[]{"# " + NbBundle.getMessage(JFXProjectGenerator.class, "COMMENT_build.sysclasspath")}, false); // NOI18N
        ep.setProperty(ProjectProperties.RUN_CLASSPATH, new String[]{ // NOI18N
                    // note that dist.jar needs to be first to prevent mixups in case of multiple dependent FX projects
                    "${dist.jar}:", // NOI18N
                    "${javac.classpath}:", // NOI18N
                    "${build.classes.dir}" // NOI18N
                });
        ep.setProperty("debug.classpath", new String[]{ // NOI18N
                    "${run.classpath}", // NOI18N
                });
        ep.setComment("debug.classpath", new String[]{ // NOI18N
                    "# " + NbBundle.getMessage(JFXProjectGenerator.class, "COMMENT_debug.transport"), // NOI18N
                    "#debug.transport=dt_socket" // NOI18N
                }, false);
        ep.setProperty("jar.compress", "false"); // NOI18N

        ep.setProperty("javac.compilerargs", ""); // NOI18N
        ep.setComment("javac.compilerargs", new String[]{ // NOI18N
                    "# " + NbBundle.getMessage(JFXProjectGenerator.class, "COMMENT_javac.compilerargs"), // NOI18N
                }, false);
        SpecificationVersion sourceLevel = getPlatformSourceLevel(platformName);
        ep.setProperty("javac.source", sourceLevel.toString()); // NOI18N
        ep.setProperty("javac.target", sourceLevel.toString()); // NOI18N
        ep.setProperty("javac.deprecation", "false"); // NOI18N
        ep.setProperty(ProjectProperties.JAVAC_TEST_CLASSPATH, new String[]{ // NOI18N
                    "${javac.classpath}:", // NOI18N
                    "${build.classes.dir}", // NOI18N
                });
        ep.setProperty(ProjectProperties.RUN_TEST_CLASSPATH, new String[]{ // NOI18N
                    "${javac.test.classpath}:", // NOI18N
                    "${build.test.classes.dir}", // NOI18N
                });
        ep.setProperty("debug.test.classpath", new String[]{ // NOI18N
                    "${run.test.classpath}", // NOI18N
                });

        ep.setProperty("build.generated.dir", "${build.dir}/generated"); // NOI18N
        ep.setProperty("meta.inf.dir", "${src.dir}/META-INF"); // NOI18N

        ep.setProperty(ProjectProperties.BUILD_DIR, "build"); // NOI18N
        ep.setComment(ProjectProperties.BUILD_DIR, new String[]{"# " + NbBundle.getMessage(JFXProjectGenerator.class, "COMMENT_build.dir")}, false); // NOI18N
        ep.setProperty(ProjectProperties.BUILD_CLASSES_DIR, "${build.dir}/classes"); // NOI18N
        ep.setProperty("build.generated.sources.dir", "${build.dir}/generated-sources"); // NOI18N
        ep.setProperty("build.test.classes.dir", "${build.dir}/test/classes"); // NOI18N
        ep.setProperty("build.test.results.dir", "${build.dir}/test/results"); // NOI18N
        ep.setProperty("build.classes.excludes", "**/*.java,**/*.form"); // NOI18N
        ep.setProperty("dist.javadoc.dir", "${dist.dir}/javadoc"); // NOI18N
        ep.setProperty(JFXProjectProperties.PLATFORM_ACTIVE, platformName); // NOI18N

        ep.setProperty(JFXProjectProperties.JAVADOC_PRIVATE, "false"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_NO_TREE, "false"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_USE, "true"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_NO_NAVBAR, "false"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_NO_INDEX, "false"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_SPLIT_INDEX, "true"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_AUTHOR, "false"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_VERSION, "false"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_WINDOW_TITLE, ""); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_ENCODING, "${" + JFXProjectProperties.SOURCE_ENCODING + "}"); // NOI18N
        ep.setProperty(JFXProjectProperties.JAVADOC_ADDITIONALPARAM, ""); // NOI18N
        Charset enc = FileEncodingQuery.getDefaultEncoding();
        ep.setProperty(JFXProjectProperties.SOURCE_ENCODING, enc.name());
        if (manifestFile != null) {
            ep.setProperty("manifest.file", manifestFile); // NOI18N
        }
        h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
        Map<String,String> browserInfo = JFXProjectUtils.getDefaultBrowserInfo();
        ep = h.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
        ep.setProperty(JFXProjectProperties.JAVAFX_ENDORSED_ANT_CLASSPATH, "."); // NOI18N
        ep.setComment(JFXProjectProperties.JAVAFX_ENDORSED_ANT_CLASSPATH, new String[]{"# " + NbBundle.getMessage(JFXProjectGenerator.class, "COMMENT_endorsed_ant_classpath")}, false); // NOI18N
        if(browserInfo != null && !browserInfo.isEmpty()) {
            for(Map.Entry<String,String> entry : browserInfo.entrySet()) {
                ep.setProperty(JFXProjectProperties.RUN_IN_BROWSER, entry.getKey());
                ep.setProperty(JFXProjectProperties.RUN_IN_BROWSER_PATH, entry.getValue());
                break;
            }
        }
        h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
        JFXProjectUtils.updateDefaultRunAsConfigFile(dirFO, JFXProjectProperties.RunAsType.ASWEBSTART, false);
        JFXProjectUtils.updateDefaultRunAsConfigFile(dirFO, JFXProjectProperties.RunAsType.INBROWSER, false);
        logUsage(Action.CREATE);
        return h;
    }

    /**
     * Logs project specific usage.
     * See: http://wiki.netbeans.org/UsageLoggingSpecification
     * Todo: Should log also J2SE project usage? The JFX project is de facto J2SE project,
     * most of this class should be replaced by J2SEProjectBuider.
     */
    static void logUsage(@NonNull Action action) {
        assert action != null;
        Logger logger = Logger.getLogger(JFXProjectGenerator.METRICS_LOGGER);
        LogRecord logRecord = new LogRecord(Level.INFO, action.getGenericLogMessage());
        logRecord.setLoggerName(logger.getName());
        logRecord.setParameters(new Object[]{
            PROJECT_TYPE
        });
        logger.log(logRecord);
        
        logger = Logger.getLogger(JFXProjectGenerator.JFX_METRICS_LOGGER);
        logRecord = new LogRecord(Level.INFO, action.getSpecificLogMessage());
        logRecord.setLoggerName(logger.getName());
        logger.log(logRecord);
    }

    private static boolean isDefaultPlatform(@NonNull final String platformName) {
        Parameters.notNull("platformName", platformName);   //NOI18N
        return platformName.equals(JavaPlatform.getDefault().getProperties().get("platform.ant.name")); //NOI18N
    }

    private static void copyRequiredLibraries(AntProjectHelper h, ReferenceHelper rh) throws IOException {
        if (!h.isSharableProject()) {
            return;
        }
        if (rh.getProjectLibraryManager().getLibrary("junit") == null // NOI18N
                && LibraryManager.getDefault().getLibrary("junit") != null) { // NOI18N
            rh.copyLibrary(LibraryManager.getDefault().getLibrary("junit")); // NOI18N
        }
        if (rh.getProjectLibraryManager().getLibrary("junit_4") == null // NOI18N
                && LibraryManager.getDefault().getLibrary("junit_4") != null) { // NOI18N
            rh.copyLibrary(LibraryManager.getDefault().getLibrary("junit_4")); // NOI18N
        }
        if (rh.getProjectLibraryManager().getLibrary("CopyLibs") == null // NOI18N
                && LibraryManager.getDefault().getLibrary("CopyLibs") != null) { // NOI18N
            rh.copyLibrary(LibraryManager.getDefault().getLibrary("CopyLibs")); // NOI18N
        }
        if (rh.getProjectLibraryManager().getLibrary("JavaFX2Runtime") == null // NOI18N
                && LibraryManager.getDefault().getLibrary("JavaFX2Runtime") != null) { // NOI18N
            File mainPropertiesFile = h.resolveFile(h.getLibrariesLocation());
            referenceLibrary(LibraryManager.getDefault().getLibrary("JavaFX2Runtime"), mainPropertiesFile.toURI().toURL(), true); //NOI18N

        }
    }

    /** for jar uri this method returns path wihtin jar or null*/
    private static String getJarFolder(URI uri) {
        String u = uri.toString();
        int index = u.indexOf("!/"); //NOI18N
        if (index != -1 && index + 2 < u.length()) {
            return u.substring(index + 2);
        }
        return null;
    }

    /** append path to given jar root uri */
    private static URI appendJarFolder(URI u, String jarFolder) {
        try {
            if (u.isAbsolute()) {
                return new URI("jar:" + u.toString() + "!/" + (jarFolder == null ? "" : jarFolder.replace('\\', '/'))); // NOI18N
            } else {
                return new URI(u.toString() + "!/" + (jarFolder == null ? "" : jarFolder.replace('\\', '/'))); // NOI18N
            }
        } catch (URISyntaxException e) {
            throw new AssertionError(e);
        }
    }

    private static Library referenceLibrary(final Library lib, final URL location,
            final boolean generateLibraryUniqueName) throws IOException {
        final File libBaseFolder = new File(URI.create(location.toExternalForm())).getParentFile();
        final Map<String, List<URI>> content = new HashMap<String, List<URI>>();
        String[] volumes = LibrariesSupport.getLibraryTypeProvider(lib.getType()).getSupportedVolumeTypes();
        for (String volume : volumes) {
            List<URI> volumeContent = new ArrayList<URI>();
            for (URL origlibEntry : lib.getContent(volume)) {
                URL libEntry = origlibEntry;
                String jarFolder = null;
                if ("jar".equals(libEntry.getProtocol())) { // NOI18N
                    jarFolder = getJarFolder(URI.create(libEntry.toExternalForm()));
                    libEntry = FileUtil.getArchiveFile(libEntry);
                }
                FileObject libEntryFO = URLMapper.findFileObject(libEntry);
                if (libEntryFO == null) {
                    if (!"file".equals(libEntry.getProtocol()) && // NOI18N
                            !"nbinst".equals(libEntry.getProtocol())) { // NOI18N
                        Logger.getLogger(JFXProjectGenerator.class.getName()).log(Level.INFO,
                                "referenceLibrary is ignoring entry {0}", libEntry); // NOI18N
                        //this is probably exclusively urls to maven poms.
                        continue;
                    } else {
                        Logger.getLogger(JFXProjectGenerator.class.getName()).log(Level.WARNING,
                                "Library ''{0}'' contains entry ({1}) which does not exist. " // NOI18N
                                + "This entry is ignored and will not be refernced from sharable " // NOI18N
                                + "libraries.", new Object[]{lib.getDisplayName(), libEntry}); // NOI18N
                        continue;
                    }
                }
                URI u;
                String name = PropertyUtils.relativizeFile(libBaseFolder, FileUtil.toFile(libEntryFO));
                if (name == null) { // #198955
                    Logger.getLogger(JFXProjectGenerator.class.getName()).log(Level.WARNING,
                            "Can not relativize file: {0}", libEntryFO.getPath()); // NOI18N
                    continue;
                }
                u = LibrariesSupport.convertFilePathToURI(name);
                if (FileUtil.isArchiveFile(libEntryFO)) {
                    u = appendJarFolder(u, jarFolder);
                }
                volumeContent.add(u);
            }
            content.put(volume, volumeContent);
        }
        final LibraryManager man = LibraryManager.forLocation(location);
        try {
            return ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Library>() {
                @Override
                public Library run() throws IOException {
                    String name = lib.getName();
                    if (generateLibraryUniqueName) {
                        int index = 2;
                        while (man.getLibrary(name) != null) {
                            name = lib.getName() + "-" + index;
                            index++;
                        }
                    }
                    return man.createURILibrary(lib.getType(), name, content);
                }
            });
        } catch (MutexException ex) {
            throw (IOException) ex.getException();
        }
    }

    private static void createFiles(String mainClassName, String fxmlName, FileObject srcFolder, WizardType type) throws IOException {
        DataFolder pDf = DataFolder.findFolder(srcFolder);
        if(mainClassName != null && mainClassName.length() > 0)
        {
            int lastDotIdx = mainClassName.lastIndexOf('.'); // NOI18N
            String mName, pName;
            if (lastDotIdx == -1) {
                mName = mainClassName.trim();
                pName = null;
            } else {
                mName = mainClassName.substring(lastDotIdx + 1).trim();
                pName = mainClassName.substring(0, lastDotIdx).trim();
            }

            if (mName.length() > 0) {
                Map<String, String> params = null;
                FileObject template = null;
                switch (type) {
                    case APPLICATION:
                        template = FileUtil.getConfigFile("Templates/javafx/FXMain.java"); // NOI18N
                        break;
                    case PRELOADER:
                        template = FileUtil.getConfigFile("Templates/javafx/FXPreloader.java"); // NOI18N
                        break;
                    case SWING:
                        template = FileUtil.getConfigFile("Templates/javafx/FXSwingMain.java"); // NOI18N
                        break;
                    case FXML:
                        template = FileUtil.getConfigFile("Templates/javafx/FXML.java"); // NOI18N
                        params = new HashMap<String, String>(1);
                        params.put("fxmlname", fxmlName); // NOI18N
                }

                if (template == null) {
                    return; // Don't know the template
                }

                DataObject mt = DataObject.find(template);
                if (pName != null) {
                    String fName = pName.replace('.', '/'); // NOI18N
                    FileObject pkgFolder = FileUtil.createFolder(srcFolder, fName);
                    pDf = DataFolder.findFolder(pkgFolder);
                }
                if (params != null) {
                    mt.createFromTemplate(pDf, mName, params);
                } else {
                    mt.createFromTemplate(pDf, mName);
                }
            }
        }
        if (type == WizardType.FXML) {
            FileObject xmlTemplate = FileUtil.getConfigFile("Templates/javafx/NewProjectFXML.fxml"); // NOI18N
            if (xmlTemplate == null) {
                return; // Don't know the template
            }
            Map<String, String> params = new HashMap<String, String>(1);
            params.put("postfix", NbBundle.getMessage(ConfigureFXMLControllerPanelVisual.class, "TXT_FileNameControllerPostfix")); // NOI18N
            DataObject dXMLTemplate = DataObject.find(xmlTemplate);
            dXMLTemplate.createFromTemplate(pDf, fxmlName, params);

            FileObject javaTemplate = FileUtil.getConfigFile("Templates/javafx/FXML2.java"); // NOI18N
            if (javaTemplate == null) {
                return; // Don't know the template
            }
            DataObject dJavaTemplate = DataObject.find(javaTemplate);
            dJavaTemplate.createFromTemplate(pDf, fxmlName + NbBundle.getMessage(ConfigureFXMLControllerPanelVisual.class, "TXT_FileNameControllerPostfix")); //NOI18N
        }
    }
    
    private static void createPreloaderClass(String preloaderClassName, FileObject srcFolder) throws IOException {
        int lastDotIdx = preloaderClassName.lastIndexOf('.'); // NOI18N
        String mName, pName;
        if (lastDotIdx == -1) {
            mName = preloaderClassName.trim();
            pName = null;
        } else {
            mName = preloaderClassName.substring(lastDotIdx + 1).trim();
            pName = preloaderClassName.substring(0, lastDotIdx).trim();
        }

        if (mName.length() == 0) {
            return;
        }

        FileObject template = FileUtil.getConfigFile("Templates/javafx/FXPreloader.java"); // NOI18N
        if (template == null) {
            return; // Don't know the template
        }

        DataObject mt = DataObject.find(template);
        FileObject pkgFolder = srcFolder;
        if (pName != null) {
            String fName = pName.replace('.', '/'); // NOI18N
            pkgFolder = FileUtil.createFolder(srcFolder, fName);
        }
        DataFolder pDf = DataFolder.findFolder(pkgFolder);
        mt.createFromTemplate(pDf, mName);
    }
    
    private static SpecificationVersion getPlatformSourceLevel(String fxPlatformName) {
        JavaPlatform platform = null;
        JavaPlatform[] platforms = JavaPlatformManager.getDefault().getInstalledPlatforms();
        for (JavaPlatform javaPlatform : platforms) {
            String platformName = javaPlatform.getProperties().get(JavaFXPlatformUtils.PLATFORM_ANT_NAME);
            if (JFXProjectProperties.isEqual(platformName, fxPlatformName)) {
                platform = javaPlatform;
                break;
            }
        }
        if(platform == null) {
            // default JavaFX2 specification version is 1.6
            return new SpecificationVersion("1.6"); // NOI18N
        }
        SpecificationVersion v = platform.getSpecification().getVersion();
        return v;
    }

    //------------ Used by unit tests -------------------
    private static SpecificationVersion defaultSourceLevel;

    private static SpecificationVersion getDefaultSourceLevel() {
        if (defaultSourceLevel != null) {
            return defaultSourceLevel;
        } else {
            JavaPlatform defaultPlatform = JavaPlatformManager.getDefault().getDefaultPlatform();
            SpecificationVersion v = defaultPlatform.getSpecification().getVersion();
            return v;
        }
    }
    private static final Pattern INVALID_NAME = Pattern.compile("[$/\\\\\\p{Cntrl}]");  //NOI18N

    private static String validatePropertyValue(String value) {
        final Matcher m = INVALID_NAME.matcher(value);
        if (m.find()) {
            value = m.replaceAll("_");  //NOI18N
        }
        return value;
    }

    /**
     * Unit test only method. Sets the default source level for tests
     * where the default platform is not available.
     * @param version the default source level set to project when it is created
     *
     */
    public static void setDefaultSourceLevel(SpecificationVersion version) {
        defaultSourceLevel = version;
    }
}
