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

import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.modules.web.common.api.UsageLogger;
import org.netbeans.spi.project.AuxiliaryConfiguration;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Persistence of libraries.
 *
 * @author Jan Stola
 */
public final class LibraryPersistence {
    /** Name-space used to store the library information. */
    private static final String NAMESPACE_URI = "http://www.netbeans.org/ns/cdnjs-libraries/1"; // NOI18N
    /** Name of the root element. */
    private static final String ELEMENT_LIBRARIES = "libraries"; // NOI18N
    /** Name of the element holding information about one library. */
    private static final String ELEMENT_LIBRARY = "library"; // NOI18N
    /** Name of the element holding information about one library file. */
    private static final String ELEMENT_FILE = "file"; // NOI18N
    /** Name of the attribute storing the name of the library. */
    private static final String ATTR_LIBRARY_NAME = "name"; // NOI18N
    /** Name of the attribute storing the name of the version of the library. */
    private static final String ATTR_VERSION_NAME = "version"; // NOI18N
    /** Name of the attribute storing the local path (relative to the project's folder) to the library file. */
    private static final String ATTR_FILE_LOCAL_PATH = "localPath"; // NOI18N
    /** Name of the attribute storing the relative path to the library file as specified by CDNJS meta-data. */
    private static final String ATTR_FILE_PATH = "path"; // NOI18N
    /** The default instance of this class. */
    private static final LibraryPersistence DEFAULT = new LibraryPersistence();

    private final LibraryListener.Support libraryListenerSupport = new LibraryListener.Support();

    /**
     * Creates a new {@code LibraryPersistence}.
     */
    LibraryPersistence() {
    }

    /**
     * Returns the default instance of this class.
     *
     * @return default instance of this class.
     */
    public static LibraryPersistence getDefault() {
        return DEFAULT;
    }

    /**
     * Adds a {@link LibraryListener} to the listener list. The same
     * listener object may be added more than once, and will be called
     * as many times as it is added. If {@code listener} is {@code null},
     * no exception is thrown and no action is taken.
     * @param listener the {@link LibraryListener} to be added, can be {@code null}
     */
    public void addLibraryListener(@NullAllowed LibraryListener listener) {
        libraryListenerSupport.addLibraryListener(listener);
    }

    /**
     * Removes a {@link LibraryListener} from the listener list.
     * If {@code listener} was added more than once,
     * it will be notified one less time after being removed.
     * If {@code listener} is {@code null}, or was never added, no exception is
     * thrown and no action is taken.
     * @param listener the {@link LibraryListener} to be removed, can be {@code null}
     */
    public void removeLibraryListener(@NullAllowed LibraryListener listener) {
        libraryListenerSupport.removeLibraryListener(listener);
    }

    /**
     * Loads library information for the given project.
     *
     * @param project project whose library information should be loaded.
     * @return library information for the given project.
     */
    public Library.Version[] loadLibraries(Project project) {
        Library.Version[] libraries;
        AuxiliaryConfiguration config = ProjectUtils.getAuxiliaryConfiguration(project);
        Element element = config.getConfigurationFragment(ELEMENT_LIBRARIES, NAMESPACE_URI, true);
        if (element == null) {
            libraries = new Library.Version[0];
        } else{
            NodeList libraryList = element.getElementsByTagNameNS(NAMESPACE_URI, ELEMENT_LIBRARY);
            libraries = new Library.Version[libraryList.getLength()];
            for (int i=0; i<libraryList.getLength(); i++) {
                Element libraryElement = (Element)libraryList.item(i);
                libraries[i] = loadLibrary(libraryElement);
            }
        }
        return libraries;
    }

    /**
     * Loads/parses information about one library from the given DOM element.
     *
     * @param libraryElement element to load information from.
     * @return library version corresponding to the given DOM element.
     */
    @org.netbeans.api.annotations.common.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
            justification = "Not sure about it, really (not my code)")
    private Library.Version loadLibrary(Element libraryElement) {
        String libraryName = libraryElement.getAttribute(ATTR_LIBRARY_NAME);
        String versionName = libraryElement.getAttribute(ATTR_VERSION_NAME);
        Library library = new Library();
        library.setName(libraryName);
        Library.Version version = new Library.Version(library, true);
        version.setName(versionName);
        library.setVersions(new Library.Version[] { version });
        NodeList fileList = libraryElement.getElementsByTagNameNS(NAMESPACE_URI, ELEMENT_FILE);
        String[] files = new String[fileList.getLength()];
        String[] localFiles = new String[fileList.getLength()];
        for (int i=0; i<fileList.getLength(); i++) {
            Element fileElement = (Element)fileList.item(i);
            String path = fileElement.getAttribute(ATTR_FILE_PATH);
            String localPath = fileElement.getAttribute(ATTR_FILE_LOCAL_PATH);
            files[i] = path;
            localFiles[i] = (localPath == null) ? path : localPath;
        }
        version.setFileInfo(files, localFiles);
        return version;
    }

    /**
     * Stores the information about libraries used by the given project.
     *
     * @param project project whose library information should be stored.
     * @param libraries libraries used by the project.
     */
    void storeLibraries(Project project, Library.Version[] libraries) throws IOException {
        Arrays.sort(libraries, new LibraryVersionComparator());
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            Element librariesElement = document.createElementNS(NAMESPACE_URI, ELEMENT_LIBRARIES);
            for (Library.Version library : libraries) {
                Element libraryElement = document.createElementNS(NAMESPACE_URI, ELEMENT_LIBRARY);
                String libraryName = library.getLibrary().getName();
                libraryElement.setAttribute(ATTR_LIBRARY_NAME, libraryName);
                String versionName = library.getName();
                libraryElement.setAttribute(ATTR_VERSION_NAME, versionName);
                String[] files = library.getFiles();
                String[] localFiles = library.getLocalFiles();
                for (int i=0; i<files.length; i++) {
                    Element fileElement = document.createElementNS(NAMESPACE_URI, ELEMENT_FILE);
                    String path = files[i];
                    String localPath = localFiles[i];
                    fileElement.setAttribute(ATTR_FILE_PATH, path);
                    fileElement.setAttribute(ATTR_FILE_LOCAL_PATH, localPath);
                    libraryElement.appendChild(fileElement);
                }
                librariesElement.appendChild(libraryElement);
            }
            AuxiliaryConfiguration config = ProjectUtils.getAuxiliaryConfiguration(project);
            config.putConfigurationFragment(librariesElement, true);
            ProjectManager.getDefault().saveProject(project);

            logLibraryUsage(libraries);

            // fire event
            libraryListenerSupport.fireLibrariesChanged(project);
        } catch (ParserConfigurationException pcex) {
            Logger.getLogger(LibraryPersistence.class.getName()).log(Level.SEVERE,
                    "Unable to store library information!", pcex); // NOI18N
        }
    }

    /** Logger of CDNJS libraries usage. */
    private static final UsageLogger USAGE_LOGGER = new UsageLogger.Builder("org.netbeans.ui.metrics.javascript.cdnjs")  // NOI18N
            .firstMessageOnly(false)
            .create();

    /**
     * Logs the used libraries.
     *
     * @param libraries used libraries.
     */
    private static void logLibraryUsage(Library.Version[] libraries) {
        // ui usage
        USAGE_LOGGER.log(LibraryPersistence.class, "USG_CDNJS_LIBRARY_EDIT"); // NOI18N
        // libraries
        for (Library.Version library : libraries) {
            String version = library.getName();
            String name = library.getLibrary().getName();
            USAGE_LOGGER.log(LibraryPersistence.class, "USG_CDNJS_LIBRARY", name, version); // NOI18N
        }
    }

    /**
     * Comparator of {@code Library.Version}s.
     */
    @org.netbeans.api.annotations.common.SuppressWarnings(value = "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE",
            justification = "No need to be serializable")
    static class LibraryVersionComparator implements Comparator<Library.Version> {
        @Override
        public int compare(Library.Version o1, Library.Version o2) {
            String name1 = o1.getLibrary().getName();
            String name2 = o2.getLibrary().getName();
            return name1.compareTo(name2);
        }
    }

}
